logrotate是最稳妥的生产级日志轮转方案,配置需严格匹配slow_query_log_file的实际路径(含大小写与符号),create 640 mysql mysql不可少,且mysql用户须与mysqld进程一致;postrotate中刷新慢日志须按MySQL版本选择mysqladmin flush-logs slow(5.7+)或SQL方式开关(5.6及以下),并确保~/.my.cnf认证安全、路径全为绝对路径、手动验证新文件属主/权限及日志写入有效性。

logrotate 是最稳妥、生产环境广泛使用的方案,不依赖 MySQL 版本,也不需要自己写脚本处理权限和并发问题。直接用它配就行,别绕弯。
logrotate 配置文件必须写对路径和用户权限
配置里第一行写的日志路径,必须和 slow_query_log_file 的实际值完全一致(包括大小写和符号),否则 logrotate 根本找不到文件,轮转就静默失败。
create 640 mysql mysql 这行不能少,且 mysql 用户必须是 MySQL 进程运行的用户(常见但不是绝对等于系统用户 mysql,可用 ps aux | grep mysqld 确认)。如果权限不对,新日志创建后 MySQL 写不进去,slow_query_log 会自动关闭,错误日志里出现 Could not write to slow log。
常见坑点:
-
slow_query_log_file路径含软链接?logrotate不解析软链,得写真实物理路径 - 目录不存在或父目录权限不够(比如
/data/mysql/my3306/log/所有者不是mysql) - 配置文件放在
/etc/logrotate.d/下但没执行logrotate -d /etc/logrotate.conf测试语法
postrotate 里用 mysqladmin flush-logs slow 要看 MySQL 版本
MySQL 5.7+ 支持 mysqladmin flush-logs slow 单独刷慢日志;5.6 及更早版本不识别 slow 参数,执行会刷所有日志(binary、error、general 等全重命名),可能干扰备份或高可用切换。
所以判断方式很简单:
- 先查版本:
mysql -V - 5.7+:放心用
mysqladmin flush-logs slow - 5.6 或不确定:改用 SQL 方式:
mysql -uroot -p... -e "SET GLOBAL slow_query_log = OFF; SET GLOBAL slow_query_log = ON;" - 注意 socket 路径(如
-S /tmp/mysql_3306.sock)或 TCP 连接(-h127.0.0.1 -P3306),避免连不上
crontab 不要直接调 logrotate,走系统默认机制
logrotate 默认由 /etc/cron.daily/logrotate 触发,每天凌晨运行一次。你不需要额外加 crontab 行 —— 除非你真要非标准时间(比如每天 23:59)。
如果非要自定义时间,写法是:
59 23 * * * root /usr/sbin/logrotate -f /etc/logrotate.d/mysql-slow
但要注意:
-
-f强制执行,跳过logrotate自身的时间判断逻辑,慎用 - 不要用
~或相对路径,所有路径写绝对路径 - 密码明文写在命令里极不安全,务必用
~/.my.cnf配置认证([client] user=root password=xxx,权限600)
验证切割是否真生效,别只看文件名
光看到 slow.log-20260908 生成了,不代表成功。关键看三件事:
- 新
slow.log文件属主是否为mysql,权限是否可写(ls -l slow.log) - MySQL 里执行
SHOW VARIABLES LIKE 'slow_query_log_file';,确认指向的是没带日期后缀的那个原始路径 - 手动触发一条慢 SQL(如
SELECT SLEEP(3);),检查新文件里有没有新增记录,旧文件是否不再追加
最容易被忽略的是:MySQL 进程启动后第一次写日志时,会按配置的 slow_query_log_file 路径创建文件;而 logrotate 创建的新文件只是“空壳”,真正让 MySQL 切到新文件的,是 postrotate 里的刷新动作 —— 这一步失败,日志就还在老文件里滚。


















