3. 慢查询日志分析工具:mysqldumpslow 与 pt-query-digest
MySQL 慢查询日志记录了执行时间超过 long_query_time 阈值的 SQL 语句。面对动辄数百 MB 甚至 GB 级别的原始日志,人工逐条分析几乎不可能。本章介绍两款最常用的慢查询日志分析工具:MySQL 官方自带的 mysqldumpslow 和 Percona 工具包中的 pt-query-digest,涵盖安装、基本用法和输出解读。
3.1 工具对比与选型
| 特性 | mysqldumpslow | pt-query-digest |
|---|---|---|
| 来源 | MySQL 官方自带(Perl 脚本) | Percona Toolkit(需单独安装) |
| 安装复杂度 | 零安装,随 MySQL 发布 | 需安装 perl 依赖及工具包 |
| 分析粒度 | 按 SQL 指纹聚合,输出摘要 | 按查询指纹聚合,支持多种输出格式 |
| 排序方式 | 支持按平均/总查询时间、锁时间、返回行数排序 | 支持按总耗时、平均耗时、响应时间占比、执行次数排序 |
| 输出格式 | 纯文本 | 文本、JSON、YAML、HTML 等 |
| 过滤能力 | 有限(按时间范围、正则) | 强大(按数据库、用户、查询模式、时间范围等) |
| 适用场景 | 快速查看、日常巡检、MySQL 原生环境 | 深度分析、报告生成、自动化监控集成 |
选型建议:日常快速排查使用
mysqldumpslow;需要生成详细报告、对接监控系统或进行复杂过滤时,优先使用 pt-query-digest。
3.2 mysqldumpslow 安装与使用
3.2.1 安装确认
mysqldumpslow 是 Perl 脚本,通常位于 MySQL 安装目录的 bin/ 子目录下。确认方式:
# 查找 mysqldumpslow 路径
which mysqldumpslow
# 或
find /usr -name "mysqldumpslow" 2>/dev/null
# 查看帮助
mysqldumpslow --help
如果系统提示找不到命令,可尝试从 MySQL 安装目录的 support-files/ 或 scripts/ 目录下查找并复制到 PATH 中。
3.2.2 常用参数
| 参数 | 说明 | 示例 |
|---|---|---|
-s |
排序方式:t(查询时间)、l(锁时间)、r(返回行数)、c(执行次数) |
-s t |
-t |
只显示前 N 条 | -t 10 |
-g |
按正则过滤 SQL 内容 | -g "SELECT.*user" |
-a |
不将数字抽象为 N,字符串抽象为 S | -a |
--verbose |
显示更详细的信息 | --verbose |
3.2.3 典型用法
# 按平均查询时间降序,显示前 5 条
mysqldumpslow -s t -t 5 /var/log/mysql/slow-query.log
# 按执行次数降序,显示前 10 条
mysqldumpslow -s c -t 10 /var/log/mysql/slow-query.log
# 过滤包含特定表的慢查询
mysqldumpslow -g "orders" /var/log/mysql/slow-query.log
# 保留原始数字和字符串(不抽象)
mysqldumpslow -a -s t -t 20 /var/log/mysql/slow-query.log
3.2.4 输出解读
mysqldumpslow 的输出格式如下:
Count: 123 Time=2.34s (288s) Lock=0.01s (1.23s) Rows=100.0 (12300), root[root]@localhost
SELECT * FROM orders WHERE status = 'S' AND create_time BETWEEN N AND N ORDER BY id DESC LIMIT N
- Count:该 SQL 指纹的执行次数。
- Time:平均执行时间(秒),括号内为总耗时。
- Lock:平均锁等待时间,括号内为总锁时间。
- Rows:平均返回行数,括号内为总返回行数。
- 用户@主机:执行该查询的用户和客户端主机。
- SQL 语句:经过抽象后的 SQL 模板(数字被替换为 N,字符串被替换为 S)。
3.3 pt-query-digest 安装与使用
3.3.1 安装 Percona Toolkit
pt-query-digest 是 Percona Toolkit 的核心工具之一。安装方式:
# CentOS / RHEL
yum install percona-toolkit
# Ubuntu / Debian
apt-get install percona-toolkit
# 或从官网下载 RPM/DEB 包手动安装
wget https://downloads.percona.com/downloads/percona-toolkit/3.5.5/binary/redhat/7/x86_64/percona-toolkit-3.5.5-1.el7.x86_64.rpm
rpm -ivh percona-toolkit-3.5.5-1.el7.x86_64.rpm
# 验证安装
pt-query-digest --version
依赖注意:Percona Toolkit 依赖 Perl 及若干 CPAN 模块(如 DBD::mysql、Time::HiRes 等)。如果安装过程中提示缺少模块,可使用
cpan 或系统包管理器安装对应 perl 模块。
3.3.2 常用参数
| 参数 | 说明 | 示例 |
|---|---|---|
--limit |
限制输出前 N 条查询 | --limit=20 |
--order-by |
排序依据:Query_time:sum、Query_time:avg、Exec_count 等 |
--order-by=Query_time:sum |
--filter |
使用 Perl 表达式过滤查询 | --filter '$event->{db} eq "mydb"' |
--since / --until |
按时间范围过滤 | --since '2024-01-01 00:00:00' --until '2024-01-02 00:00:00' |
--type |
输入类型:slowlog、general-log、binlog、tcpdump 等 |
--type slowlog |
--output |
输出格式:report(默认)、json、yaml、html |
--output json |
--review |
将分析结果存入数据库表,便于历史对比 | --review h=localhost,D=percona,t=query_review |
3.3.3 典型用法
# 基本分析,按总耗时排序,显示前 10 条
pt-query-digest --limit=10 --order-by=Query_time:sum /var/log/mysql/slow-query.log
# 分析指定数据库的慢查询
pt-query-digest --filter '$event->{db} eq "ecommerce"' /var/log/mysql/slow-query.log
# 分析指定时间段的慢查询
pt-query-digest --since '2024-06-01 00:00:00' --until '2024-06-30 23:59:59' /var/log/mysql/slow-query.log
# 输出 JSON 格式,便于程序处理
pt-query-digest --output json /var/log/mysql/slow-query.log > slow_report.json
# 从 MySQL 进程列表直接分析(实时)
pt-query-digest --processlist h=localhost,u=root,p=password
3.3.4 输出解读
pt-query-digest 的输出分为三个主要部分:
- Overall:全局统计信息,包括总查询数、总耗时、唯一查询指纹数、时间范围等。
- Profile:按响应时间占比排序的查询指纹列表,每行显示占比、执行次数、平均耗时、标准差等。
- Query details:每个查询指纹的详细分析,包括样本 SQL、执行计划建议、响应时间分布直方图等。
关键指标:关注 Profile 中
Response time ratio(响应时间占比)最高的查询,它们通常是系统瓶颈。结合 Rows examine(扫描行数)和 Rows sent(返回行数)的比值,可判断是否存在全表扫描或索引缺失。
3.4 分析流程与最佳实践
下图展示了从慢查询日志采集到问题定位的完整分析流程:
3.5 实战案例:快速定位 TOP 慢查询
假设某电商平台数据库出现响应延迟,DBA 执行以下步骤快速定位问题:
# 步骤1:使用 mysqldumpslow 快速查看 TOP 10 慢查询
mysqldumpslow -s t -t 10 /var/log/mysql/slow-query.log
# 输出显示:
# Count: 456 Time=3.21s (1464s) Lock=0.02s (9.12s) Rows=500.0 (228000), root[root]@localhost
# SELECT o.id, o.total_amount, u.name FROM orders o
# JOIN users u ON o.user_id = u.id
# WHERE o.status = 'S' AND o.create_time BETWEEN N AND N
# ORDER BY o.create_time DESC LIMIT N
# 步骤2:使用 pt-query-digest 获取该查询的详细分析
pt-query-digest --filter '$event->{fingerprint} =~ m/SELECT.*orders.*users/' \
/var/log/mysql/slow-query.log > order_slow_detail.txt
# 步骤3:查看分析报告中的 Query details 部分,关注:
# - 扫描行数 (Rows examine) 是否远大于返回行数 (Rows sent)
# - 响应时间分布直方图
# - EXPLAIN 建议
实战要点:
- 先用
mysqldumpslow -s t -t 5快速定位最耗时的查询指纹。 - 再用
pt-query-digest --filter对特定查询进行深度分析。 - 结合
EXPLAIN和SHOW PROFILE进一步确认索引使用情况和执行计划。 - 定期(如每天)运行 pt-query-digest 并将结果存入
--review表,便于趋势分析。
3.6 常见问题与避坑
| 问题 | 原因 | 解决方案 |
|---|---|---|
| mysqldumpslow 输出为空 | 慢查询日志路径错误或日志为空 | 检查 slow_query_log_file 变量,确认日志文件存在且非空 |
| pt-query-digest 报 DBD::mysql 错误 | 缺少 Perl MySQL 驱动 | yum install perl-DBD-MySQL 或 apt-get install libdbd-mysql-perl |
| 分析结果中 SQL 被抽象过度 | mysqldumpslow 默认将数字替换为 N,字符串替换为 S | 使用 -a 参数保留原始值 |
| pt-query-digest 分析大文件耗时过长 | 日志文件过大(数 GB) | 使用 --since 和 --until 缩小时间范围,或先按天分割日志 |
| 慢查询日志轮转后分析中断 | 日志文件被重命名或删除 | 配置 MySQL 的 log_slow_rotate 或使用 pt-query-digest --review 增量分析 |
重要提醒:在生产环境开启慢查询日志时,务必设置合理的
long_query_time(建议 1~2 秒)和 log_queries_not_using_indexes,避免日志量过大影响磁盘 I/O。同时配置日志轮转策略,防止磁盘空间被写满。