mysql binlog占用磁盘过大的根本原因是expire_logs_days默认为0(永不清除),8.0.11+已废弃该参数,必须改用binlog_expire_logs_seconds并写入my.cnf重启生效,再执行purge binary logs手动清理旧日志,同时建议添加宝塔定时脚本兜底。

MySQL binlog 占用磁盘过大,根本不是“日志太多”,而是默认**永不清除**——expire_logs_days 默认值是 0,且在 MySQL 8.0.11+ 中已失效;不改配置、不手动清理,它就会一直涨,直到把磁盘撑爆。
确认 binlog 是否开启及当前过期策略是否生效
别猜,先查清楚现状,避免白配一通:
- 执行
mysql -uroot -p -e "show variables like 'log_bin';",返回ON表示 binlog 已启用 - 执行
mysql -uroot -p -e "show variables like 'expire_logs_days';"和show variables like 'binlog_expire_logs_seconds';"—— 两个都得看。如果前者是7但后者是0或NULL,说明你还在用老参数,而 MySQL 8.0.11+ 实际已忽略它 - 执行
mysql -uroot -p -e "show binary logs;",看文件数量和最早文件的File_size累加是否超 GB 级。若最早文件生成时间是 2026-04-01,而你设了 7 天却还存在,就说明没生效
MySQL 5.7 与 8.0+ 的过期参数必须分清
写错参数名或混用版本,等于没配:
- MySQL 5.7 及更早:只认
expire_logs_days = 7,加到/www/server/mysql/etc/my.cnf的[mysqld]段末尾,重启生效 - MySQL 8.0.11+(含宝塔常见 8.0.33):
expire_logs_days已废弃,默认值变为0,即使写了也无效;必须用binlog_expire_logs_seconds = 604800(7 天),同样加进my.cnf并重启 - 注意路径:宝塔用户配置文件通常在
/www/server/mysql/etc/my.cnf,不是/etc/my.cnf;改错位置等于白改 - 不要同时写两个参数——
binlog_expire_logs_seconds会静默覆盖expire_logs_days,连警告都不打
PURGE BINARY LOGS 手动清理前必须核对三件事
自动策略有延迟,磁盘告急时得立刻动手,但删错一条就可能中断主从或丢恢复能力:
- 查所有从库状态:
SHOW SLAVE STATUS\G,重点看Relay_Master_Log_File字段值。你要删的日志,不能比这个文件更新,否则从库 IO 线程直接报错Got fatal error 1236 - 查主库当前日志:
SHOW MASTER STATUS;,确认File值(如mysql-bin.000123),PURGE时不能包含它——比如用PURGE BINARY LOGS TO 'mysql-bin.000123';是错的,正确是TO 'mysql-bin.000124'; - 如果是 GTID 模式(
gtid_mode = ON),禁止按文件名PURGE TO,必须用时间点:PURGE BINARY LOGS BEFORE '2026-04-30 00:00:00';,否则可能删掉未被消费的事务
自动清理不触发?可能是低流量下 binlog 不滚动
MySQL 不是定时扫描清理,而是在每次 FLUSH LOGS(日志切换)时才检查过期并删除——如果业务极闲、一天都没几条写入,mysql-bin.000001 就会一直写下去,永远不滚,过期逻辑也就永远不会跑。
验证方法:手动执行 mysql -uroot -p -e "FLUSH LOGS;",立刻再查 SHOW BINARY LOGS;,看最老的文件是否消失。若消失了,说明策略本身是对的,只是缺触发条件。
生产环境建议补一层兜底:用宝塔定时任务每天凌晨跑一次 mysql -u root -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);",比等 MySQL 自己滚动更可靠。但记住——这条命令不会校验从库状态,执行前务必人工确认。
真正容易被忽略的点是:binlog_expire_logs_seconds 的时间基准是 binlog 写入时间戳,不是系统时间;如果服务器时钟不准、或跨时区同步,可能导致误删或漏删。上线前最好拿测试库跑一遍时间点 purge,观察从库是否持续追平。











