MySQL错误日志默认持续追加不轮转,需用logrotate配合kill -USR1信号通知mysqld重新打开日志文件;慢查询日志同理,而binlog必须通过expire_logs_days或PURGE命令管理,禁止直接删除。

MySQL 的 error.log 不会自动轮转,它只是持续追加写入——这是默认行为,不是 bug。只要 MySQL 进程不重启、不手动刷新,日志就一直往同一个文件里写,磁盘占满是迟早的事。
确认 log_error 路径是否真被 MySQL 使用
很多人配了 logrotate 却没效果,第一排查点就是:MySQL 实际写的到底是不是你配置的那个 error.log?
- 执行
mysql -u root -p -e "SHOW VARIABLES LIKE 'log_error';",看输出路径 - 检查进程实际参数:
ps aux | grep mysqld,留意是否有--log-error=...覆盖了配置文件设置 - Docker 环境要核对 volume 映射路径是否和配置一致;Ubuntu/Debian 系统可能通过
debian.cnf指定了路径,但 systemd 启动脚本又绕过了它 - 确保该路径目录存在且属主为
mysql:mysql,权限至少为755
logrotate 配置必须带 USR1 信号通知 mysqld reopen
logrotate 自己切完文件后,MySQL 还拿着旧文件的 fd 往里写,新日志不会自动出现在新文件里——除非你告诉它“该换文件了”。
- 在
/etc/logrotate.d/mysql的postrotate段中,必须用kill -USR1(不是SIGHUP或kill -9) - USR1 是 MySQL 官方文档明确指定用于
reopen error log的信号,5.5.3+ 全版本支持 - PID 文件路径要匹配真实位置,常见的是
/var/run/mysqld/mysqld.pid,但有些系统是/var/lib/mysql/mysqld.pid或/run/mysqld/mysqld.pid - 示例关键段:
/var/log/mysql/error.log { daily missingok rotate 7 compress notifempty create 640 mysql mysql sharedscripts postrotate if [ -f /var/run/mysqld/mysqld.pid ]; then kill -USR1 $(cat /var/run/mysqld/mysqld.pid) fi endscript }
别忽略 slow_query_log 和 binlog 的轮转差异
错误日志和慢查询日志能走 logrotate + USR1,但 binlog 完全不能这么搞——直接删或轮转会破坏复制和恢复。
-
slow_query_log_file路径也得在my.cnf里显式指定,否则可能写到临时位置;轮转方式和error.log完全一致 -
binlog必须靠 MySQL 自身控制:SET PERSIST binlog_expire_logs_seconds = 604800;(7 天),或用PURGE BINARY LOGS BEFORE ... - 绝对禁止
rm -f /var/lib/mysql/mysql-bin.*,会导致mysql-bin.index和实际文件不一致,从库同步中断甚至无法启动 - 如果启用了
general_log,它同样需要logrotate + USR1,但生产环境建议关闭
最容易被跳过的一步是验证:改完 logrotate 配置后,运行 sudo logrotate -d /etc/logrotate.conf 看调试输出是否命中你的规则;再手动触发一次 sudo logrotate -f /etc/logrotate.d/mysql,立刻检查新日志是否生成、旧日志是否压缩、error.log 文件大小是否归零——别等 cron 自动跑才确认。


















