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_purgeON 时允许自动清理,为 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;

注意注意注意:这种在线设置只要满足下面两点,就会一直生效

  1. 数据库服务进程不重启(包括 systemctl restart mariadb/mysql、异常崩溃、机器重启)

  2. 没有人/脚本再把它改回别的值

一旦 数据库重启,它会按配置文件启动——如果配置文件里还是 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;

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