讲解

慢查询日志(slow query log)把执行时间超过阈值的 SQL 记录下来,是定位性能问题的第一入口。核心参数就两个:slow_query_log 开关、long_query_time 阈值(秒,默认 10,生产上常设为 0.5 到 2)。还有一个补充参数 log_queries_not_using_indexes,把「没用索引」的查询也记下来,哪怕它很快——没用索引的查询在小表上快,表一大就变慢,提前抓住它们是防患于未然。

日志输出由 log_output 控制:FILE 写到文件(默认,生产用法),TABLE 写到 mysql.slow_log 表里——TABLE 模式方便用 SQL 直接分析,教学演示特别合适,但高并发下写表有额外开销,生产环境别长期开着。分析日志文件的标配工具是 mysqldumpslow(按模式聚合、按时间/次数排序),更专业的是 Percona 的 pt-query-digest。

慢日志里每条记录的关键信息:执行时间 query_time、锁等待时间 lock_time、扫描行数 rows_examined、返回行数 rows_sent。诊断时重点看 rows_examined 远大于 rows_sent 的查询——扫了一万行只返回十行,十有八九是缺索引或条件写法让索引失效。配合上一章的 EXPLAIN,就能完成「发现慢查询 → 分析原因 → 加索引或改写」的完整闭环。

示例

先看当前慢查询日志的配置状态:

SHOW VARIABLES LIKE 'slow_query_log%';

SHOW VARIABLES LIKE 'long_query_time';

开启慢日志并切到 TABLE 输出,把本会话阈值降到 0.1 秒,人为制造一条「慢查询」再查出来(long_query_time 对当前会话要用 SET SESSION 设置):

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL log_output = 'TABLE';
SET SESSION long_query_time = 0.1;

DO SLEEP(0.3);

SELECT start_time, query_time, lock_time, rows_examined,
       CONVERT(sql_text USING utf8mb4) AS sql_text
FROM mysql.slow_log
ORDER BY start_time DESC
LIMIT 3;

用完恢复默认配置并清空演示数据——生产环境也应按需开关,别长期全量记录:

SET GLOBAL slow_query_log = 'OFF';
SET GLOBAL long_query_time = 10;
SET GLOBAL log_output = 'FILE';

TRUNCATE TABLE mysql.slow_log;

常见坑

  • SET GLOBAL 之后当前会话不生效:long_query_time 这类参数改了 GLOBAL 只影响新连接,当前会话要用 SET SESSION 单独设。排查「明明开了却没记录」先看这一条。
  • long_query_time 设成 0:记录所有查询,高峰期日志暴涨、写日志本身变成负担。给合理的阈值,聚焦真正的慢查询。
  • 只看执行次数不看扫描行数:一条查询快但 rows_examined 巨大,是「还没变慢」的隐患。配合 log_queries_not_using_indexes 提前发现。
  • 在生产长期开 TABLE 输出:写 mysql.slow_log 表有锁开销,高并发下会拖慢正常业务。教学演示完就关,生产用 FILE 输出。

小结

慢查询日志 = slow_query_log + long_query_time,FILE 输出给生产、TABLE 输出方便分析;关注 rows_examined 远大于 rows_sent 的查询。下一章讲权限:谁能连、能做什么。