第 48 章

Percona Toolkit 实战

Percona Toolkit — DBA 必备工具集

Percona Toolkit 是 MySQL DBA 最重要的开源工具集,由 Percona 维护,包含 30+ 工具,覆盖性能分析、在线 DDL、数据一致性验证、数据归档等场景。本章介绍最常用的 5 个工具。

1. 安装

# Ubuntu/Debian
wget https://downloads.percona.com/downloads/percona-toolkit/3.5.x/binary/debian/focal/x86_64/percona-toolkit_3.5.x_amd64.deb
dpkg -i percona-toolkit_3.5.x_amd64.deb

# RHEL/CentOS
yum install -y https://downloads.percona.com/downloads/percona-toolkit/3.5.x/binary/redhat/7/x86_64/percona-toolkit-3.5.x-1.el7.x86_64.rpm

# macOS(Homebrew)
brew install percona-toolkit

# 验证安装
pt-query-digest --version

2. pt-query-digest — 慢查询日志分析

pt-query-digest 最常用

分析 MySQL 慢查询日志、General Log、Binlog,按查询模式聚合统计,快速找到性能热点。

# 基本分析:按 Query_time 总和排序(最关键视角)
pt-query-digest /var/log/mysql/slow.log \
  --limit 20 \
  --order-by Query_time:sum

# 只看最慢的前 5 条(单次执行时间)
pt-query-digest /var/log/mysql/slow.log \
  --limit 5 \
  --order-by Query_time:max

# 过滤:只分析某个数据库
pt-query-digest /var/log/mysql/slow.log \
  --filter '$event->{db} eq "mydb"' \
  --limit 20

# 过滤:只看执行超过 5 秒的查询
pt-query-digest /var/log/mysql/slow.log \
  --filter '$event->{Query_time} >= 5' \
  --limit 20

# 输出到文件(便于后续分析)
pt-query-digest /var/log/mysql/slow.log > /tmp/slow_report.txt

# 直接分析正在运行的 MySQL(实时 SHOW PROCESSLIST)
pt-query-digest --processlist h=localhost,u=root,p=password \
  --interval 1 \
  --run-time 60  # 抓取 60 秒

# 分析 Binlog(找高频写入查询)
mysqlbinlog /var/lib/mysql/binlog.000001 | pt-query-digest --type binlog

输出解读:

# pt-query-digest 输出关键字段:
# Rank: 排名(按 Query_time sum 降序)
# Query ID: 查询指纹哈希
# Response time: 总耗时(占比)
# Calls: 执行次数
# R/Call: 平均耗时/次
# V/M: 方差/均值(波动大说明执行计划不稳定)
# Item: 查询样本

# 示例输出片段:
# Rank  Query ID           Response time   Calls   R/Call   V/M   Item
# ====  =================  ==============  =====   =======  ====  ====
#    1  0x89A1A40AFAF4AF0E  1234.5678  45%  56789  0.0217   0.01  SELECT orders WHERE user_id=?

3. pt-online-schema-change(pt-osc)— 在线 DDL

pt-online-schema-change 高风险操作必用

对大表执行 DDL 变更而不锁表、不影响正常读写。原理:创建新表 → 复制数据 → 交换表名。

# 场景:给 1 亿行的 orders 表添加索引(不锁表)
pt-online-schema-change \
  --host=localhost \
  --user=root \
  --password=password \
  --database=mydb \
  --table=orders \
  --alter="ADD INDEX idx_created (created_at)" \
  --execute \
  --chunk-size=5000 \          # 每批复制行数(根据写入压力调整)
  --max-load="Threads_running=25" \  # 负载超此值暂停
  --critical-load="Threads_running=50" \  # 超此值中止
  --sleep=0.5 \                # 每批间隔(降低 I/O 压力)
  --progress=time,30           # 每 30 秒打印进度

# 场景:修改列类型(VARCHAR 50 → VARCHAR 100)
pt-online-schema-change \
  --host=localhost -u root -p password \
  --alter="MODIFY COLUMN name VARCHAR(100) NOT NULL" \
  D=mydb,t=users \
  --execute

# 场景:删除列
pt-online-schema-change \
  --alter="DROP COLUMN legacy_field" \
  D=mydb,t=users \
  --execute

