MySQL 8.0+ 必须用 binlog_expire_logs_seconds,expire_logs_days 已废弃;需在 my.cnf 的 [mysqld] 段配置 binlog_expire_logs_seconds = 604800(7天)并显式设 expire_logs_days = 0,且仅在 MySQL 启动或 binlog 切换(如 flush logs、达 max_binlog_size)时触发自动清理。

MySQL 8.0+ 必须用 binlog_expire_logs_seconds,expire_logs_days 已失效
MySQL 8.0.11 起,expire_logs_days 被标记为 deprecated,即使你设了它,MySQL 也会忽略——除非同时清空 binlog_expire_logs_seconds(设为 0 或 unset),否则新参数优先且旧参数不生效。实测中常见配置冲突:my.cnf 里两个参数都写了,结果自动清理完全不动。
正确做法是只留一个:
-
binlog_expire_logs_seconds = 604800(7 天)→ 推荐,秒级精度,主从容错更稳 - 顺手加一行:
expire_logs_days = 0,显式关闭旧逻辑,避免歧义 - 该配置必须写进
/www/server/mysql/etc/my.cnf的[mysqld]段,不是/etc/my.cnf
PURGE BINARY LOGS 手动清理后空间不释放?检查文件句柄是否被占
执行 PURGE BINARY LOGS BEFORE '2026-05-02 00:00:00'; 后 df -h 看磁盘没变化,大概率是 MySQL 进程还拿着已删文件的句柄(尤其是备份工具如 xtrabackup 执行过 FLUSH NO_WRITE_TO_BINLOG BINARY LOGS 后未释放锁)。
验证方式:
- 查句柄:
lsof -nP | grep '/www/server/mysql/data/mysql-bin' | grep deleted - 若输出非空,说明文件被进程占用,磁盘空间不会真正释放
- 临时解法:
systemctl restart mysqld(宝塔面板点重启也行),但注意主从延迟风险
binlog_expire_logs_seconds 不触发自动清理?看它到底什么时候干活
这个参数不是“每秒检查一次”,而是靠事件驱动:只在 MySQL 启动、或发生 binlog 切换时扫描并清理。而 binlog 切换又依赖两个条件:
- 当前 binlog 文件大小 ≥
max_binlog_size(默认 1GB) - 或你手动执行了
FLUSH BINARY LOGS
所以如果业务写入量极低,单个 mysql-bin.0000xx 几天都写不满 1GB,那就算设了 7 天,也不会自动删——得主动 FLUSH BINARY LOGS 触发一次切换,才能启动清理逻辑。
建议搭配定时任务:
- 每天凌晨跑一次:
mysql -uroot -e "FLUSH BINARY LOGS;" - 再立刻跟一句
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);,双重保险
宝塔计划任务里写 PURGE 脚本,必须校验主从位置再删
直接在宝塔「计划任务」里加 Shell 脚本执行 PURGE 很方便,但危险点在于:删掉的 binlog 若从库还没读完,就会报错 Got fatal error 1236,主从中断。
安全脚本必须包含校验步骤:
- 先查从库位置:
mysql -uroot -e "SHOW SLAVE STATUS\G" | grep "Relay_Master_Log_File" - 拿到值如
mysql-bin.000023,则PURGE至少保留到这个文件(即TO 'mysql-bin.000023') - 或者用时间兜底:
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 12 HOUR);(比从库延迟多留几小时)
别图省事跳过这步——主从断开后恢复成本远高于多占几 GB 磁盘。


















