必须用binlog_expire_logs_seconds(如604800秒),expire_logs_days已废弃且设则冲突或报错;PURGE前须核对主从位置,避免中断复制。
直接结论:别删文件,先查主从位置再 PURGE;MySQL 8.0+ 必须用 binlog_expire_logs_seconds,设了 expire_logs_days 反而可能失效。
磁盘告警不等于 binlog 问题——slow_query_log 单独涨到 397G 的案例刚发生在 2026 年 4 月。先定位真实元凶:
du -sh /var/lib/mysql/*.log /var/log/mysql/*.log 看各日志大小,重点关注 mysql-bin.*、slow-query.log、error.log
SHOW VARIABLES LIKE 'log_bin'; 确认 binlog 是否开启(返回 ON 才算)SHOW BINARY LOGS; 查看当前 binlog 总数和总大小;如果单个 mysql-bin.000xxx 超过 1GB,且数量持续增加,基本可锁定为 binlog 问题general_log:SHOW VARIABLES LIKE 'general_log'; —— 它记录每条 SQL,不用时务必关掉直接 rm mysql-bin.000042 会断主从,从库报错 Got fatal error 1236。安全清理的前提是确认所有从库都已读完待删日志:
SHOW MASTER STATUS;,记下 File 字段(如 mysql-bin.000042)SHOW SLAVE STATUSG,重点看 Relay_Master_Log_File 和 Exec_Master_Log_Pos
Relay_Master_Log_File 序号最小的那个(比如 mysql-bin.000035),这就是安全边界——你最多只能 PURGE TO 'mysql-bin.000036';
PURGE BINARY LOGS TO 'mysql-bin.000036'; 或 PURGE BINARY LOGS BEFORE '2026-06-02 00:00:00';(注意时间格式必须是 Y-m-d H:i:s)binlog_expire_logs_seconds
MySQL 8.0 开始,expire_logs_days 已废弃,默认值为 0(永不清除),设了也不生效。只靠 SET GLOBAL 是临时的,重启即丢:
/etc/my.cnf 或宝塔路径 /www/server/mysql/etc/my.cnf),在 [mysqld] 段添加:binlog_expire_logs_seconds = 604800expire_logs_days = 0保存后重启:systemctl restart mysqld 验证是否生效:SHOW VARIABLES LIKE 'binlog_expire_logs_seconds'; —— 值必须是你设的秒数(如 604800),不是 0 或空 顺手加一句 max_binlog_size = 100M,防止单个 binlog 文件过大拖慢 purge 效率
自动清理只是兜底,真正治本得减少 binlog 体积本身:
SHOW VARIABLES LIKE 'binlog_format'; —— 若是 ROW 或 MIXED,高频更新场景下体积可能是 STATEMENT 的 10 倍+NOW()、RAND()),改用 STATEMENT:SET GLOBAL binlog_format = 'STATEMENT';,并写入 my.cnf 永久生效INSERT 替代批量 INSERT ... VALUES (...), (...),这类写法会成倍放大 binlog 事件数最容易被忽略的是:配置改了、PURGE 也执行了,但磁盘空间没释放——大概率是旧日志文件句柄仍被 mysqld 进程占用。此时需 FLUSH LOGS; 强制切换新 binlog,旧文件才能被彻底释放。