MySQL binlog默认永不过期,易致磁盘爆满;需检查log_bin=ON、binlog_expire_logs_seconds=0(或未设)及expire_logs_days=0,并确保binlog_expire_logs_auto_purge=ON,8.0.23+必须用binlog_expire_logs_seconds设秒级保留。

MySQL 的 binlog 不设过期策略,默认永不过期,磁盘被撑爆是大概率事件,不是小概率风险。
如何确认 binlog 是否已启用且未设过期时间
先连上 MySQL,执行:SHOW VARIABLES LIKE 'log_bin'; 确认值为 ON;SHOW VARIABLES LIKE '%expire%'; 查看关键参数实际值。
重点关注:
-
binlog_expire_logs_seconds(MySQL 8.0.23+ 主力参数)是否为 0 或空 -
expire_logs_days(旧版兼容参数)是否为 0(默认值,即不清理) -
binlog_expire_logs_auto_purge是否为ON(必须为 ON 才会自动清理)
binlog_expire_logs_seconds 是 0 或未设置,binlog_expire_logs_auto_purge 即使为 ON 也无效。MySQL 8.0.23+ 必须用 binlog_expire_logs_seconds 设置秒级保留
新版不再支持 expire_logs_days 和 binlog_expire_logs_seconds 共存,冲突会报错 ERROR 3683 (HY000)。
动态设置(立即生效,但重启后丢失):SET GLOBAL binlog_expire_logs_seconds = 604800;(保留 7 天)
永久生效(写入配置文件):
编辑 /etc/my.cnf 的 [mysqld] 段,添加:
binlog_expire_logs_seconds = 604800然后重启或执行
SET PERSIST binlog_expire_logs_seconds = 604800;(需有权限)。
注意:
- 该参数只控制“过期时间”,不控制“文件大小”;清理动作在每天凌晨由后台线程触发,不是实时的
- 若主从延迟严重,从库还没读完的 binlog,MySQL 不会删——所以得先确保复制正常
- 设置后不会立刻删日志,可手动
FLUSH LOGS;触发一次轮转,再等清理线程跑一遍
max_binlog_size 控制单个 binlog 文件上限,但不解决总量问题
max_binlog_size 只决定每个 binlog 文件最多多大(如 max_binlog_size = 536870912 即 512MB),达到后自动切新文件。它不能替代过期策略,只是让日志更易管理、避免单文件过大影响备份或传输。
常见误操作:
- 只调大
max_binlog_size却不设binlog_expire_logs_seconds→ 日志文件变少但总量仍疯涨 - 把
max_binlog_size设得太小(如 10MB)→ 频繁切换文件,增加文件系统开销和SHOW BINARY LOGS查询负担 - 未监控磁盘使用率,等到
df -h显示/var/lib/mysql分区 95%+ 才发现
手动清理前务必确认从库同步状态
自动清理靠不住?想马上腾空间?可以手动 PURGE,但必须先验证:
查主库当前 binlog 位置:SHOW MASTER STATUS;
查所有从库的同步点:SHOW SLAVE STATUS\G(或 SELECT * FROM performance_schema.replication_applier_status_by_coordinator;),重点看 Read_Master_Log_Pos 和 Exec_Master_Log_Pos。
只有当所有从库的 Exec_Master_Log_Pos 都大于目标 binlog 文件的结束位置时,才能安全清理。否则执行:PURGE BINARY LOGS BEFORE '2026-04-01 00:00:00'; 就会导致从库 IO 线程报错 Could not find first log file name in binary log index file。
最容易被忽略的一点:
即使你没搭从库,也要检查是否有备份工具(如 mydumper、xtrabackup)正在读取 binlog —— 它们可能隐式依赖某段日志,删了就备份失败。


















