MySQL 8.0.23+ 必须用 binlog_expire_logs_seconds 设置保留周期,设为0或未配置即失效;需三步验证:log_bin=ON、binlog_expire_logs_seconds>0、binlog_expire_logs_auto_purge=ON。

MySQL 8.0.23+ 必须用 binlog_expire_logs_seconds 配置 binlog 保留周期,设成 0 或不设就等于没配——磁盘爆满不是偶然,是默认策略失效的必然结果。
确认 binlog 是否真启用且过期策略生效
别只看配置文件写了什么,连上 MySQL 执行三行检查命令,否则可能“以为删了,其实全在”:
-
SHOW VARIABLES LIKE 'log_bin';—— 必须返回ON,否则 binlog 根本没开,后续所有策略都白搭 -
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';—— 若值为0或空,表示自动清理被禁用;默认值2592000(30 天)只在参数显式存在时才起作用 -
SHOW VARIABLES LIKE 'binlog_expire_logs_auto_purge';—— 必须为ON,这是开关,关了就啥都不删,哪怕binlog_expire_logs_seconds设对了也没用
注意:expire_logs_days 在 8.0.23+ 已弃用。如果它和 binlog_expire_logs_seconds 同时非零,MySQL 启动或重载配置会直接报错 ERROR 3683 (HY000),拒绝运行。
设置 binlog_expire_logs_seconds(唯一推荐方式)
必须用秒级单位,不能靠天数蒙混过关。7 天 = 604800,30 天 = 2592000:
- 动态设置(立即生效,但重启丢失):
SET GLOBAL binlog_expire_logs_seconds = 604800; - 持久化设置(推荐):编辑
/etc/my.cnf的[mysqld]段,添加binlog_expire_logs_seconds = 604800,然后重启;或执行SET PERSIST binlog_expire_logs_seconds = 604800;(需有PERSIST权限) - 该参数只控制“过期时间”,不控制文件大小;清理由后台线程每天凌晨触发,并非实时;主从延迟严重时(
Seconds_Behind_Master明显大于 0),正在被从库读取的 binlog 不会被删
配合 max_binlog_size 控制单文件体积
max_binlog_size 和过期策略完全正交,但它影响运维体验和排查效率:
- 默认值
1073741824(1GB),大事务会突破限制(事务不能跨文件),建议调小到536870912(512MB)或268435456(256MB) - 配置方式同上:
SET GLOBAL max_binlog_size = 536870912;或写入my.cnf - 哪怕把
max_binlog_size设成 1MB,若binlog_expire_logs_seconds是 0,照样攒满磁盘
验证与手动清理(别等自动触发)
自动清理有延迟,且依赖系统时间判断(按文件最后修改时间,而非日志内事件时间):
- 手动清理指定时间前的日志:
PURGE BINARY LOGS BEFORE '2026-09-25 00:00:00'; - 手动清理到某文件为止(不含该文件):
PURGE BINARY LOGS TO 'mysql-bin.000123'; - 执行
FLUSH LOGS;可强制滚动新 binlog,同时触发一次过期检查(前提是binlog_expire_logs_auto_purge = ON)
真正容易被忽略的是:清理逻辑会从 bin.index 中最老的文件开始检查,只要它没过期,哪怕后面有几十个过期文件,也不会删——所以得确保最老那个 binlog 文件本身也已超时,否则整个链路卡死。


















