必须先确认主从状态和权限:slave_io_running与slave_sql_running均为yes、seconds_behind_master≈0、无last_sql_error;主库需replication client+select,从库还需insert/update/delete及lock tables权限;pt-table-sync默认只打印sql,须加--execute才执行,但务必先用--dry-run --print验证语句合理性。

pt-table-sync 修复前必须确认主从状态和权限
不能直接跑 pt-table-sync --execute。先登录从库执行 SHOW SLAVE STATUS\G,盯住三处:如果 Slave_IO_Running 或 Slave_SQL_Running 是 No,说明复制链路已断,此时修复毫无意义;Seconds_Behind_Master 持续大于 60 秒,说明延迟严重,需先压降主库写入或优化从库配置;Last_SQL_Error 出现 Error_code: 1032(行不存在)或 1062(主键重复),才是真实不一致的铁证。
权限方面,工具需要两套账号能力:主库上账号至少要有 REPLICATION CLIENT 和 SELECT(读取 percona.checksums 表);从库上同一账号还需 INSERT、UPDATE、DELETE 权限。别漏掉 LOCK TABLES——某些模式下它会用到,否则报错 Access denied; you need (at least one of) the LOCK TABLES privilege(s)。
为什么 pt-table-sync 不报错却没修数据?
默认行为是只输出 SQL,不执行。很多人看到命令返回就以为修好了,其实只是“打印”而已。必须加 --execute 才真正写库。但更稳妥的做法是先加 --dry-run --print,看它生成的语句是否合理:
- WHERE 条件是否基于主键?非主键表会退化为全表扫描,耗时且易锁表
- 语句类型是否为
REPLACE INTO或DELETE + INSERT?若出现大量UPDATE,说明主键/唯一索引匹配正常;若全是INSERT,可能目标表为空或结构不一致 - 涉及的表是否在
--databases范围内?漏指定会导致部分库被跳过
跨版本迁移(如 MySQL 5.7 → 8.0)还要显式加 --charset=utf8mb4,否则字符集隐式转换会导致哈希比对误判。
目标库表缺失或结构不一致怎么办?
pt-table-sync 完全不处理建库、建表、改字段。它报错 Table 'test.t1' doesn't exist on host 192.168.0.103 或跳过某表,根本原因就是结构没对齐。
补救步骤必须手动完成:
- 源库导结构:
mysqldump -d -h 192.168.0.101 -u root -p test t1 > t1.sql - 目标库导入:
mysql -h 192.168.0.103 -u root -p test - 确认字符集、引擎、索引完全一致,尤其注意
ENGINE=InnoDB和COLLATE=utf8mb4_0900_ai_ci是否匹配 - 联合唯一键表要确保有高选择性索引,否则
pt-table-checksum阶段就会卡在Cannot chunk table because of lack of good index
修复后从库延迟飙升或复制中断了?
这是典型副作用:工具按主库顺序重放修复语句,若差异集中在热点 ID(比如用户余额表里 ID=1001 的几万次 UPDATE),所有语句串行打到同一个页,引发锁竞争和回滚段膨胀。
缓解方法不是关掉并行复制,而是控制节奏:
- 加
--chunk-size=1000限制每次操作行数,避免单次事务过大 - 避开业务高峰,用
--max-load=Threads_running=20设置阈值,超载自动暂停 - 修复大表时,优先用
--replicate模式(依赖percona.checksums),它只处理已知差异块,比 DSN 对比模式快得多 - 修复完成后立刻检查
SHOW PROCESSLIST,确认没有长事务残留
最易被忽略的是:修复完必须验证 Seconds_Behind_Master 是否归零,且持续观察 10 分钟以上——短暂归零可能是假象,真正稳定才算落地。











