pt-table-checksum不是开箱即用工具,必须满足主库row格式、校验用户权限、表有主键或唯一非空索引等前置条件,且需显式指定连接主库、库名、checksum表位置等关键参数,否则结果无效或失败。

直接跑 pt-table-checksum 默认参数几乎一定会出问题——它不是“迁移完执行一下就出报告”的工具,而是需要你明确约束校验范围、规避权限和结构缺陷、并理解结果含义的诊断型命令。
必须先确认主库 binlog_format 和权限是否达标
工具运行失败或结果无效,80% 出在前置条件没满足。它必须连接主库(不是目标库),且主库需满足:
-
binlog_format = ROW是硬性要求;若为MIXED或STATEMENT,不加--no-check-binlog-format会直接退出 - 校验用户至少要有:
SELECT、PROCESS、SUPER(或REPLICATION CLIENT),以及对percona.checksums表的INSERT/UPDATE/DELETE - 所有待校验表必须有主键或唯一非空索引;否则报错
Cannot chunk table without a primary key or unique not null index,且该表会被跳过 - 目标库(迁移后库)必须能通过复制链路同步到
percona.checksums表的写入(即不能是只读库,也不能 SQL_THREAD 停止)
小表用 CHECKSUM TABLE 更快,大表才上 pt-table-checksum
别一上来就堆工具。千万行以内的表,CHECKSUM TABLE 直接比对整表 CRC32 最省事;但要注意它的局限:
- 执行时会对表加读锁,高峰期慎用;建议先在从库或低峰期验证
- 含
FLOAT/DOUBLE字段时,因浮点精度表现可能跨版本不一致,容易误报差异 - 它只校验数据行,不包含索引、
AUTO_INCREMENT值、字符集隐式转换等逻辑差异 - 真正要定位“哪几行不一致”,必须用
pt-table-checksum分块机制
关键参数不设等于白跑
默认参数下,pt-table-checksum 可能扫全库、锁太久、被负载中断、甚至跳过你关心的表。最小安全组合应显式指定:
-
--host=master_ip --port=3306 --user=check_user --password=xxx:连接主库,非目标库 -
--databases=mydb:限定库名,避免意外扫描系统库;多库用逗号分隔 -
--replicate=percona.checksums:结果写入位置,首次运行需加--create-replicate-table -
--chunk-size=1000:控制每块行数,默认按 0.5 秒目标时间动态调整,但手动设更可控 -
--max-load="Threads_running=25":防止校验拖垮线上查询 -
--ignore-databases="information_schema,mysql,performance_schema":排除系统库 - 若主库 binlog 是 ROW 格式,必须加
--no-check-binlog-format,否则报错退出
看懂 DIFFS 和 this_crc != master_crc 才算真验证
执行完后查 SELECT * FROM percona.checksums WHERE this_crc != master_crc OR is_drift,重点看三列:
-
DIFFS列为1表示该块不一致;为0不代表全表一致,只是当前块没差异 -
this_crc是主库算出的块校验和,master_crc是从库(或目标库)同步后自己重算的值;两者不等才说明真实数据差异 -
is_drift为1表示该块校验被跳过(如锁等待超时、主从延迟过大),这类结果不可信,需单独重试 - 注意:如果用了
--replicate-check-only,输出只会显示不一致块,但不会写入新记录,无法追溯历史
最容易被忽略的是:校验结果反映的是“主库执行校验那一刻”的快照状态,若目标库延迟严重,master_crc 其实还没同步过来——所以执行前务必确认 Seconds_Behind_Master 接近 0。











