expire_logs_days仅清理binlog,需启用log_bin且依赖flush logs触发,受主从复制保护;error/slow/general日志须用logrotate或purge命令主动管理。

expire_logs_days 设置后为什么日志没被清理?
MySQL 的 expire_logs_days 参数只控制二进制日志(binlog)的自动过期删除,不清理错误日志、慢查询日志或 general log。很多用户误以为它能“清所有日志”,结果发现 error.log 或 slow.log 越积越大,磁盘报警依旧。
- 该参数仅对
SHOW BINARY LOGS列出的 binlog 文件生效 - 必须开启 binlog(
log_bin=ON)才起作用;若未启用 binlog,设置该参数无效且 MySQL 启动时会忽略 - 实际清理发生在每天首次执行 FLUSH LOGS 时(或 mysqld 启动时),不是实时扫描删除
- 如果主从复制中从库还没读完某 binlog,即使超期也不会删——这是安全机制,不是 bug
如何确认 expire_logs_days 是否生效?
不能只看配置文件里写了就放心。得查运行时值 + 实际 binlog 状态:
- 运行
SELECT @@global.expire_logs_days;,确认返回的是你设的数字(如 7),不是 0 或 NULL - 执行
SHOW BINARY LOGS;,观察最早那个文件的生成时间是否已超过设定天数 - 手动触发一次清理:
FLUSH LOGS;,再立刻查SHOW BINARY LOGS;,看最老的是否消失 - 注意:如果返回空结果或报错
ERROR 1373 (HY000): BINLOG statement is not allowed when @@binlog_format == STATEMENT and @@binlog_direct_non_transactional_updates == OFF,说明 binlog 格式或权限有问题,先检查log_bin和binlog_format
比 expire_logs_days 更可靠的清理方式
依赖自动参数有延迟、受复制状态制约,生产环境建议配合主动管理:
- 用
PURGE BINARY LOGS BEFORE '2024-06-01 00:00:00';精确删除指定时间前的所有 binlog - 用
PURGE BINARY LOGS TO 'mysql-bin.000123';删除编号小于该文件的所有 binlog(适合主从切换后清理旧主日志) - 把 purge 命令写进定时任务(如 crontab),比依赖 MySQL 内部调度更可控,例如每天凌晨 2 点执行:
mysql -u root -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);" - 注意:执行 purge 前务必确认从库
SHOW SLAVE STATUS\G中的Relay_Master_Log_File没有指向即将被删的 binlog,否则会导致从库 IO 线程中断
其他日志(error/slow/general)怎么定期清理?
这些日志 MySQL 完全不管过期,得靠操作系统级轮转或脚本处理:
- 错误日志(
error.log)默认不自动轮转;可配置log_error = /var/log/mysql/error.log,再用logrotate管理,加copytruncate避免重启 mysqld - 慢查询日志(
slow_query_log_file)和 general log 同理,需配合logrotate或定时mv+mysqladmin flush-logs - 切忌直接
rm -f error.log:MySQL 会继续往原 fd 写,文件虽删但磁盘空间不释放;正确做法是echo "" > error.log或用logrotate的copytruncate - 如果启用了
log_output = 'TABLE'(写入mysql.slow_log表),则用DELETE FROM mysql.slow_log WHERE start_time 清理,记得 <code>OPTIMIZE TABLE mysql.slow_log;回收空间
真正麻烦的不是设一个参数,而是搞清每种日志的生命周期、谁在读、谁在写、删了会不会断复制或丢审计线索。binlog 清理卡在从库进度上、error.log 被直接 truncate 导致空间不释放——这两类问题现场最多。











