4. MySQL 慢查询日志:配置、解读与分析工具(pt-query-digest)

慢查询日志是 MySQL 数据库性能诊断的“黑匣子”。当 SQL 执行时间超过预设阈值时,MySQL 会将完整的语句、执行时间、锁等待、扫描行数等信息记录到日志文件中。本章将深入讲解如何正确配置慢查询日志、解读日志中的关键指标,以及使用业界标准工具 pt-query-digest 进行高效分析。

4.1 慢查询日志的配置与最佳实践

慢查询日志的配置涉及多个系统变量,错误的配置可能导致日志文件过大、性能下降或关键 SQL 被遗漏。以下为生产环境推荐配置:

参数名 推荐值 说明
slow_query_log ON 开启慢查询日志
slow_query_log_file /var/log/mysql/slow-query.log 日志文件路径,建议与数据文件分离
long_query_time 0.5 (秒) 执行时间超过 500ms 的 SQL 被记录
log_queries_not_using_indexes ON 记录未使用索引的查询(即使执行很快)
log_slow_admin_statements ON 记录慢管理语句(如 ALTER TABLE)
log_slow_slave_statements ON 从库上记录慢复制语句
min_examined_row_limit 1000 扫描行数超过此值才记录,过滤小查询
生产建议: 在低峰期开启 log_queries_not_using_indexes,避免日志写入压力过大。对于高并发业务,建议将 long_query_time 设置为 0.5~1 秒,并配合 pt-query-digest 定期轮转日志。

4.2 慢查询日志格式深度解读

一条完整的慢查询记录包含以下关键字段,理解这些字段是定位问题的前提:

# Time: 2025-03-15T10:23:45.123456Z
# User@Host: go_app[go_app] @  [10.0.1.100]  Id: 45231
# Query_time: 2.345678  Lock_time: 0.000123  Rows_sent: 10  Rows_examined: 500000
# Thread_id: 45231  Schema: order_db  Last_errno: 0  Killed: 0
# Bytes_sent: 1234  Tmp_tables: 1  Tmp_disk_tables: 0  Tmp_table_sizes: 0
# InnoDB_trx_id: 1234567
# QC_Hit: No  Full_scan: Yes  Full_join: No  Tmp_table: Yes  Tmp_table_on_disk: No
# Filesort: Yes  Filesort_on_disk: No  Merge_passes: 0
#   InnoDB_IO_r_ops: 150  InnoDB_IO_r_bytes: 2457600  InnoDB_IO_r_wait: 0.001234
#   InnoDB_rec_lock_wait: 0.000000  InnoDB_queue_wait: 0.000000
#   InnoDB_pages_distinct: 350
SET timestamp=1742027025;
SELECT o.id, o.order_no, o.amount, u.name
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'pending'
ORDER BY o.created_at DESC
LIMIT 10;
字段 含义 诊断价值
Query_time SQL 实际执行时间(秒) 核心指标,超过阈值即为慢查询
Lock_time 锁等待时间(秒) 高值表示锁竞争严重
Rows_examined 扫描行数 远大于 Rows_sent 时,索引缺失或查询效率低
Rows_sent 返回行数 与 Rows_examined 对比,评估过滤效率
Full_scan 是否全表扫描 Yes 表示未使用索引
Filesort 是否使用文件排序 Yes 表示排序未使用索引,可能消耗大量内存
Tmp_table 是否使用临时表 Yes 表示 GROUP BY 或 DISTINCT 效率低
InnoDB_IO_r_ops InnoDB 读 IO 操作次数 高值表示磁盘 IO 压力大
常见误区: 不要只看 Query_time。一个 Query_time 为 0.1 秒但 Rows_examined 为 100 万的查询,在并发 1000 时会导致 CPU 和 IO 飙升。必须结合 Rows_examined、Full_scan、Filesort 等字段综合判断。

4.3 慢查询日志分析流程

分析慢查询日志应遵循以下步骤,避免盲目优化:

  1. 收集原始日志:使用 mysqldumpslow 或 pt-query-digest 聚合分析。
  2. 识别 TOP N 查询:按总耗时、平均耗时、执行次数排序。
  3. 提取查询指纹:将参数替换为占位符,聚合相同结构的 SQL。
  4. 分析执行计划:对 TOP 查询执行 EXPLAIN,检查索引使用情况。
  5. 定位根因:区分是索引缺失、数据量增长、锁竞争还是配置问题。
  6. 制定优化方案:添加索引、改写 SQL、调整连接池参数或分库分表。
  7. 验证效果:再次分析日志,确认 Query_time 和 Rows_examined 下降。
