DTS同步中INSERT ON DUPLICATE KEY UPDATE未生效,因DTS默认用REPLACE INTO或INSERT IGNORE,需在高级配置中显式开启冲突处理并选“更新已存在记录”,且源表须有唯一键、目标字段不能有NOT NULL无默认值列。

MySQL DTS 同步任务里,INSERT ON DUPLICATE KEY UPDATE 为什么没生效?
因为 DTS 默认用 REPLACE INTO 或 INSERT IGNORE,不是你写的那条语句。它只认主键/唯一键冲突时的“覆盖策略”,不解析你的 SQL 逻辑。
实操建议:
- DTS 控制台建同步任务时,必须在「高级配置」里显式开启「冲突处理」并选「更新已存在记录」,否则默认丢弃冲突行或报错
- 确认源库表有且仅有一个
PRIMARY KEY或UNIQUE KEY—— DTS 依赖这个判断“哪一行算重复”,没有就全量覆盖 - 目标库字段不能有
NOT NULL且无默认值的列,否则INSERT IGNORE会静默失败(查SHOW WARNINGS能看到1364 Field doesn't have a default value)
PostgreSQL 使用 pglogical 双向同步时,自增 ID 冲突怎么破?
双向同步下,两个库都可能生成相同 serial 值,一写就主键冲突。这不是 pglogical 的 bug,是设计使然 —— 它不自动拆分序列空间。
实操建议:
- 停写期间,手动把两个库的
sequence拆开:一个设为偶数起始(ALTER SEQUENCE xxx RESTART WITH 2 INCREMENT BY 2),另一个设为奇数起始 - 改应用层插入逻辑,避免直接用
NEXTVAL;改用gen_random_uuid()或带前缀的业务 ID(如'shard_a_' || md5(now()::text)) - 别依赖
pglogical.replicate_ddl_command()自动同步 DDL —— 它不会帮你改 sequence 属性,得手工跑一遍
阿里云 DTS 迁移中,UPDATE 同步延迟高,SHOW PROCESSLIST 看到大量 Waiting for table metadata lock
这是目标库被长事务或未提交的 DDL 卡住元数据锁,DTS 的同步线程只能干等。不是网络或 CPU 问题,是锁等待。
实操建议:
- 在目标 RDS 上执行
KILL掉State为Waiting for table metadata lock的线程(注意别杀 DTS 自己的连接,看User字段是rdsdtssync就放过) - 迁移前检查目标库是否有未关闭的事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW()) - TIME_TO_SEC(TRX_STARTED) > 60 - 避免在同步期间执行
ALTER TABLE ... ADD COLUMN—— DTS 会暂停同步等 DDL 完成,而 DDL 在大表上拿 MDL 锁时间极长
SQL Server 用 Transactional Replication 做双向同步,为什么 DELETE 会同步成 UPDATE?
因为订阅端触发器把 DELETE 转成了软删(比如设 is_deleted = 1),而发布端没配 NOT FOR REPLICATION,导致触发器又被复制链路二次执行。
实操建议:
- 所有用于软删、审计、时间戳更新的触发器,必须加上
NOT FOR REPLICATION选项 - 检查
sysarticles视图里的status字段:如果值是8(代表启用触发器复制),就得重置发布(sp_dropsubscription+sp_addsubscription)并关掉该选项 - 不要在发布库上用
INSTEAD OF DELETE—— DTS 类工具无法识别其语义,大概率跳过或报Could not find stored procedure 'sp_MSins_XXX'
双向同步真正的难点不在工具配置,而在业务层能否接受“最终一致”和“冲突后以某一方为准”。比如用户同时在新旧系统改同一张订单的状态,谁的写入算数?这个规则得提前写进应用代码,而不是指望 DTS 自动猜。










