mysql 8.0 必须显式配置 binlog_expire_logs_seconds(如604800)并设 binlog_expire_logs_auto_purge=on,否则默认为0(永不清除),且需配合 max_binlog_size 控制单文件大小,再通过 flush logs 触发清理。

MySQL 8.0 部署时必须显式配置 binlog_expire_logs_seconds,否则默认值为 0(永不清除),磁盘迟早被撑爆。
确认 binlog 是否启用及清理参数是否生效
别跳过这步——很多“清理不生效”问题其实压根没开 binlog,或参数根本没加载成功:
- 运行
mysql -uroot -p -e "SHOW VARIABLES LIKE 'log_bin';",返回ON才说明 binlog 已启用 - 执行
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';,若值为0或空,代表自动清理完全关闭 - 执行
SHOW VARIABLES LIKE 'binlog_expire_logs_auto_purge';,必须是ON,否则设了秒数也白搭 - 用
SHOW BINARY LOGS;查当前文件数量和总大小,File_size 加起来超 2GB 就该动手了
写入 my.cnf 并重启(不是 SET GLOBAL)
动态设置 SET GLOBAL binlog_expire_logs_seconds = 604800; 只是临时生效,MySQL 重启就丢。生产环境必须落盘:
- 编辑配置文件:宝塔用户改
/www/server/mysql/etc/my.cnf,其他环境通常是/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf - 在
[mysqld]段末尾添加两行:binlog_expire_logs_seconds = 604800binlog_expire_logs_auto_purge = ON - 顺手清掉已废弃的旧参数:
expire_logs_days = 0(哪怕不写,也别留expire_logs_days = 7,它会冲突且静默失效) - 保存后必须执行
systemctl restart mysqld(或宝塔面板点重启),再查SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';确认值已更新
配合 max_binlog_size 控制单文件体积
binlog_expire_logs_seconds 管“保留多久”,max_binlog_size 管“每个文件多大”。两者不配,可能单个文件过大(比如 2GB+),导致过期扫描滞后、备份卡顿、甚至 purge 不及时:
- 在同一个
[mysqld]段下加一行:max_binlog_size = 512M(推荐 256M–1G 区间) - 注意:这个值只是建议上限,大事务不会中途切文件,所以实际文件可能略超
- 它和过期策略无关,但没配的话,
binlog_expire_logs_seconds的效果会打折——比如一个 3GB 的活跃日志,即使过了 7 天也不会被删
验证清理是否真在跑
MySQL 不是定时任务,它只在三个时机检查过期:启动时、FLUSH LOGS 时、或当前 binlog 写满触发轮转时。所以部署完不能只等:
- 执行
FLUSH LOGS;强制轮转一次(生成新文件如mysql-bin.000043),同时触发对旧文件的过期扫描 - 几秒后立刻查
SHOW BINARY LOGS;,看旧文件是否减少;再用ls -lh /var/lib/mysql/(或你的 binlog 目录)确认磁盘空间是否释放 - 如果没释放,大概率是文件句柄还被 mysqld 占着——
FLUSH LOGS后必须等 MySQL 完成内部清理逻辑,不是立即删磁盘文件
真正容易被忽略的是:binlog_expire_logs_seconds 对正在写的当前 binlog(如 mysql-bin.000043)完全无效,它只扫“已关闭”的历史文件;而 max_binlog_size 决定了这些历史文件能长多大、多久轮转一次——这两个参数必须一起调,缺一不可。











