Navicat 17 不支持真正双向实时同步,其“双向”实为两次人工控制的单向同步,依赖手动执行A→B与B→A、严格配置选项(禁用Delete、设时间戳过滤)、表结构对齐及主键避重等前提,否则易致冲突、覆盖或锁表。
navicat 17 本身不支持真正的“双向实时同步”,也没有内置触发器管理或主键分段能力——它做的是**按需、离线、批量的数据比对与搬运**。所谓“双向”,实际是两次独立单向同步,必须人工控制顺序、范围和选项,否则极易因主键冲突、时间戳错位或删除误操作引发数据混乱,甚至在目标库写入时阻塞源库事务(尤其跨实例时)。
为什么不能依赖 Navicat 做“自动双向同步”
Navicat 的 Data Synchronization 是一次性作业,没有后台监听、无变更捕获(CDC)、不维护同步位点。它不像 Debezium 或 Oracle GoldenGate 那样能持续追踪 binlog/redo log。所谓“双向”,只是你手动执行 A→B、再执行 B→A 两次操作,中间没有任何协调机制:
- 如果两次同步间隔内,A 和 B 同时修改了同一主键的记录,第二次同步会直接覆盖,且无冲突提示
- Navicat 不校验业务时间戳字段(如
updated_at),无法判断哪边更新更“新” - 跨数据库类型(如 MySQL ↔ SQL Server)时,自增主键生成逻辑不同,
INSERT可能因主键重复失败,但 Navicat 默认不会跳过或重试 - 它不干预数据库层面的锁行为:同步过程中对目标表加写锁(取决于目标库隔离级别),若同步耗时长,可能阻塞线上查询
如何用 Navicat 实现可控的类双向效果
关键不是开启什么开关,而是拆解动作、加约束、留退路。真实可行的流程如下:
-
首次对齐:用
Structure Synchronization确保两张表字段名、类型、主键定义完全一致;特别检查CHARSET和COLLATION,不一致会导致WHERE比对失效 -
A→B 同步(只合并):在 Options 中仅勾选
Insert records和Update records,绝对不勾Delete records;在 Field Mapping 中,把updated_at字段映射为“源覆盖目标”,避免旧数据回写 -
B→A 同步(带条件):同样禁用
Delete records;在 Step 2 的“Where Condition”栏手动填入类似updated_at > '2026-04-25 00:00:00'的过滤条件,只同步 B 表新增/更新的部分,规避全表扫描和锁扩大 -
主键冲突兜底:若主键非自增(如 UUID 或业务编码),Navicat 能正常比对;若是自增整型,务必确认两边初始值不重叠(例如 A 用奇数段、B 用偶数段),否则同步时必然报
Duplicate entry
触发器和主键分段?Navicat 做不了,得靠数据库自己
Navicat 不部署也不管理触发器。如果你需要在数据写入时自动打标或分流,必须提前在数据库中创建:
- MySQL 示例:在 B 表上建
BEFORE INSERT触发器,强制设置source_flag = 'B'和updated_at = NOW(),后续同步时可据此过滤 - SQL Server 示例:用序列(
SEQUENCE)替代IDENTITY,为 A 库分配1, 3, 5...,B 库分配2, 4, 6...,避免主键碰撞 - Oracle 示例:用
DBMS_SCHEDULER定期清理已同步的临时标记表,而非依赖 Navicat 的“增量同步”伪选项(它实际只是加 WHERE,不维护状态)
Navicat 的“增量同步”选项只是界面快捷方式,底层仍是静态 SQL 查询,不记录上次同步位置。真要可靠增量,必须由数据库提供可追踪的变更源(如 MySQL 的 GTID、PostgreSQL 的 logical replication slot)。
最容易被忽略的三个硬性前提
没做完这三件事,任何“双向”方案都等于裸奔:
- 目标表必须有明确的、稳定的唯一键(最好是主键)。Navicat 用它做
JOIN对比,没它就只能全表扫,性能崩、锁死、结果不可信 - 同步前必须手动备份目标表,命令级示例:
mysqldump -h prod_db -u user prod_db.table_name > table_name_$(date +%F).sql。Navicat 的“预览”不等于安全,它不校验外键约束是否允许更新 - 跨库同步时,确保网络延迟 Connection lost,不提示具体断在哪一步


















