确认慢查询日志是否真正启用需执行show variables like 'slow_query_log',返回on才生效;若为off则未启用,即使my.cnf已配置也无效,且mysql 8.0该变量只读,必须修改配置文件并重启服务。

确认当前慢查询日志是否真正启用
别信配置文件里写了就等于生效。直接连上 MySQL 执行:SHOW VARIABLES LIKE 'slow_query_log';,如果返回值是 OFF,那不管 my.cnf 里怎么写都白搭。顺手再查两个关键变量:SHOW VARIABLES LIKE 'slow_query_log_file'; 看日志实际写哪(不是默认路径!),SHOW VARIABLES LIKE 'long_query_time'; 看阈值设了多少秒(注意:8.0 默认仍是 10.0,不是你想象的 1 秒)。
修改 my.cnf 并重启 mysqld 才算真正生效
MySQL 8.0 的 slow_query_log 不支持动态开启,SET GLOBAL slow_query_log = ON 虽然能临时生效,但服务一重启就回退。必须改配置文件并重启:
- 确保配置写在
[mysqld]段下,写在[client]或其他段无效 -
slow_query_log = ON(必须大写ON,用1或true会静默失败) -
slow_query_log_file = /var/log/mysql/mysql-slow.log(路径目录得存在,且 MySQL 进程有写权限,否则启动报错或日志静默丢失) -
long_query_time = 1.0(单位秒,支持小数;8.0 对锁等待时间不计入该值,只算纯执行耗时) - 显式加
log_output = FILE(避免之前被设成TABLE导致日志没进文件)
改完后必须执行 systemctl restart mysqld(或 service mysql restart),不能只 reload。
验证配置有没有真起作用
重启后别等业务流量,立刻用 SELECT SLEEP(2); 测试——这是最稳最快的验证方式。然后立刻检查日志文件:tail -n 5 /var/log/mysql/mysql-slow.log。如果看到类似这样的内容:
# Time: 2026-06-09T12:15:22.123456Z # User@Host: root[root] @ localhost [] Id: 12 # Query_time: 2.000123 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1 use test; SELECT SLEEP(2);
说明配置已生效。常见失败原因包括:
-
mysqld --help --verbose | grep "Default options"显示它实际加载的是/etc/my.cnf还是/etc/mysql/my.cnf,很多人改错了文件 - SELinux/AppArmor 拦截写入,
ausearch -m avc -ts recent | grep mysqld可查拒绝记录 -
slow_query_log_file路径的父目录权限不对,MySQL 启动时不会报错,但日志根本不会生成
INSERT/UPDATE 不进慢日志?这是默认行为
MySQL 默认只记录 SELECT,DML 语句(INSERT、UPDATE、DELETE)即使执行超时也不会写进慢日志。这不是 bug,是设计如此。要让它们也被记录,必须额外开启:
-
log_slow_admin_statements = ON(影响ALTER、ANALYZE等管理语句) - 但 DML 本身仍不记录——除非你用的是从库且开了
log_slow_replica_statements = ON(仅限复制场景) - 没有通用开关让所有 DML 进慢日志;如需监控写操作性能,应结合
performance_schema.events_statements_history_long或代理层埋点
最容易被忽略的一点:日志里 Query_time 是执行完成后的总耗时,但 Lock_time 是单独字段,两者不叠加;而你在代码里测的“耗时”往往包含网络往返和客户端解析,和日志里的数值对不上是正常的。











