必须执行show variables like 'slow_query_log'确认返回on才真正启用,否则即使配置文件设置或执行set global也因权限、路径不可写等原因静默失败。

确认 slow_query_log 是否已真正启用
很多问题其实卡在第一步:你以为开了,其实没开。执行 SHOW VARIABLES LIKE 'slow_query_log',返回值必须是 ON 才算生效;如果看到 OFF,哪怕配置文件里写了、也执行过 SET GLOBAL slow_query_log = 'ON',仍可能因权限不足或路径不可写而静默失败。重点检查三件事:slow_query_log_file 指向的路径是否存在、MySQL 进程是否有写权限(比如 /var/log/mysql/ 常因 SELinux 或目录属主问题被拒写);long_query_time 的值是否符合预期(默认 10 秒,线上建议设为 0.5 或 1.0);log_queries_not_using_indexes 别轻易开,它会把所有未走索引的语句都记下来——哪怕只耗时 10ms,日志量可能瞬间爆炸。
用 pt-query-digest 聚合分析原始 slow.log
别打开 slow.log 逐行翻。原始日志里同一条 SQL 因参数不同(如 WHERE id = 123 和 WHERE id = 456)会被当成两条,根本看不出热点。必须用聚合工具:pt-query-digest 是生产首选,它能自动归类、统计执行次数、95% 延迟、全表扫描率,并给出索引建议。运行命令如:pt-query-digest /var/log/mysql/mysql-slow.log --limit 10 > report.txt。注意两个坑:一是该命令需 Percona Toolkit 安装完整,缺依赖会报错;二是若日志路径含空格或特殊字符,必须加引号包裹;三是报告里的 Rows_examined 和 Rows_sent 比值大于 100 倍,基本可断定缺索引或索引失效。
从 EXPLAIN 输出里抓三个致命信号
拿到可疑 SQL 后,直接跑 EXPLAIN,不看其他字段,盯死这三项:type 列出现 ALL(全表扫描),说明完全没走索引;Extra 列出现 Using filesort 或 Using temporary,代表排序或分组被迫在内存/磁盘临时建结构,性能雪崩点;rows 值远高于实际返回行数(比如 rows=98234 但只 SELECT * FROM t LIMIT 10),大概率是联合索引没匹配最左前缀,或统计信息过期(此时可手动执行 ANALYZE TABLE table_name)。特别注意:key_len 值要和你建的索引字段长度对得上,比如 VARCHAR(32) 字段用了 utf8mb4 编码,单字节最多占 4 字节,那 32 字符理论上 key_len 最大是 128 —— 如果实际只有 20,说明索引只用到了前几个字符。
long_query_time 设置后不生效的常见原因
SET GLOBAL long_query_time = 0.5 看似简单,但 MySQL 有个隐藏行为:该变量对**当前会话不生效**,只影响新建立的连接。也就是说,你执行完这条命令后立刻在同一个客户端里跑一条慢 SQL,它不会被记录。验证是否生效,必须新开一个 MySQL 客户端连接,再执行 SHOW VARIABLES LIKE 'long_query_time' 确认值已变;或者直接查 SELECT @@long_query_time。另一个坑是:MySQL 5.7+ 对 long_query_time 的精度支持到微秒级,但设置时传 0.1 可能被截断成 0.100000,而某些旧版本只认整数秒——稳妥起见,线上统一用 0.5 或 1.0,避免小数点后位数引发兼容性问题。











