不能盲目执行。pt-table-sync 默认只输出 SQL 不执行,需加 --execute;须确认主库唯一写入,否则修复语句可能错误;建议先用 --dry-run + --print 验证,注意 WHERE 是否基于主键,跨版本同步需显式指定 --charset=utf8mb4。

主从数据不一致时,pt-table-sync 能直接修复吗?
不能盲目执行。它默认只输出 SQL 语句,不真正执行,除非显式加 --execute。很多运维在没加这个参数的情况下以为“已经修好了”,结果查了一圈发现数据还是错的。
- 必须确认主库是唯一写入源,否则从库写入会导致
pt-table-sync生成错误的反向修复语句 - 建议先用
--dry-run+--print看它打算怎么修,尤其注意 WHERE 条件是否基于主键(非主键表会退化为全表扫描比对) - 跨版本同步(如 MySQL 5.7 → 8.0)可能因默认字符集或隐式类型转换导致比对误判,需加
--charset=utf8mb4显式指定
校验阶段为什么 pt-table-checksum 报 Cannot chunk table because of lack of good index
这是最常见的卡点:工具需要高效分块遍历表,若表没有单列、非空、有索引的整数型主键或唯一键,就会失败。
- 临时解法是加
--chunk-index指定一个合适的索引,但该索引必须满足“高选择性+无 NULL”——比如created_at时间戳索引通常不行,因为大量重复值 - 长期方案是给大表补一个自增
id主键,或者把联合唯一键拆成覆盖索引(如(user_id, order_no)上建KEY idx_user_order (user_id, order_no)) - 跳过该表校验不是好主意:
--ignore-table只是掩耳盗铃,后续pt-table-sync也不会处理它
pt-table-sync 修复后,从库延迟反而飙升了怎么办?
因为它默认按主库顺序重放修复 SQL,如果差异集中在热点行(比如用户余额表里某几个 ID),所有 UPDATE 都串行打到同一个分区/页上,锁竞争剧烈。
- 加
--algorithms=Chunk强制走分块模式,避免单条大事务;再配--chunk-size=1000控制每批量级 - 避开业务高峰执行,且务必监控
Seconds_Behind_Master和SHOW PROCESSLIST中的Waiting for table metadata lock - 如果从库启用了
read_only=ON,确保你连接时用的是有SUPER权限的账号,否则SET SESSION sql_log_bin=0会失败
为什么 pt-table-sync 说“no differences found”,但实际查几条数据就是错的?
大概率是字符集或排序规则不一致,导致比对时字符串被隐式转换,表面相等实则不同。
- 检查主从库的
character_set_database和collation_database是否完全一致,特别注意utf8mb4_unicode_ci和utf8mb4_0900_as_cs在 MySQL 8.0 下行为差异极大 - 用
SELECT HEX(col) FROM tbl WHERE ...对比二进制值,比SELECT col更可靠 -
pt-table-checksum默认跳过TEXT/BLOB列,如果关键字段是这类类型,得加--columns显式包含,并确认从库对应列定义长度足够(比如主库TEXT,从库误写成VARCHAR(255))
真正麻烦的不是工具不会用,而是主从之间那些没暴露出来的隐式不一致——比如某个时间点手动改过从库、或者 binlog_format 混用 STATEMENT 和 ROW。这些没法靠一次 sync 解决,得翻 binlog 找源头。


















