2. MySQL 慢查询日志基础:如何开启与核心参数详解

慢查询日志是 MySQL 数据库性能诊断的第一道防线。它记录了执行时间超过指定阈值或未使用索引的 SQL 语句,是定位慢 SQL、优化索引和调整连接池参数的重要依据。本章将详细介绍如何开启慢查询日志,并深入解析 long_query_time 与 log_queries_not_using_indexes 两个核心参数。

2.1 开启慢查询日志

慢查询日志默认是关闭的,需要通过修改 MySQL 配置文件或使用 SET 命令动态开启。推荐在生产环境中同时使用文件记录和系统表 mysql.slow_log 两种方式,以便于分析和监控。

2.1.1 动态开启(无需重启)

-- 开启慢查询日志
SET GLOBAL slow_query_log = ON;

-- 指定日志文件路径(可选,默认在数据目录)
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log';

-- 设置慢查询阈值(单位:秒)
SET GLOBAL long_query_time = 2;

-- 记录未使用索引的查询
SET GLOBAL log_queries_not_using_indexes = ON;

2.1.2 永久开启(写入配置文件)

[mysqld]
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2
log_queries_not_using_indexes = ON
# 记录管理语句(如 ALTER TABLE)
log_slow_admin_statements = ON
# 记录不使用索引的慢语句(即使未达到 long_query_time)
log_throttle_queries_not_using_indexes = 10
建议:在开发/测试环境开启 log_queries_not_using_indexes,在生产环境谨慎使用,避免日志量过大。建议配合 log_throttle_queries_not_using_indexes 限制每分钟记录条数。

2.2 核心参数详解

参数名 默认值 作用域 说明
slow_query_log OFF 全局 是否开启慢查询日志
long_query_time 10.000000 全局/会话 执行时间超过此值的 SQL 被记录(单位:秒,支持微秒)
log_queries_not_using_indexes OFF 全局 是否记录未使用索引的查询(即使执行时间很短)
log_slow_admin_statements OFF 全局 是否记录管理语句(ALTER、CREATE INDEX 等)
log_throttle_queries_not_using_indexes 0 全局 每分钟最多记录多少条未使用索引的查询(0 表示不限制)

2.3 long_query_time:慢查询的“时间红线”

long_query_time 是判断 SQL 是否为慢查询的核心阈值。MySQL 在查询开始计时,在查询结束后判断执行时间是否超过该值。支持微秒精度,例如 0.5 表示 500 毫秒。

  • 单位:秒,支持小数(如 0.1 表示 100ms)
  • 作用域:全局和会话级别。会话级别设置仅影响当前连接。
  • 注意事项:
    • 设置过小(如 0.1)会导致日志量激增,影响磁盘 I/O。
    • 设置过大(如 10)会漏掉大量需要优化的查询。
    • 建议从 1 秒开始,逐步调低,观察日志量变化。
最佳实践:OLTP 业务建议 long_query_time = 1;报表/批处理业务可设为 2~5;微服务高并发场景可设为 0.5~1。

2.4 log_queries_not_using_indexes:索引缺失的“照妖镜”

该参数用于记录那些没有使用索引的查询,即使它们的执行时间很短。这是发现全表扫描、索引设计缺陷的利器。

  • 开启后:所有未使用索引的 SELECT、INSERT、UPDATE、DELETE 都会被记录。
  • 风险:如果表结构简单或数据量小,大量短查询也会被记录,导致日志膨胀。
  • 配合参数:log_throttle_queries_not_using_indexes 可以限制每分钟记录条数,避免日志风暴。
注意:即使查询使用了索引,如果 MySQL 优化器认为索引效率不高(如索引选择性差),也可能被记录。此时需要检查索引质量,而非仅关注是否使用索引。

2.5 慢查询日志记录流程

下图展示了 MySQL 判断一条 SQL 是否写入慢查询日志的完整流程:

慢查询日志记录判断流程 SQL 执行 slow_query_log = ON ? 执行时间 > long_query_time ? log_queries_not_using_indexes = ON ? 写入慢查询日志 说明: 只有同时满足 slow_query_log=ON 且(执行时间超过 long_query_time 或 log_queries_not_using_indexes=ON 且未使用索引)时, SQL 才会被记录。管理语句需要额外开启 log_slow_admin_statements。

2.6 参数配置对比与建议

场景 long_query_time log_queries_not_using_indexes log_throttle 说明
开发环境 0.5 ON 0 全面捕获慢 SQL 和索引问题
测试环境 1 ON 10 限制未使用索引的日志量,避免干扰
生产环境(保守) 2 OFF - 仅记录严重慢查询,减少 I/O 开销
生产环境(优化) 1 ON 5 平衡诊断能力与日志量,配合监控告警

2.7 验证配置是否生效

-- 查看当前慢查询日志状态
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';
SHOW VARIABLES LIKE 'log_queries_not_using_indexes';

-- 手动触发一条慢查询(用于测试)
SELECT SLEEP(3);

-- 查看日志文件(Linux)
tail -f /var/log/mysql/slow-query.log

-- 查看系统表(MySQL 8.0+)
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 5;
提示:使用 mysqldumpslow 工具可以汇总分析慢查询日志,快速找出频率最高、耗时最长的 SQL。