慢查询日志生效需验证变量值为on、全局与会话级一致、slow_queries计数增长、日志路径可写;long_query_time对新连接生效,需重连;log_queries_not_using_indexes须配合min_examined_row_limit防噪音;分析时应优先用pt-query-digest并关注rows_examined/rows_sent比例。

慢查询日志不是“开了就见效”,必须确认它真正在记录你关心的查询——否则花半天分析的日志,可能全是无效噪音或根本没写入。
怎么确认 slow_query_log 确实生效了
很多人改完配置就去查日志,结果空文件。核心问题在于:变量值为 ON 不代表当前连接在记,也不代表路径可写。
- 执行
SHOW VARIABLES LIKE 'slow_query_log',返回值必须是ON(不是1或空) - 再查
SELECT @@global.slow_query_log和SELECT @@session.slow_query_log,两者必须一致;若 session 是OFF,说明当前连接不会记录任何慢 SQL - 执行
SHOW GLOBAL STATUS LIKE 'Slow_queries',初始应为0;运行一次SELECT SLEEP(2)后,该值必须 +1,才是日志链路通了 - 检查
slow_query_log_file路径是否存在、MySQL 进程是否有写权限(XAMPP 下注意 Windows 根目录拦截,Linux 下注意/var/log/mysql/目录属主是否为mysql)
long_query_time 设置后为什么没反应
这个值只对新建立的连接生效,且精度受版本限制——设了 0.5,但旧连接仍按旧值判断,甚至 5.7 版本会四舍五入到 0.1 秒级。
-
SET GLOBAL long_query_time = 0.5后,必须退出当前 MySQL 客户端、重新登录(比如关掉终端再mysql -u root -p),否则SHOW VARIABLES看到的仍是旧值 -
SET SESSION long_query_time = 0.5会报错:MySQL 不支持会话级设置该变量 - 默认值是 10 秒,线上基本无意义;建议先设为
1,观察日志量和典型耗时分布,再逐步下调 - 设为
0会记录所有查询(含SELECT 1),极易撑爆磁盘,仅限临时诊断
log_queries_not_using_indexes 开启后日志爆炸怎么办
这个开关一开,哪怕 WHERE id = -1 这种恒不成立的查询,只要没走索引,也会被记——大量低危害全表扫描混在里面,掩盖真正的问题 SQL。
- 必须同步设置
min_examined_row_limit = 100(或更高,如 500),表示“未走索引且扫描行数 ≥ 100 才记录” -
min_examined_row_limit在 MySQL 5.7+ 支持动态设置,但部分云厂商定制版禁用,生产环境建议直接写进配置文件并重启 -
log_queries_not_using_indexes = ON本身不能替代long_query_time,它记录的是“隐性慢”(快但不该快),不是“显性慢”(真超时) - 调试阶段建议先关掉它(
= OFF),等定位到真实慢 SQL 后,再打开辅助找索引缺失点
分析日志时最常踩的时间精度坑
MySQL 5.7+ 默认把 Query_time 记到微秒级,例如 Query_time: 1.234567,看着像 1.2 秒,其实是 1.234567 秒——老工具会截断或解析失败。
- 用
head -n 5 /var/log/mysql/mysql-slow.log看第一行有没有microseconds字样,确认格式 -
mysqldumpslow遇到微秒日志容易漏统计,加--verbose或升级到 MySQL 8.0.22+ 更稳 - 更推荐用
pt-query-digest,它自动适配各种时间精度,还能聚合指纹、给出索引建议,不依赖人工肉眼扫 - 别只信
Query_time,重点看Rows_examined和Rows_sent比例——如果扫了 10 万行只返 1 行,多半是索引没用对或条件写错了
真正难的不是开启日志,而是让每条记录都指向可优化的具体 SQL:阈值要匹配业务响应预期,路径权限得提前验证,min_examined_row_limit 得和 log_queries_not_using_indexes 配合使用,否则日志要么为空,要么满屏噪音。











