Navicat同步不保证数据一致性,因默认无一致性读,依赖初始快照执行,写入中无法感知变更;需手动校验COUNT(*)、控制写入窗口或加WHERE条件断点续跑。
同步时源表被写入,Navicat 读不到最新数据
navicat 数据同步默认不开启一致性读,它在开始时查一次 count(*) 或读 information_schema.tables.table_rows(innodb 下纯估算),之后就按这个快照执行。如果源表在同步过程中持续有 insert/update/delete,navicat 不会感知,也不会重查——结果就是目标端数据“少了几百行”或“多删了几条”,但日志里不报错。
这不是 Navicat 的 bug,而是它设计上没做事务隔离保障。你看到的“同步完成”只是任务流程走完了,不代表数据状态一致。
- 查当前是否有长事务干扰:连源库执行
SELECT * FROM information_schema.INNODB_TRX;,返回非空就说明有未提交事务,极可能造成可见性偏差 - 避免依赖界面右下角显示的“行数”,那个值来自
TABLE_ROWS,InnoDB 下误差 40%~50% 都算正常 - 真正可信的起点和终点校验,只能是手动执行两次
SELECT COUNT(*) FROM your_table;,且确保两次之间无任何写入
想锁住源表等同步完成,但又怕业务中断
Navicat 本身不提供 START TRANSACTION WITH CONSISTENT SNAPSHOT 或全局读锁选项,所以得靠外部配合。最直接的是 FLUSH TABLES WITH READ LOCK;,但它会阻塞所有写入,对线上业务影响大。
更可行的折中方案是控制窗口+人工协调:
- 选业务低峰期操作(比如凌晨 2–4 点),提前通知上下游暂停对该表的写入
- 若必须白天操作,可先在应用层临时关闭写入口(如切掉某个微服务的写流量),而非直接锁库
- 用
SHOW PROCESSLIST;快速确认当前没有慢查询或长事务正在改这张表
同步中途失败后重跑,怎么防止重复插入或主键冲突
Navicat 不支持断点续传,重跑默认从头开始。如果上次已成功写入部分数据,再次全量同步就会触发 Duplicate entry 错误。
解决办法不是换工具,而是加条件过滤掉已同步的部分:
- 确认源表有单调递增、带索引的字段(如自增
id或create_time) - 在同步向导「高级」页勾选「使用 SQL WHERE 条件」,填入类似
id > 123456或create_time > '2026-06-02 18:30:00' - 注意:该字段必须在目标表也存在、类型一致,且目标端已有对应数据(否则条件过滤会导致漏同步)
- 同步前手动验证条件是否准确:在源库执行
SELECT MAX(id) FROM your_table;,再查目标库是否已包含该值及之前所有记录
为什么用了 --single-transaction 的 mysqldump 就没事,Navicat 就不行
因为 mysqldump --single-transaction 底层会发起一个 START TRANSACTION WITH CONSISTENT SNAPSHOT,整个 dump 过程都在同一个 MVCC 快照里,哪怕源表持续写入,dump 出来的数据也是逻辑一致的。而 Navicat 同步是边查边写,查一行、发一条 INSERT,中间没有任何快照锚点。
所以大表、高并发写场景下,别硬扛:
- 小表(
- 大表或不能停写:直接换
mysqldump --single-transaction导出 +mysql导入,或用mydumper/myloader - 需要实时同步:考虑 MySQL 原生复制、Canal 或 Debezium,Navicat 不是为这类场景设计的
复杂点在于:你无法只靠 Navicat 设置来规避写入干扰,必须把数据库行为、业务节奏、人工协作串起来看。最容易被忽略的是——同步前后那两次 SELECT COUNT(*),很多人跳过这步,直接信界面数字,结果问题复现了还找不到根因。


















