Navicat 无法真正校验主从数据一致性,仅做静态快照比对,忽略复制延迟、双写、时区精度等关键因素;应使用 pt-table-checksum、pg_checksums 或哈希脚本等专业方案。

Navicat 不能真正实现主从数据库之间的数据一致性校验——它没有复制位点感知、不读取 binlog/WAL、也不支持跨节点原子比对。所谓“校验”,只是对两个快照做静态比对,结果不可信,尤其在主从存在延迟或写入冲突时。
Navicat「数据对比」只比快照,不比一致性
它把源库和目标库当前时刻的数据拉到本地内存里逐行比对,完全忽略复制状态:
- 如果从库延迟 5 秒,Navicat 会把这 5 秒内主库已写、从库未同步的行标为「缺失」,误报不一致
- 若从库被业务直连写入(如跳过复制的 DML),Navicat 会把这部分数据当作「多余」,但无法判断是误操作还是合法双写
- 默认只比主键存在性,不比字段值;必须手动勾选「比较所有记录」,否则
name字段变了也显示“一致” - 时间字段(
DATETIME/TIMESTAMP)因时区或精度差异(如微秒 vs 秒)直接标红,实际逻辑可能一致
用 Data Sync 预览代替“校验”,看清真实差异
与其依赖「数据对比」的模糊提示,不如走一遍 Data Synchronization 的预览流程,它更接近真实同步行为:
- 进【Tools】→【Data Synchronization】,选主库为 Source、从库为 Target
- Step 2 中确认 Key Mapping 使用的是表的主键或唯一索引,避免按全字段比对(慢且易误判)
- 点【Compare&Preview】后,底部窗口会列出每张表的
Insert/Update/Delete行数,并高亮字段级差异 - 重点看「Update」行:如果只有
updated_at或version字段不同,大概率是业务自动更新,不是数据不一致 - 预览页不显示被跳过的冲突行,要看同步完成后的「信息日志」里有没有
Duplicate entry或Cannot add or update a child row
查 SQL 差异比 Navicat 界面更快更准
当表行数超 10 万,Navicat 界面容易卡死或 OOM;直接连数据库查,绕过客户端限制:
- 查主键存在但字段值不同的记录:
SELECT s.id, s.name, t.name FROM master_db.users s JOIN slave_db.users t ON s.id = t.id WHERE BINARY TRIM(s.name) != BINARY TRIM(t.name) OR (s.name IS NULL) != (t.name IS NULL);
- 查从库多出的主键(典型双写或过滤复制):
SELECT id FROM slave_db.users WHERE id NOT IN (SELECT id FROM master_db.users);
- 查主库有但从库缺失的主键(典型复制中断):
SELECT id FROM master_db.users WHERE id NOT IN (SELECT id FROM slave_db.users);
- 所有
NOT IN查询必须加索引,否则全表扫描;大表建议改用LEFT JOIN ... WHERE t.id IS NULL
真正可靠的校验必须绕开 Navicat
如果你需要生产级一致性保障,不要在 Navicat 里折腾:
- MySQL 主从:用
pt-table-checksum在主库运行,靠复制机制把校验块同步到从库比对,结果写入percona.checksums表可查 - PostgreSQL 流复制:用
pg_checksums验证物理块完整性,再对关键表加MD5(CONCAT_WS('|', ...))字段做逻辑层校验 - 通用轻量方案:写脚本在主从分别执行
SELECT MD5(GROUP_CONCAT(MD5(CONCAT_WS('|', id, name)) ORDER BY id)) FROM t;,比对结果哈希 - Navicat 唯一合理角色:作为 SQL 执行终端,跑上面这些命令并查看结果,而不是当校验引擎
最常被忽略的一点:校验前没确认从库是否真的追平。执行 SHOW SLAVE STATUS\G 后,别只扫一眼 Seconds_Behind_Master,要同时检查 Retrieved_Gtid_Set 和 Executed_Gtid_Set 是否相等——前者是已拉取日志,后者是已执行日志,差一个 GTID 就代表漏了一笔事务。


















