MySQL/MariaDB Binlog 巡检清单:定位、评估、清理、验证一步到位
1、MySQL binlog 日志要不要定期清理?如何判断是否开启自动清理(按秒/按天)?
在 Oracle 里,大家对归档日志(archivelog)都比较敏感:
不清理,磁盘可能被打满;再严重一点,直接影响业务。
那 MySQL 呢?
答案是:也要关注。
MySQL 的二进制日志(binlog)如果开启后长期不清理,同样会持续增长,占用磁盘空间,最终可能引发写入异常、备份失败甚至业务风险。
这篇文章我把 MySQL binlog 清理的知识点、版本差异、巡检命令、结果判定规则 一次整理清楚。
2、什么是 MySQL binlog,为什么要关注清理?
binlog(Binary Log)记录了 MySQL 的数据变更相关事件,常用于:
-
主从复制(Replication)
-
基于时间点恢复(PITR)
-
部分审计/追溯场景
如果 binlog 开启,但没有设置自动过期清理,日志会持续堆积。
生产环境写入量一大,增长会很快。
重点:binlog 是“恢复能力”和“磁盘空间”之间的平衡点。
保留太短,恢复窗口不够;保留太长,磁盘压力变大。
3、先记住这几个关键变量(巡检核心)
MySQL binlog 自动清理,主要看这几个变量:
-
log_bin:binlog 是否开启 -
log_bin_basename/log_bin_index:binlog 路径(判断写在哪个分区) -
binlog_expire_logs_seconds:按秒设置过期时间(新参数) -
binlog_expire_logs_auto_purge:自动清理开关(新版本常见) -
expire_logs_days:按天设置过期时间(老参数)
MySQL 官方文档说明:
-
binlog_expire_logs_seconds用于设置 binlog 过期时间(单位秒),并且 binlog 文件会在启动或日志 flush 时触发自动清理;默认值在 MySQL 8.4 文档中为2592000(30 天)。 -
binlog_expire_logs_auto_purge为ON时允许自动清理,为OFF时会禁用自动清理;即使它是ON,如果binlog_expire_logs_seconds=0,自动清理也不会发生。 -
expire_logs_days在 MySQL 8.4 已被移除,官方建议改用binlog_expire_logs_seconds。
4、版本差异一定要搞清楚(这是最容易误判的地方)
4.1MySQL 8.0(很多生产还在用)
可能同时看到:
-
expire_logs_days(老参数) -
binlog_expire_logs_seconds(新参数) -
binlog_expire_logs_auto_purge(8.0.29+ 常见)
所以会出现一种经典场景:
-
binlog_expire_logs_seconds = 0 -
但
expire_logs_days = 7
这并不代表“没配置自动清理”,而是:
老参数还在生效,实际保留 7 天。
4.2MySQL 8.4(LTS)
expire_logs_days 已移除,尝试获取/设置会报错,官方明确要求改用 binlog_expire_logs_seconds。
另外,MySQL 8.4 文档说明二进制日志默认开启(log_bin=ON),与更早版本行为有差异。
5、MySQL binlog 巡检命令清单(可直接复制)
-- ================================
-- MySQL binlog 巡检命令清单(可直接复制)
-- 说明:
-- 1) 用于检查 binlog 是否开启、路径、自动清理(按秒/按天)、当前binlog状态与列表
-- 2) 不同版本存在差异:老版本查询 binlog_expire_logs_auto_purge 可能返回 Empty set;
-- MySQL 8.4 中 expire_logs_days 可能不存在/报错(已移除)
-- ================================
-- 1) binlog 是否开启(不启用的话后面很多项就没意义)
SHOW GLOBAL VARIABLES LIKE 'log_bin';
-- 2) binlog 路径(确认写入分区,方便结合 df -h 判断空间风险)
SHOW GLOBAL VARIABLES LIKE 'log_bin_basename';
SHOW GLOBAL VARIABLES LIKE 'log_bin_index';
-- 3) 自动清理开关(新版本常见;老版本可能 Empty set)
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_auto_purge';
-- 4) 自动清理时长(新参数:按秒)
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_seconds';
-- 5) 自动清理时长(旧参数:按天;MySQL 8.4 可能不存在/报错)
SHOW GLOBAL VARIABLES LIKE 'expire_logs_days';
-- 6) 当前 binlog 状态(当前正在写哪个)
SHOW MASTER STATUS;
-- 7) 当前 binlog 文件列表与大小(看规模/是否堆积)
SHOW BINARY LOGS;
-- 8) 一条SQL查全(快速汇总查看,可选;与上面1~7有重复)
SHOW GLOBAL VARIABLES
WHERE Variable_name IN (
'log_bin',
'log_bin_basename',
'log_bin_index',
'binlog_expire_logs_auto_purge',
'binlog_expire_logs_seconds',
'expire_logs_days'
);
6、在线开启自动过期
SET GLOBAL expire_logs_days = 3;
SHOW GLOBAL VARIABLES LIKE 'expire_logs_days';
SHOW BINARY LOGS;
看当前 binlog 堆了多少(决定要不要马上手动清)
SHOW BINARY LOGS;
SHOW MASTER STATUS;
注意注意注意:这种在线设置只要满足下面两点,就会一直生效:
-
数据库服务进程不重启(包括
systemctl restart mariadb/mysql、异常崩溃、机器重启) -
没有人/脚本再把它改回别的值
一旦 数据库重启,它会按配置文件启动——如果配置文件里还是 expire_logs_days=0,那就会回到 0。
除此之外可以一次性根治:写进配置文件(永久生效)
[mysqld]
expire_logs_days=2
但是这个方法有的版本需要重启数据库让它吃配置(这里很关键)
7、什么时候才需要手动清?
只有出现下面任一情况才建议手动清:
-
/data空间开始吃紧(比如 >80%) -
binlog 文件数量明显变多(几十上百个)
-
你明确要缩短恢复窗口(比如从 7 天改 3 天,希望立即生效)
清理前:
SHOW SLAVE STATUS\G -- 从库才有输出
SHOW PROCESSLIST; -- 主库有从库拉取会出现 Binlog Dump
清理命令:
SELECT NOW() AS now, DATE_SUB(NOW(), INTERVAL 3 DAY) AS cutoff;
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 3 DAY);
清理后:
SHOW BINARY LOGS;
SHOW MASTER STATUS;
SHOW WARNINGS;
更多推荐


所有评论(0)