必须改配置文件并重启才持久生效,set global仅对新连接临时有效;确认开启需查三要素:@@slow_query_log为1、@@slow_query_log_file路径存在且mysql用户有写权限、@@long_query_time设为合理浮点值(如1.0),再用select sleep(2)实测日志是否生成。

必须改配置文件并重启,只执行 SET GLOBAL 命令无法持久生效,且对已存在的连接无效。
确认当前慢查询日志是否真开启
别只看 slow_query_log 变量是 ON 就以为日志在写——它可能根本没路径、没权限、没重启。先查三件事:
-
SELECT @@slow_query_log, @@slow_query_log_file, @@long_query_time;—— 如果slow_query_log_file是空或默认值(如/var/lib/mysql/host-slow.log),大概率不会落盘 -
SHOW GLOBAL STATUS LIKE 'Slow_queries';—— 这个计数器为 0,说明日志逻辑压根没触发,不是“没慢 SQL”,而是“压根没记” -
ls -l $(dirname $(mysql -Nse "SELECT @@slow_query_log_file"))—— 看目录是否存在、MySQL 用户(通常是mysql)是否有写权限
my.cnf 中必须同时配齐这三项才生效
只写 slow_query_log = 1 不够,只写 slow_query_log_file 路径也不行。MySQL 5.7 要求三者共存且都在 [mysqld] 段下:
-
slow_query_log = 1—— 必须是数字1或ON,YES会报错 -
slow_query_log_file = /var/log/mysql/mysql-slow.log—— 必须用绝对路径,且确保/var/log/mysql/目录存在、属主为mysql、权限至少755 -
long_query_time = 1.0—— 生产环境建议从1.0起步;设为0仅限临时诊断,会导致日志爆炸
注意:log_output = TABLE 是另一条路(写进 mysql.slow_log 表),但会加重 Innodb 刷脏页压力,线上慎用;默认 FILE 才是安全选择。
验证日志是否真实生成的最简方法
别等业务跑出慢 SQL 再观察——主动制造一条可复现的慢查询:
- 执行
SELECT SLEEP(2);(前提是long_query_time≤ 2) - 立刻检查日志文件:
tail -n 3 /var/log/mysql/mysql-slow.log,应看到类似:
# Time: 2026-06-03T09:20:15.123456 # User@Host: root[root] @ localhost [] # Query_time: 2.000123 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1 use test; SELECT SLEEP(2);
如果没内容,优先检查:mysqld.err 里有没有 Failed to write to slow log 提示;或者用 strace -p $(pgrep mysqld) -e trace=write,openat 看 MySQL 进程是否尝试写该路径。
分析日志时最容易被忽略的三个字段
很多人只扫 Query_time,但真正定位瓶颈得盯住:
-
Lock_time:如果接近Query_time,说明卡在锁等待(如行锁、MDL),不是 SQL 本身问题 -
Rows_examined和Rows_sent的比值:比如Rows_examined: 98765,Rows_sent: 1,基本就是全表扫描+没走索引 -
# Time:时间戳:这是语句**开始执行**时间,不是日志写入时间,可用于和应用端埋点对齐
微秒精度(如 Query_time: 1.234567)在 MySQL 5.7+ 是默认行为,老版 mysqldumpslow 会截断小数,推荐直接用 pt-query-digest /var/log/mysql/mysql-slow.log,它自动适配且带索引优化建议。











