概述

Docker 环境下使用 pt-query-digest 分析 MySQL 慢查询。

在生产或测试环境中,MySQL 查询变慢往往是性能问题的信号。要精准定位问题,分析慢查询日志是最直接有效的方式。本文介绍如何在 Docker 环境中启用慢查询日志,并使用 pt-query-digest 进行深入分析与优化。

一、前提条件

  • MySQL 运行在 Docker 容器中。
  • 能进入容器或通过挂载访问日志文件。
  • 主机或容器中可使用 pt-query-digest 工具(Percona Toolkit 提供)。

如果 pt-query-digest 尚未安装,可在常见发行版中安装:

1
2
3
4
5
# CentOS / RHEL
yum install -y percona-toolkit

# Debian / Ubuntu
apt install -y percona-toolkit

若系统源中没有,可通过 Percona 官方源安装:

1
2
3
wget https://repo.percona.com/yum/percona-release-latest.noarch.rpm
rpm -ivh percona-release-latest.noarch.rpm
yum install -y percona-toolkit

二、开启 MySQL 慢查询日志

首先确保 MySQL 已启用慢查询日志。

进入容器:

1
docker exec -it mysql-container-name bash

登录 MySQL:

1
mysql -uroot -p

查看慢查询日志状态:

1
2
3
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'slow_query_log_file';
SHOW VARIABLES LIKE 'long_query_time';

如果 slow_query_log 为 OFF,可执行以下命令开启:

1
2
3
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL slow_query_log_file = '/var/lib/mysql/mysql-slow.log';
SET GLOBAL long_query_time = 1; -- 超过 1 秒的查询将记录

建议将这些配置写入 MySQL 配置文件(my.cnf 或 mysqld.cnf),避免容器重启后丢失:

1
2
3
4
5
6
7
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/mysql-slow.log
long_query_time = 1
log_output = FILE
# 可选:记录未使用索引的查询
# log_queries_not_using_indexes = 1

三、拷贝慢查询日志文件

MySQL 的慢查询日志默认保存在容器内 /var/lib/mysql/mysql-slow.log
可以通过以下方式拷贝出来:

1
docker cp mysql-container-name:/var/lib/mysql/mysql-slow.log ./mysql-slow.log

执行后,会在当前目录生成一个 mysql-slow.log 文件,供后续分析使用。

四、使用 pt-query-digest 分析日志

pt-query-digest 是 Percona Toolkit 中非常强大的 SQL 分析工具,它可以对慢查询日志进行统计、聚合和排序,帮助我们快速定位性能瓶颈。

基本用法:

1
pt-query-digest mysql-slow.log > slow-report.txt

执行后,slow-report.txt 中会生成一份详细报告。

五、报告结构解读

典型输出结构如下:

1
2
3
4
5
6
7
8
9
# 123ms user time, 5 system time, 0.45s elapsed
# Time range: 2025-11-13 09:00:00 to 2025-11-13 10:00:00
# Attribute total min max avg 95% stddev median
# Exec time 1.23s 0.001s 0.350s 0.045s 0.200s 0.050s 0.020s
# Rows examine 1.2M 10 50000 3000

# Query 1: 50% of total query time (0.61s)
# ...
SELECT * FROM user_log WHERE user_id = ? AND create_time > ?;

常见关注点:

  • Exec time:执行时间分布,查找最耗时的 SQL。
  • Rows examine:扫描的行数,尽量通过索引减少全表扫描。
  • Query ID:查询的聚合编号,用于快速定位具体 SQL。
  • Count:出现次数,频繁且慢的 SQL 优先优化。

六、优化方向建议

  • 添加合适的索引:重点关注 WHEREORDER BYGROUP BY 涉及字段。
  • 使用 EXPLAIN 分析执行计划:定位全表扫描、回表、Using filesort 等问题。
  • 避免使用 SELECT *:仅查询必要字段,减少数据传输量与行宽。
  • 优化分页与子查询:大分页可改为基于索引的条件翻页或游标。
  • 缓存热点数据:对频繁访问但更新较少的数据,可放入 Redis。
  • 合理设置 long_query_time:建议从 1s 起步,逐步降低以捕获更多慢 SQL。

可搭配示例执行计划查看:

1
2
3
4
5
EXPLAIN ANALYZE SELECT id, user_id, create_time
FROM user_log
WHERE user_id = ? AND create_time > ?
ORDER BY create_time DESC
LIMIT 50;

七、自动化分析脚本(可选)

可以编写简单脚本定期执行分析:

1
2
3
4
5
6
7
8
#!/bin/bash
DATE=$(date +"%Y%m%d_%H%M%S")
LOGFILE="/var/lib/mysql/mysql-slow.log"
REPORT="/opt/reports/slow_report_$DATE.txt"

docker cp mysql-container-name:$LOGFILE /tmp/mysql-slow.log
pt-query-digest /tmp/mysql-slow.log > $REPORT
echo "Slow query report generated: $REPORT"

通过以上步骤即可在容器环境中系统性地捕获和分析慢 SQL,并结合索引、执行计划与缓存策略进行迭代优化。