mysql 8.0 binlog自动清理需同时满足三个条件:binlog_expire_logs_auto_purge=on、binlog_expire_logs_seconds设为非零值、触发清理时机(启动/flush logs/轮转),文件mtime而非事件时间决定是否删除。

binlog_expire_logs_seconds 不是“清理间隔”,而是“过期阈值”——它定义日志文件从最后关闭时间起保留多久才可被删除,不是每多少秒检查一次。
MySQL 从不按固定秒数轮询清理 binlog。真正触发清理的只有三个时机:
- MySQL 启动时
- 执行
FLUSH BINARY LOGS或FLUSH LOGS时 - 当前 binlog 文件写满(达到
max_binlog_size)并自动轮转时
所以你设了 binlog_expire_logs_seconds = 604800(7 天),不代表 7 天一到就删;而是:等下一个轮转事件发生时,MySQL 才会扫描所有已关闭的 binlog,把“最后关闭时间早于当前时间减 7 天”的文件批量删掉。
常见误解和应对方式:
误以为设了参数就会每小时/每天自动删
实际上没有后台定时器。若业务写入量极低、max_binlog_size很大、又没手动FLUSH LOGS,可能连续几天都不触发清理,binlog 持续堆积。磁盘告急时干等自动清理
别等。立刻执行:FLUSH LOGS—— 这会强制生成新 binlog,并同步触发过期扫描与删除。主从延迟高,清理却照常发生
自动清理只看“是否过期”,不主动校验从库进度。如果Seconds_Behind_Master很大,而你又没关binlog_expire_logs_auto_purge,MySQL 仍可能删掉从库还没读的文件,导致复制中断。
怎么确认清理逻辑真在跑?
执行这三条命令,缺一不可:
-
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_seconds';→ 必须是非零整数(如604800) -
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_auto_purge';→ 必须是ON -
SHOW VARIABLES LIKE 'log_bin';→ 必须是ON,否则整个 binlog 链路都不存在
如果其中任一值不符合,PURGE 类操作不会被自动触发,哪怕磁盘快爆了。
最易被忽略的一点:Docker 官方镜像或部分云数据库(如阿里云 RDS、腾讯云 CDB)默认把 binlog_expire_logs_auto_purge 设为 OFF,哪怕你配了 binlog_expire_logs_seconds,也等于白配。必须显式打开它,且不能只靠 SET GLOBAL —— 要写进配置文件或用 SET PERSIST 持久化,否则重启即失效。











