编程数据工程师

如何在不同数据库中编程实现仅更新已更改数据的表同步?

用 Hintsage AI 助手通过面试

答案。

自从出现数据之间集成任务的时候,编程同步的问题常常出现:只需要更新真实更改的行,以节省资源并最小化锁定。过去的标准方法是完全替换或手动查找差异,这导致多余的操作并引发错误。

问题:在同步时,需要检测和更新仅已更改的数据,而不是全部更新。这对于性能、网络流量和完整性非常重要,尤其是在大规模或分布式数据库中。

解决方案:通常通过使用JOIN操作符比较源表和目标表,通过HASH或校验和计算差异,仅使用MERGE(或UPSERT)或特定触发器更新“不同”的行。

示例代码(在SQL Server中):

MERGE target_table AS t USING source_table AS s ON t.id = s.id WHEN MATCHED AND (t.name <> s.name OR t.value <> s.value) THEN UPDATE SET t.name = s.name, t.value = s.value WHEN NOT MATCHED BY TARGET THEN INSERT (id, name, value) VALUES (s.id, s.name, s.value);

关键特性:

  • 使用MERGE/UPSERT而不重新更新未更改的行
  • 不仅根据PK进行匹配,还可以根据其他唯一字段进行匹配
  • 仅检查真正改变了的列值(通过条件)

拘留性问题。

MERGE是否总是能够保证在并发更新时没有竞争条件?

不,如果没有额外的事务控制,可能会出现竞争条件(race condition)。为了最大程度的准确性,请使用适当的事务隔离级别。

可以使用UPDATE ... JOIN而不是MERGE进行复杂同步吗?

通常可以,但这种方法无法将新行添加到目标表中。只有MERGE/UPSERT可以更新和添加。

UPDATE t SET t.name = s.name, t.value = s.value FROM target_table t JOIN source_table s ON t.id = s.id WHERE t.name <> s.name OR t.value <> s.value;

如果同步的表具有不匹配的列集怎么办?

建议明确列出对应的字段,而不是尝试更新“始终所有”字段。如有需要,请使用映射表或转换。

常见错误和反模式

  • 连续更新所有行(即使未更改的)
  • 缺乏对新行的存在性检查(插入)
  • 缺乏事务控制,导致双重更新

生活中的例子

负面案例

ETL工程师通过简单的UPDATE操作一口气“冲”入所有键的记录:表中有数千万行,过程耗时数小时并锁定服务器。没有单独的插入新行,导致丢失新数据。

优点:

  • 代码简单

缺点:

  • 速度慢,无法节省资源,丢失新数据的风险

积极案例

专家在插入之前计算行的校验和,过滤已更改的记录,使用MERGE快速同步并追加新行。整个过程在几分钟内完成,没有过载。

优点:

  • 高速
  • 最小化锁定
  • 仅准确更改真正不同的数据

缺点:

  • 需要一些设计(哈希、标识符)