慢查询日志未开启或未生效是线上慢SQL排查失败的最常见原因,需确认slow_query_log为ON、long_query_time设为1.0、log_queries_not_using_indexes配合log_throttle_queries_not_using_indexes使用,并优先选择file输出方式。

慢查询日志没开,或者开了但没生效,是线上慢SQL排查失败最常见的原因。 不是SQL写得不够差,而是日志根本没抓到——你查的压根不是真实慢的那条语句。
确认 slow_query_log 是否真的 ON
别信配置文件写了就完事。MySQL 启动时读取配置,但中间可能被 SET GLOBAL 覆盖,也可能权限不足导致写日志失败。最直接的办法是进数据库执行:
SHOW VARIABLES LIKE 'slow_query_log';
返回 ON 才算真正启用;如果返回 OFF,哪怕 my.cnf 里写了 slow_query_log = 1,也白搭。常见原因包括:
- 改了 my.cnf 但没重启 MySQL(永久配置必须重启)
- 执行过
SET GLOBAL slow_query_log = OFF,覆盖了配置文件设置 - MySQL 进程用户(如
mysql)对slow_query_log_file指定路径无写权限,日志静默失败
long_query_time 设为 1.0 而不是 0 或 10
long_query_time 是浮点数,设成 1 和 1.0 效果一致,但设成 0 会记录所有查询(含毫秒级),日志爆炸式增长,磁盘很快打满;设成默认 10 则绝大多数生产慢 SQL(2~5 秒)根本不会被捕获。
执行命令验证当前值:
SHOW VARIABLES LIKE 'long_query_time';
生产环境建议设为 1.0,压测或紧急排查时可临时调低至 0.5。注意:SET GLOBAL long_query_time = 0.5 只对**新建立的连接**生效,已有连接仍用旧值。
log_queries_not_using_indexes 要开,但得配 log_throttle_queries_not_using_indexes
开启 log_queries_not_using_indexes = ON 能捕获“快但危险”的 SQL —— 比如小表全表扫描,现在不慢,数据量涨十倍就崩。但它极易引发日志刷屏,尤其在高频低数据量查询场景。
必须配套限制频率,否则日志文件每秒写入几百行,mysqldumpslow 都解析不动:
-
SET GLOBAL log_throttle_queries_not_using_indexes = 3;表示每秒最多记录 3 条无索引查询 - 该参数仅在 MySQL 5.6.5+ 支持,8.0 默认可用
- 若版本太老不支持,宁可关掉
log_queries_not_using_indexes,也不要让它失控
日志输出选 file 还是 table?优先用 file
虽然 log_output = 'TABLE'(写入 mysql.slow_log 表)看起来方便查,但实际问题很多:
- 每次写日志都要走 SQL 引擎、事务、锁,高并发下反而拖慢 MySQL 自身
-
mysql.slow_log默认是 CSV 引擎,不支持索引,几万行后SELECT * FROM mysql.slow_log本身变慢 SQL - 部分云 RDS(如阿里云 PolarDB)禁用该表写入,强制走文件
推荐坚持用文件输出:slow_query_log_file = /var/log/mysql/mysql-slow.log,再配合 pt-query-digest 或 mysqldumpslow 分析。路径务必提前 chown mysql:mysql /var/log/mysql 并 chmod 755,否则 MySQL 启动时跳过日志初始化。
真正卡住人的从来不是怎么写 SQL,而是日志压根没记下来——路径没权限、阈值设太高、变量被覆盖、工具选错输出方式,这些细节一错,后面所有 EXPLAIN 和索引优化都是空中楼阁。


















