mysql 8.0+ 必须使用 binlog_expire_logs_seconds,expire_logs_days 已废弃且默认值为0、设了也无效;需显式配置秒级参数并配合 flush logs 或重启触发清理,同时须确保其值大于最大从库延迟。

MySQL 8.0+ 必须用 binlog_expire_logs_seconds,expire_logs_days 已被弃用且可能被忽略。 直接设 expire_logs_days 在新版本里大概率不生效,磁盘照样爆。
为什么不能只依赖 expire_logs_days
MySQL 5.7 及更早版本靠 expire_logs_days 控制 binlog 过期,但 8.0 开始官方明确标记该参数为“deprecated”,实际行为是:即使你设了 expire_logs_days = 7,只要 binlog_expire_logs_seconds 是非零值(哪怕只是默认的 2592000,即 30 天),MySQL 就会优先按秒级参数判断,expire_logs_days 彻底失效。
常见错误现象:set global expire_logs_days = 3; 执行成功,show variables like 'expire_logs_days'; 显示 3,但日志就是不删——因为 binlog_expire_logs_seconds 还是默认 30 天,它赢了。
- MySQL 8.0.11+ 默认启用
binlog_expire_logs_seconds = 2592000(30 天) - 必须显式设为 0 才能“关闭”该参数,否则它永远压倒
expire_logs_days - 配置文件中同时写两个参数,启动时后者(秒级)生效,前者被静默忽略
正确设置 binlog_expire_logs_seconds 的步骤
分两步走:先清旧参数干扰,再设新参数。顺序错了就白忙。
- 执行
set global expire_logs_days = 0;—— 不是为了启用,而是为了“退场”,避免冲突 - 计算目标秒数,比如保留 7 天:7 × 24 × 60 × 60 =
604800 - 执行
set global binlog_expire_logs_seconds = 604800; - 立即验证:
show variables like 'binlog_expire_logs_seconds';确认值已更新
注意:这个设置是运行时生效的,无需重启 MySQL。但若希望永久生效,必须同步写入 /etc/my.cnf 的 [mysqld] 段:
binlog_expire_logs_seconds = 604800 expire_logs_days = 0
PURGE 不会等你设完才触发,得手动推一把
MySQL 不是实时扫描并删除过期 binlog 的。它只在两个时机检查:实例启动时 和 执行 flush logs 时。也就是说,你设完 binlog_expire_logs_seconds,旧日志不会立刻消失。
- 想马上清理,执行
flush logs;—— 它会滚动出一个新 binlog 文件,并顺手删掉所有过期文件 - 别用
reset master;替代,它会清空全部 binlog,包括从库还没读的,主从直接断裂 - 如果磁盘已告急,先
purge binary logs before '2026-04-07 00:00:00';快速腾空间,再设自动策略
主从环境里最容易被忽略的硬约束
自动清理只管“时间”,不管“从库进度”。如果你设了保留 7 天,但最慢的从库延迟了 8 天,它就会去读一个已被删掉的 binlog,报错 Could not find first log file name in binary log index file 或直接中断复制。
所以真实场景中,binlog_expire_logs_seconds 的值必须满足:
- 大于等于所有从库中最大的
Seconds_Behind_Master - 最好再加缓冲,比如最大延迟是 12 小时,那就设成 2 天(172800 秒)起步
- 定期用
show slave status\G查看各从库延迟,而不是只信配置值
自动清理不是设完就高枕无忧的事——它只负责“到点删”,不负责“删得安全”。真正的安全边界,永远在你的监控和对从库状态的掌握里。











