binlog_expire_logs_seconds设置后旧日志未立即删除,是因为mysql不实时扫描清理,仅在mysqld启动、flush binary logs执行或binlog写满切换时触发;需确保binlog_expire_logs_auto_purge=on并手动执行flush binary logs强制触发。

binlog_expire_logs_seconds 设置后为什么旧日志没立刻删?
MySQL 不是实时扫描并删除过期 binlog 的,清理动作由后台线程触发,通常每小时左右运行一次,也可能在启动、FLUSH BINARY LOGS 或 max_binlog_size 达限时顺带检查。所以改完参数别干等,立刻执行:
-
FLUSH BINARY LOGS—— 强制滚动一次,让当前正在写的 binlog 关闭,新文件开始写入,同时触发一次过期扫描 - 再查
SHOW BINARY LOGS,对比最老文件的关闭时间(需结合ls -lt /var/lib/mysql/mysql-bin.*看系统时间戳)是否已超出binlog_expire_logs_seconds设定范围
若仍不删,重点检查 binlog_expire_logs_auto_purge 是否为 ON:它优先级高于过期时间,设成 OFF 就完全禁用自动清理。
MySQL 8.0.11+ 必须用 binlog_expire_logs_seconds,expire_logs_days 会被忽略
8.0.11 及之后版本中,expire_logs_days 已废弃。即使你在配置里写了 expire_logs_days = 7,只要 binlog_expire_logs_seconds 存在(哪怕值为 0),前者就静默失效;若两者都设非零值,MySQL 会报错 ERROR 3683 (HY000)。
确认当前生效参数的方法:
- 执行
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_seconds';和SHOW GLOBAL VARIABLES LIKE 'expire_logs_days'; - 返回值非默认(
binlog_expire_logs_seconds默认 2592000,expire_logs_days默认 0)的那个才是真起作用的 - 注意:8.0.11+ 中只要
binlog_expire_logs_seconds有值,expire_logs_days就只是个只读兼容字段
永久生效必须写进 my.cnf,且位置和拼写不能错
仅用 SET GLOBAL binlog_expire_logs_seconds = 604800; 是临时的,MySQL 重启就丢。要永久生效,必须编辑配置文件(如 /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf),在 [mysqld] 段下添加:
binlog_expire_logs_seconds = 604800
常见静默失败原因:
- 漏写
[mysqld]段头,参数被当成全局无效配置 - 拼写错误,比如
binlog_expire_log_seconds(少一个s),MySQL 启动时直接忽略,SHOW VARIABLES仍显示默认值 - 配置文件权限不对或路径错误,MySQL 根本没读到该文件
改完不用重启 MySQL,但必须执行 FLUSH BINARY LOGS 才能立即触发清理逻辑。
主从环境里这个参数容易引发复制中断
主库设了 binlog_expire_logs_seconds = 604800(7 天),但从库延迟超过 7 天,主库一删旧 binlog,从库 I/O 线程立刻报错:Could not find first log file name in binary log index file,复制停摆。
安全做法:
- 先用
SHOW SLAVE STATUS\G查Seconds_Behind_Master和Relay_Master_Log_File - 确保
Relay_Master_Log_File对应的 binlog 文件仍在主库SHOW BINARY LOGS列表中 - 主库保留时长 ≥ 从库最大可能延迟 + 安全缓冲(建议至少多留 2–3 天)
- 不要只依赖自动清理,定期用
PURGE BINARY LOGS BEFORE ...手动清理前,务必核对从库进度
最麻烦的是:清理逻辑不看从库状态,只认时间戳。哪怕从库卡在某个事务上不动,主库该删还是删。











