navicat实现增量同步需关闭“删除目标中不存在的记录”,选择“插入和更新”类型,通过“设置同步条件”添加where子句(如updated_at > '2024-06-10 00:00:00'),并配置冲突处理为“更新现有记录”,同时确保主键/唯一键一致、时区与字符集统一。
navicat 同步只跑新增和更新,不删老数据
navicat 本身没有“仅同步增量”的开关,所谓“增量同步”得靠人工构造条件来实现——核心是让同步任务跳过已存在的记录,只处理 insert 和部分 update,彻底绕开 delete 和全量覆盖逻辑。
常见错误现象:同步后目标表少了几百条记录 或 历史数据被清空重写,基本都是误选了「删除目标中不存在的记录」或「清空目标表再插入」这类危险选项。
- 必须关闭「删除目标中不存在的记录」——这个勾一打,源里没出现的行,目标里直接
DELETE - 同步类型选「插入和更新」,别选「插入、更新和删除」或「仅插入」(后者会忽略所有主键/唯一键冲突的更新)
- 确保源表有可靠的时间戳字段(如
created_at或updated_at),后续要用它圈定增量范围
用 WHERE 条件框限定「上次同步之后的新数据」
Navicat 的「高级选项」里有个「设置同步条件」入口,本质就是给同步 SQL 加 WHERE 子句。这是控制增量范围最直接、最可控的方式,比依赖日志或触发器更轻量。
使用场景:每天凌晨跑一次同步,只想拉过去 24 小时内新增或修改过的记录。
- 在「高级选项 → 设置同步条件」中填:
updated_at > '2024-06-10 00:00:00'(注意单引号不能少) - 如果只有
created_at,且业务上不允许更新,可用:created_at > '2024-06-10 00:00:00' - 时间值建议用变量替代硬编码,比如 Navicat 支持
DATE_SUB(NOW(), INTERVAL 1 DAY),但要注意目标数据库是否支持该函数(MySQL 可以,PostgreSQL 得写NOW() - INTERVAL '1 day') - 别用
BETWEEN,容易漏掉边界秒级数据;用>+ 上次同步时间点更稳妥
主键/唯一键冲突时,强制走 UPDATE 而不是报错
增量同步过程中,如果某条记录在目标库已存在(比如上次同步延迟了一分钟,这次又来了),Navicat 默认行为取决于「冲突处理」设置——不调好就会卡住或跳过。
错误现象:duplicate entry for key 'PRIMARY' 报错中断,或者明明该更新的行却没变
- 进「高级选项 → 冲突处理」,选「更新现有记录」,别选「跳过」或「停止」
- 确认源和目标表的主键或唯一索引定义完全一致,否则 Navicat 找不到匹配依据,UPDATE 会失效
- 如果目标表有自增主键,但源表用 UUID,Navicat 可能无法识别为同一行——此时得手动指定「匹配字段」,比如勾选
order_id作为业务主键 - 注意:Navicat 的「更新」默认是全字段覆盖,不会做字段级 diff,所以只要匹配上,整行都会刷一遍
避免踩坑:时间字段时区、NULL 值、字符集不一致
增量逻辑看似简单,实际最容易崩在细节。尤其当源库和目标库不在同一时区,或字段允许 NULL,同步条件就可能漏判。
-
updated_at是NULL?那WHERE updated_at > 'xxx'会直接过滤掉它——要么补默认值,要么加OR updated_at IS NULL(但要小心语义) - 源库用 UTC 时间,目标库设的是东八区?
NOW()在两边含义不同,建议统一用 UTC 时间戳做条件,或显式转换:CONVERT_TZ(updated_at, '+00:00', '+08:00') > '...' - 字符集不一致(比如源是
utf8mb4,目标是utf8),可能导致中文字段同步失败,报Incorrect string value——提前检查并统一 - Navicat 同步任务不记录「最后成功同步时间」,你得自己记。建议把每次执行的时间点写进一个配置表,下次自动读取,别靠人肉改 SQL
真正难的不是配哪几个勾,而是怎么让时间条件稳、匹配逻辑准、NULL 和时区不捣乱——这些地方一松动,增量就变成「看起来像增量」的假同步。










