pt-table-checksum迁移后必须手动确认4项状态并显式配置参数才能真实校验:binlog_format=row、复制线程正常、percona.checksums表存在且有权限、dsn表预置;仅"diffs=0"是假阳性,须查各从库checksums表crc_diff为空才确认一致。

直接跑 pt-table-checksum 不等于校验完成——它只在主库执行、依赖复制链路、结果必须查从库的 percona.checksums 表才能确认是否真一致。迁移后若跳过前提检查,90% 的“Diffs = 0”都是假阳性。
为什么迁移后不能直接执行默认命令
迁移环境往往不满足 pt-table-checksum 的底层约束:主库 binlog 可能没开、从库 SQL_THREAD 常被手动停掉、percona.checksums 表可能不存在或权限缺失。工具会静默跳过表,或卡在 Waiting for replica mysql2,但输出仍显示 “0 diffs”,让你误以为数据完好。
- 迁移后常见状态:主库 binlog_format 是 MIXED 或 STATEMENT,而
pt-table-checksum默认要求 ROW(否则校验语句无法精确重放) - 从库常被设为
read_only=ON且未授权对percona.checksums表的写权限,导致 checksum 记录根本写不进去 - 迁移脚本常忽略
report_host/report_port配置,工具无法自动发现从库,--recursion-method又没显式指定,就一直干等
必须手动确认的 4 个迁移后状态
不是“运行前检查”,而是“不满足就别跑”。缺一不可:
-
SHOW VARIABLES LIKE 'binlog_format'必须返回ROW;若为MIXED或STATEMENT,需先在主库执行SET GLOBAL binlog_format = 'ROW'(并写入配置文件持久化) -
SHOW SLAVE STATUS\G中Slave_IO_Running和Slave_SQL_Running都得是Yes,且Seconds_Behind_Master ;迁移后常因 GTID 不一致或 relay log 残留导致 SQL_THREAD 停滞 - 每个从库上都要有
percona.checksums表(用--create-replicate-table只在主库建,不会同步到从库);手动执行:CREATE DATABASE IF NOT EXISTS percona; CREATE TABLE IF NOT EXISTS percona.checksums (...) - 校验用户(如
chkuser)在每个从库上都得有:GRANT SELECT, REPLICATION CLIENT ON *.* TO 'chkuser'@'%'; GRANT INSERT, UPDATE, DELETE ON percona.checksums TO 'chkuser'@'%';
最小安全启动命令(迁移后专用)
迁移后首次校验,禁用所有自动推测逻辑,显式控制每一步:
pt-table-checksum \ --host=master_ip \ --port=3306 \ --user=chkuser \ --password=xxx \ --databases=mydb \ --replicate=percona.checksums \ --no-check-binlog-format \ --no-check-replication-filters \ --recursion-method="dsn=t=percona.DSN" \ --chunk-size=1000 \ --max-lag=1 \ --max-load="Threads_running=15"
-
--no-check-binlog-format:避免因 binlog_format 非 ROW 而退出;你已手动确认过,就别让工具再拦一次 -
--recursion-method="dsn=t=percona.DSN":迁移后SHOW PROCESSLIST常查不到从库连接,DSN 表必须提前在主库建好:CREATE TABLE percona.DSN (id INT PRIMARY KEY AUTO_INCREMENT, dsn VARCHAR(255)),再插入从库 DSN:INSERT INTO percona.DSN(dsn) VALUES ('h=slave1_ip,u=chkuser,p=xxx,P=3306') -
--chunk-size=1000:迁移后表结构可能含大字段(如 TEXT),默认 chunk 容易超时;小一点更稳 - 去掉
--create-replicate-table:迁移后你已手动建好percona.checksums,再加这个参数反而可能因权限不足报错中断
如何真正判断“全量一致”而非“跑完了”
命令行输出 “Diffs = 0” 只代表主库没写差异记录,不代表从库已完成比对。必须登录每个从库,执行:
SELECT db, tbl, this_cnt - master_cnt AS cnt_diff, this_crc != master_crc AS crc_diff FROM percona.checksums WHERE (this_cnt != master_cnt) OR (this_crc != master_crc);
- 如果返回空集,才说明该从库全量一致;只要有一行,就定位到具体
db和tbl - 注意
this_cnt是从库自己算的行数,master_cnt是主库写的值;差值非零 ≠ 数据错,可能是从库删了行但主库没同步(比如迁移后人工清理) - 真正危险的是
crc_diff = 1:同一块数据,主从 CRC32 不同,基本可断定内容不一致(NULL 处理、字符集、隐式转换已由工具规避) - 迁移后最容易被忽略的是:多个从库之间结果不一致。必须逐个查,不能只看第一个从库
迁移后的校验不是一次性动作,而是状态确认过程。最常出问题的环节不在工具本身,而在迁移脚本是否清除了旧 relay log、是否重置了 GTID_EXECUTED、是否漏授了 percona.checksums 表权限——这些细节不手工验证,pt-table-checksum 再准也白跑。











