mysql 8.0+ 必须设 binlog_expire_logs_seconds(如604800秒)并启用 binlog_expire_logs_auto_purge=on 才能自动清理,expire_logs_days 已废弃;设错版本、不重启、不触发 flush logs 或从库依赖未满足均会导致清理失效。

必须设,不设磁盘迟早被撑爆;但设了不生效、设错版本、设完不重启、设了却删不掉——这四类问题占了线上 binlog 清理失败的 90% 以上。
确认 MySQL 版本再选参数:5.7 和 8.0+ 完全不同
MySQL 5.7 只认 expire_logs_days,单位是“天”;MySQL 8.0.28+ 才真正支持 binlog_expire_logs_seconds(单位秒),且它优先级更高。旧版本设了也白设。
先查版本:SELECT VERSION();,别只看文档写法。比如你用的是 8.0.26,那 binlog_expire_logs_seconds 就无效,仍得靠 expire_logs_days。
常见错误:
- 在 5.7 上写
binlog_expire_logs_seconds = 604800,配置文件里加了也没用 - 在 8.0.28+ 上同时写
expire_logs_days = 7和binlog_expire_logs_seconds = 604800,后者生效但 MySQL 会报警告 - 误以为
SET GLOBAL binlog_expire_logs_seconds = ...重启后还有效——它不持久,必须写进配置文件或用SET PERSIST
配置写对 + 服务重启 + 最老 binlog 真超期 + 从库不依赖 = 四个条件缺一不可
自动清理不是“设完就跑”,而是满足全部四个条件才真正触发删除。少一个,SHOW BINARY LOGS 里就还堆着一堆“该删没删”的文件。
验证是否真生效:
- 查变量:
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';或SHOW VARIABLES LIKE 'expire_logs_days';,返回值不是 0 才算启用 - 查最老 binlog 时间:
SHOW BINARY LOGS;看第一个文件的File_size列没用,要看它的操作系统 mtime(用ls -lt /var/lib/mysql/mysql-bin.*确认) - 查从库依赖:
SHOW SLAVE STATUS\G看Relay_Master_Log_File是否还在SHOW BINARY LOGS列表里,且不是第一个 - 检查
binlog_expire_logs_auto_purge是否为ON(MySQL 8.0.29+ 新增开关,优先级最高,设成OFF就彻底禁用清理)
为什么 flush logs 后 binlog 还不删?清理时机不是实时的
MySQL 不是每小时扫一遍磁盘删文件,而是只在三个时刻检查并清理:MySQL 启动时、执行 FLUSH LOGS 时、或 binlog 文件大小达到 max_binlog_size 触发切换时。没有这些动作,哪怕过期一周也不会动。
所以在线调参后,必须手动触发一次清理:
- 先
SET GLOBAL expire_logs_days = 7;或SET GLOBAL binlog_expire_logs_seconds = 604800; - 再立刻执行
FLUSH LOGS;(注意:需要RELOAD权限) - 观察
SHOW BINARY LOGS;,最老的文件序号应跳变,超期文件消失
如果 FLUSH LOGS 后仍不删,大概率是:最老那个 binlog 文件还没超期(mtime 比设定时间新),或者从库还在读它。
云数据库要额外留意控制台保留策略
腾讯云、阿里云 RDS 的控制台里常有“本地 binlog 保留小时数”选项,它和你 MySQL 实例里的 expire_logs_days 是两套独立机制。控制台策略可能强制覆盖实例配置,甚至不允许你改 binlog_expire_logs_seconds。
排查方法:
- 在控制台确认是否开启了“自动清理 binlog”及具体小时数
- 对比控制台设置与实例内
SHOW VARIABLES输出,看哪个实际起效 - 云厂商有时会把 binlog 存在独立存储上,
SHOW BINARY LOGS显示的大小 ≠ 磁盘真实占用,得看控制台监控图表
真正麻烦的点在于:你以为自己配对了,其实云平台悄悄按它的规则在删——或者根本不删,只留个开关摆设。上线前务必在测试环境走通整条链路。











