直接删除 error.log 不释放空间,必须配合 logrotate 的 postrotate 脚本执行 mysqladmin flush-logs 才能切换日志文件;真实路径需通过 SELECT @@global.log_error 确认,避免因 Docker 映射、启动参数覆盖或配置未加载导致路径错位。

直接删 error.log 文件不会释放磁盘空间,MySQL 进程仍往旧文件描述符里写;必须配合轮转动作和 MySQL 主动重开日志,否则磁盘会持续告警甚至撑爆。
确认真实 log_error 路径再操作
很多人配了 logrotate 却没效果,第一反应是脚本错了——其实常是 MySQL 根本没在写你认为的那个文件。Docker 容器路径映射错、systemd 启动时用 --log-error 覆盖了配置、Ubuntu 默认用 debian.cnf 但 mysqld 没读它,都可能导致路径错位。
- 登录 MySQL 执行:
SELECT @@global.log_error;—— 返回值才是真实路径 - 检查是否启用:
SELECT @@global.log_error_verbosity;(建议设为2,过滤掉大量INFO级日志) - 若返回空或路径异常,查启动参数:
ps aux | grep mysqld,看是否有--log-error=显式指定
logrotate 必须带 postrotate + mysqladmin flush-logs
只靠 copytruncate 或简单移动文件,MySQL 仍往原文件句柄写,空间不释放;create 权限设错还会导致新日志写不进,报 Can't open log file。
- 配置中必须用
postrotate(不是prerotate),顺序是:先轮转文件,再通知 MySQL 切日志,否则丢最后几秒日志 -
mysqladmin flush-logs是关键动作,它让 mysqld 关闭当前error.log并打开新文件;别用FLUSH LOGS(会刷所有日志,包括 binlog) -
mysqladmin需权限:建议用专用账号(如flush-logs@localhost),仅授RELOAD权限,避免用 root 密码硬编码 - 示例片段(
/etc/logrotate.d/mysql-error):/var/log/mysql/error.log { daily missingok rotate 30 compress delaycompress notifempty create 640 mysql adm sharedscripts postrotate if [ -f /var/run/mysqld/mysqld.pid ]; then mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs 2>/dev/null || true fi endscript }
手动轮转应急时,mv + FLUSH ERROR LOGS 更稳妥
临时清理或验证逻辑时,手动操作比等 logrotate 周期更快,且不依赖外部工具链。注意:MySQL 5.7.2+ 才支持 FLUSH ERROR LOGS,旧版本只能发信号。
- 先重命名当前日志:
sudo mv /var/log/mysql/error.log /var/log/mysql/error.log.$(date +%Y%m%d) - 再执行:
mysql -e "FLUSH ERROR LOGS;"—— MySQL 会立即创建新error.log并写入后续日志 - 旧文件可立刻压缩:
gzip /var/log/mysql/error.log.$(date +%Y%m%d),节省空间 - 别用
truncate -s 0清空:虽然能释放空间,但无法归档,也失去时间维度追溯能力
容易被忽略的兼容性细节
看似简单的轮转,实际踩坑点密集:MySQL 版本差异、信号支持不稳定、socket 路径不一致、属组权限错配……任一环节断掉,日志就停在旧文件里继续涨。
- MySQL 5.7+ 推荐用
mysqladmin flush-logs,而非kill -USR1:后者在某些发行版或容器环境信号处理不一致 -
create 640 mysql adm中的adm组适用于 Debian/Ubuntu;CentOS/RHEL 应用mysql组,否则新文件 MySQL 写不了 - 测试配置是否生效:
logrotate -d /etc/logrotate.d/mysql-error(调试模式),看输出是否触发postrotate脚本 - 若 MySQL 启动时用 socket 认证(如
-S /var/run/mysqld/mysqld.sock),mysqladmin也得走 socket,避免 TCP 连接失败


















