mysql 8.0 的错误日志和慢查询日志路径必须显式配置绝对路径,否则 logrotate 无法识别并轮转;需在 my.cnf 的 [mysqld] 段中明确设置 log_error 和 slow_query_log_file,并使用 copytruncate 方式轮转,避免日志写入中断。

MySQL 8.0 的错误日志和慢查询日志路径必须显式配置
MySQL 8.0 默认不启用 slow_query_log_file 和 log_error 的绝对路径,如果没在 my.cnf 里写死,logrotate 就找不到文件,轮转会静默失败。常见现象是 logrotate 执行无报错,但日志文件大小照涨不缩。
检查当前路径:
mysql -Nse "SELECT @@global.slow_query_log_file; SELECT @@global.log_error;"
若返回的是相对路径(如 host-name-slow.log 或 host-name.err),必须修改配置:
- 编辑
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf - 在
[mysqld]段下添加或修正:
log_error = /var/log/mysql/error.log slow_query_log_file = /var/log/mysql/slow.log
重启 MySQL:systemctl restart mysql;确认新路径已生效。
logrotate 配置中必须用 copytruncate 而非 create
MySQL 进程始终持有日志文件句柄,直接 mv 或 create 新文件会导致 MySQL 继续往已重命名的旧文件写入(即日志“消失”)。copytruncate 是唯一安全选项:它先拷贝内容,再清空原文件,MySQL 无感知。
示例配置(存为 /etc/logrotate.d/mysql):
/var/log/mysql/*.log {
daily
missingok
rotate 7
compress
delaycompress
copytruncate
notifempty
sharedscripts
postrotate
if systemctl is-active --quiet mysql; then
# MySQL 8.0 不再支持 mysqladmin flush-logs 对 error.log 生效
# 只对 slow.log 和 general_log 有效;error.log 依赖 copytruncate 自然截断
mysql -s -e "FLUSH SLOW LOGS;" 2>/dev/null || true
fi
endscript
}
注意点:
-
sharedscripts确保postrotate只执行一次(即使匹配多个.log文件) -
FLUSH SLOW LOGS仅刷新慢日志,对log_error无效;MySQL 8.0 的错误日志无法通过 SQL 刷新,全靠copytruncate - 不要加
create 644 mysql mysql——这会破坏句柄,导致日志写入中断
验证 logrotate 是否真正触发了 MySQL 日志截断
手动运行并观察输出细节:
logrotate -d /etc/logrotate.d/mysql
关键要看两行:
- 是否出现
copying /var/log/mysql/error.log to /var/log/mysql/error.log.1 - 是否出现
truncating /var/log/mysql/error.log
若只有 renaming 或 creating new log file,说明配置用了 create 或路径不对。再检查 logrotate -v 输出中的 “error:” 行,常见错误包括:error: cannot stat /var/log/mysql/*.log(路径不存在或权限不足)、error: skipping "/var/log/mysql/error.log" because parent directory has insecure permissions(/var/log/mysql 目录权限不是 755 或属主非 root)。
权限修复命令:
chown -R root:root /var/log/mysql chmod 755 /var/log/mysql
MySQL 8.0 的 general_log 和 error_log 不能共用同一份 logrotate 规则
如果启用了 general_log,它的文件路径由 general_log_file 控制,且默认不开启。一旦开启,它和 slow_query_log_file、log_error 的轮转需求不同:general_log 写入极频繁,建议更激进压缩(如 hourly + rotate 24),而 error.log 可 daily + rotate 30。
拆分配置更稳妥:
-
/etc/logrotate.d/mysql-error:只管log_error -
/etc/logrotate.d/mysql-slow:只管slow_query_log_file -
/etc/logrotate.d/mysql-general(可选):只在启用general_log=ON时存在
否则容易因某类日志缺失导致整条规则跳过——logrotate 默认遇到第一个匹配失败就停止处理该配置块。
最易被忽略的一点:MySQL 8.0 的 log_error 文件名后缀不固定,有些安装会生成 mysqld.log 而非 error.log,务必用 ls -l /proc/$(pidof mysqld)/fd/ | grep log 确认进程实际打开的文件路径。











