SQL如何在迁移期间保持旧新库双向同步_DTS工具与冲突覆盖规则

1次阅读

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

SQL 如何在迁移期间保持旧新库双向同步_DTS 工具与冲突覆盖规则

MySQL DTS 同步任务里,INSERT ON DUPLICATE KEY UPDATE 为什么没生效?

因为 DTS 默认用 REPLACE INTOINSERT IGNORE,不是你写的那条语句。它只认主键 / 唯一键冲突时的“覆盖策略”,不解析你的 SQL 逻辑。

实操建议:

  • DTS 控制台建同步任务时,必须在「高级配置」里显式开启「冲突处理」并选「更新已存在记录」,否则默认丢弃冲突行或报错
  • 确认源库表有且仅有一个 PRIMARY KEYUNIQUE 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 上执行 KILLStateWaiting 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 自动猜。

text=ZqhQzanResources