工程案例: 某 Go 项目订单查询接口响应时间从 200ms 飙升到 3s。通过 pt-query-digest 分析发现,一条 SELECT * FROM orders WHERE status = ? ORDER BY created_at DESC LIMIT 10 的 Rows_examined 从 5000 增长到 200 万。原因是 status 字段区分度低,MySQL 选择了全表扫描。解决方案:创建 (status, created_at) 联合索引,查询时间降至 15ms。

4.4 pt-query-digest 使用详解

pt-query-digest 是 Percona Toolkit 中最强大的慢查询分析工具。它能自动聚合、排序、输出报告,并支持多种输出格式。

4.4.1 安装与基本用法

# 安装 Percona Toolkit(Ubuntu)
sudo apt-get install percona-toolkit

# 分析慢查询日志文件
pt-query-digest /var/log/mysql/slow-query.log

# 分析实时慢查询(从 MySQL 进程列表抓取)
pt-query-digest --processlist h=localhost,u=root,p=your_password

# 分析 tcpdump 抓取的 MySQL 流量
pt-query-digest --type tcpdump /tmp/mysql.pcap

# 输出到指定文件
pt-query-digest /var/log/mysql/slow-query.log > /tmp/analysis.txt

4.4.2 输出报告解读

pt-query-digest 的输出分为三个主要部分:

报告部分 内容 关注点
Overall 总查询数、唯一查询数、总耗时、平均耗时、时间范围 整体负载情况,判断是否需要立即优化
Profile 按总耗时排序的查询指纹列表,包含响应时间占比、执行次数、平均耗时 快速定位 TOP N 问题查询
Query details 每个查询指纹的详细统计:执行时间分布、锁时间、扫描行数、示例 SQL 深入分析单个查询的性能特征
高效使用技巧: 使用 --limit 10 只输出 TOP 10 查询;使用 --filter '$event->{Rows_examined} > 10000' 过滤扫描行数超过 1 万的查询;使用 --since '2025-03-15 10:00:00' --until '2025-03-15 11:00:00' 分析特定时间窗口。

4.5 慢查询日志分析工具对比

工具 优点 缺点 适用场景
mysqldumpslow MySQL 自带,无需安装 功能简单,不支持复杂过滤和输出格式 快速查看 TOP 查询
pt-query-digest 功能强大,支持多种输入源,输出报告详细 需要安装 Percona Toolkit 生产环境深度分析
mysqlsla 轻量级,支持多种日志格式 已停止维护,功能有限 旧系统兼容
Percona Monitoring and Management (PMM) 可视化界面,历史趋势,告警 需要部署服务端,资源消耗较大 企业级监控平台

4.6 慢查询日志与连接池的关联

慢查询日志不仅帮助优化 SQL,还能间接反映连接池的健康状况:

  • 连接池耗尽:当慢查询阻塞连接时,连接池中的连接被长时间占用,导致新请求排队等待。此时慢查询日志中会出现大量 Query_time 正常但 Lock_time 异常的查询。
  • 连接泄漏:如果 Go 应用未正确归还连接,慢查询日志中会出现来自同一 Thread_id 的连续慢查询,且连接数持续增长。
  • 事务超时:长事务导致的慢查询会在日志中显示 InnoDB_trx_id 长时间未提交,配合 SHOW ENGINE INNODB STATUS 可定位事务源头。
排查思路: 当连接池监控显示活跃连接数持续高位时,立即分析慢查询日志。如果发现大量 Rows_examined 极高的查询,优先优化 SQL;如果发现大量 Lock_time 高的查询,优先排查锁竞争和事务隔离级别。
慢查询日志分析流程与连接池关联 慢查询日志 pt-query-digest TOP N 查询 EXPLAIN 分析 索引优化 SQL 改写 连接池监控 连接池参数调优 验证效果 关键关联点 • 慢查询导致连接池连接被 长时间占用 • 连接池参数影响慢查询 的并发执行能力

4.7 本章小结

  • 慢查询日志是 MySQL 性能诊断的基石,正确配置 long_query_time 和 log_queries_not_using_indexes 至关重要。
  • 解读日志时,不能只看 Query_time,必须结合 Rows_examined、Full_scan、Filesort 等字段综合判断。
  • pt-query-digest 是生产环境最推荐的慢查询分析工具,支持多种输入源和灵活的过滤条件。
  • 慢查询日志与连接池监控联动,可以快速定位是 SQL 问题还是连接池配置问题。
  • 优化流程应遵循“收集 → 分析 → 定位 → 优化 → 验证”的闭环,避免盲目添加索引或调整参数。