# 先模拟(不实际执行),检查是否可行
pt-online-schema-change \
  --alter="ADD INDEX idx_test (col1)" \
  D=mydb,t=orders \
  --dry-run  # 不加 --execute,只打印计划

**注意事项:**① 触发器会被 pt-osc 复制,若表已有触发器需特殊处理 ② 外键约束需要加 --alter-foreign-keys-method=rebuild_constraints ③ 复制过程中磁盘空间需要足够(额外一份表大小)④ 目标表必须有主键

**pt-osc vs gh-ost:**两者功能相似,gh-ost(GitHub 开源)基于 Binlog 而非触发器,对主库压力更小,复制更安全,推荐大型生产环境使用 gh-ost。

4. pt-table-checksum — 主从数据一致性验证

pt-table-checksum 复制运维必备

通过 Binlog 在主从两端分别计算 checksum,验证主从数据是否一致。

# 检查所有数据库的主从一致性
pt-table-checksum \
  --host=主库IP \
  --user=root \
  --password=password \
  --databases=mydb \
  --replicate=percona.checksums  # checksum 结果写入此表,从库读取对比

# 检查完成后查看不一致的表
SELECT db, tbl, chunk, master_cnt, this_cnt, master_crc, this_crc
FROM percona.checksums
WHERE master_cnt != this_cnt OR master_crc != this_crc
  OR ISNULL(master_crc) != ISNULL(this_crc);

# 配合 pt-table-sync 修复不一致数据
pt-table-sync \
  --execute \
  --replicate=percona.checksums \
  h=主库IP,u=root,p=password \
  h=从库IP  # 将主库数据同步到从库

5. pt-archiver — 数据归档

pt-archiver 大表数据清理

低影响地将数据从一张表移动或删除,支持限速、批量大小控制、断点续传。

# 场景:归档 2 年前的订单到历史表(主库写,归档到从库读的历史表)
pt-archiver \
  --source  h=主库,D=mydb,t=orders,u=root,p=password \
  --dest    h=历史库,D=archive,t=orders_history,u=root,p=password \
  --where   "created_at < '2022-01-01'" \
  --limit   1000 \            # 每次处理 1000 行
  --sleep   0.1 \             # 每批暂停 0.1 秒
  --no-delete \               # 只复制,不删除源数据(先验证归档正确性)
  --progress 5000             # 每 5000 行打印进度

# 场景:直接删除 2 年前的日志数据(无归档需求)
pt-archiver \
  --source  h=localhost,D=mydb,t=access_logs,u=root,p=password \
  --where   "created_at < '2022-01-01'" \
  --limit   5000 \
  --sleep   0.05 \
  --purge                     # 只删除,不归档

6. pt-kill — 查询管理

# 杀掉运行超过 60 秒的 SELECT 查询(只打印,不真正 kill)
pt-kill \
  --host=localhost -u root -p password \
  --match-command Query \
  --match-info "^SELECT" \
  --busy-time 60 \
  --print

# 真正 kill(去掉 --print,加 --kill)
pt-kill \
  --host=localhost -u root -p password \
  --match-command Query \
  --busy-time 60 \
  --kill \
  --interval 5 \  # 每 5 秒检查一次
  --run-time 3600  # 运行 1 小时(用于临时应急)

# 杀掉 Waiting for lock 超过 30 秒的查询
pt-kill \
  --host=localhost -u root -p password \
  --match-state "Waiting for table" \
  --busy-time 30 \
  --kill

7. 其他常用工具

工具 用途
pt-duplicate-key-checker 检查表中重复/冗余索引
pt-index-usage 分析哪些索引从未被使用(基于 General Log)
pt-show-grants 将用户权限输出为可复现的 GRANT 语句
pt-mysql-summary 生成 MySQL 实例全面的诊断报告
pt-summary 生成服务器硬件/OS 配置报告
pt-config-diff 对比两台 MySQL 实例的配置差异
pt-slave-delay 人为延迟从库(用于误操作恢复)
pt-heartbeat 精确测量主从复制延迟
本章评分
4.6  / 5  (3 评分)

💬 留言讨论