mysql 8.0.11+ 必须使用 binlog_expire_logs_seconds 控制 binlog 过期,expire_logs_days 已废弃;生效需同时满足:binlog_expire_logs_seconds 非零、binlog_expire_logs_auto_purge=on,并在触发时机(启动/flush binary logs/轮转)下执行清理。

MySQL 8.0.11+ 必须用 binlog_expire_logs_seconds,设 expire_logs_days 不仅无效,还可能报错或静默失效。
确认当前生效的是哪个过期参数
别看配置文件写了什么,直接查 MySQL 实际加载的值:
-
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_seconds';—— 若返回非零值(如604800),说明它在管事 -
SHOW GLOBAL VARIABLES LIKE 'expire_logs_days';—— 即使显示非零,也只是兼容字段,不代表生效 -
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_auto_purge';—— 必须为ON,否则自动清理完全不触发
三者中,binlog_expire_logs_auto_purge 优先级最高:设成 OFF,哪怕 binlog_expire_logs_seconds 是 604800 也白搭。
永久配置 binlog_expire_logs_seconds 的正确写法
临时 SET GLOBAL 在重启后丢失,磁盘爆满往往就发生在重启后——必须落盘:
- 编辑配置文件:
/etc/mysql/mysql.conf.d/mysqld.cnf(Ubuntu/Debian)或/etc/my.cnf(CentOS/RHEL),确保在[mysqld]段内 - 添加两行(注意拼写,少个
s或漏掉[mysqld]都会静默失败):binlog_expire_logs_seconds = 604800 binlog_expire_logs_auto_purge = ON
- 保存后无需重启 MySQL,但必须执行
FLUSH BINARY LOGS才能立刻触发一次过期扫描
若之前设过 expire_logs_days,建议先清掉:SET GLOBAL expire_logs_days = 0;,避免冲突。
PURGE BINARY LOGS 手动清理已有堆积日志
配置只约束“未来生成的日志”,已存在的几十个 mysql-bin.000xxx 文件不会自动消失。误删会断主从:
- 主库执行:
SHOW MASTER STATUS;记下当前File(如mysql-bin.000042) - 每台从库执行:
SHOW SLAVE STATUS\G,看Relay_Master_Log_File字段(如mysql-bin.000035) - 取所有从库中序号最小的那个文件,就是安全底线;执行
PURGE BINARY LOGS TO 'mysql-bin.000036'; - 清理后若
df -h磁盘空间没释放,补一句FLUSH LOGS;强制关闭旧文件句柄
为什么配了 binlog_expire_logs_seconds 日志还没删?
MySQL 不是定时任务式清理,而是靠事件触发:
- 触发时机只有三种:MySQL 启动、执行
FLUSH BINARY LOGS、或当前 binlog 写满max_binlog_size自动轮转时 - 所以改完参数不
FLUSH,可能等一小时甚至更久才看到效果 - Docker 镜像或云数据库(如阿里云 RDS、腾讯云 CDB)常默认关掉
binlog_expire_logs_auto_purge,得单独确认 - 如果磁盘告急,别等自动,立刻手动
PURGE+FLUSH LOGS
真正容易被忽略的点是:自动清理不是“配了就删”,而是“配了+触发时机到了+开关开着”三者缺一不可;尤其 binlog_expire_logs_auto_purge 这个开关,在很多托管环境里默认是 OFF。











