第 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 |
精确测量主从复制延迟 |