在两个不同数据库之间同步数据的最佳方法


24

我必须在结构完全不同的两个大型数据库之间实现数据同步。基本上,我需要获取有关第一个数据库中不同表中产品的一些数据,并将它们重新排列为第二个数据库中的其他表。

第一次创建我的产品并不是很复杂。但是我正在寻找一种方法来更新有关每种产品的某些特定数据,而不是所有数据。

显然,有一些问题使这个问题变得棘手。

  • 除了选择查询,我不允许对源数据库执行任何操作。
  • 在目标数据库上,我可以执行常规查询(选择,更新,插入,创建),但不能修改现有的结构/表。
  • 目标数据库和源数据库的结构完全不同,表根本不一样,因此,实际上必须重新排列数据-比较表将无法工作。
  • 目标数据库使用MySQL服务器-源可能是DB2。
  • 任何地方都没有“更新时间”字段。

因此,整个过程需要在单个Python(理想情况下)脚本中完成。

我考虑根据要在目标数据库中更新的字段为每个产品创建一个哈希:md5(代码+描述+供应商+大约10个其他字段)。每天都会从源数据库中创建基于相同数据的新哈希。我将所有散列存储在一个表(项目代码,current_hash,old_hash)中,以提高性能。然后,如果新哈希与旧哈希不同,则比较并更新产品。

大约有50万种产品,所以我有点担心性能。

这是个好方法吗?


2
他们是否也想让您蒙住眼睛?这就是我现在的问题……
Hypertext队长,

1
@Neow,进展如何?您现在可以提供任何建议吗?
Edwin Evans

4
@EdwinEvans基本上,我坚持我的第一个想法,但特别是由于我的限制。我的脚本基于所有项目的关键数据创建md5哈希。然后,我将其与以前的哈希值进行比较。如果哈希值不同,则它将加载该项目的所有数据并更新所有内容。不知道这是否是最好的方法,但是它可以在晚上运行,而且表演还不错。
Neow

Answers:


9

这几乎是我过去几年一直在做的事情或生活,而我的直觉是,从源数据库读取500,000个项目并在目标中进行同步的时间不会像人们想象的那样花费那么多时间,读取“键”字段,计算MD5哈希值以及对表进行交叉检查以避免同步未更改的项目所花费的时间不会节省太多时间,甚至可能会运行更长的时间。我只是阅读全部并更新所有内容。如果这导致运行时太长,那么我将通过使ETL成为多线程来压缩运行时,每个线程仅在表的一部分上运行,但可以并行工作。

确保目标数据库具有主键索引或唯一索引非常重要。否则,您的每个更新/插入都可能锁定整个表。如果您采用多线程方法,这将很糟糕,但即使您保持单线程状态,也很重要,因为您的工作可能会锁定目标数据库表并干扰位于该数据库之上的应用程序。

您说源数据库“可能是DB2”。当您说“可以”时,表明数据库仍在设计/计划中?DB2 9或更高版本具有对上次更新时间的内置跟踪,并且能够查询和仅检索自某个时间点以来发生更改的项目。也许这就是为什么数据库被设计为没有一列指示最后更新时间的原因,例如:

SELECT * FROM T1 WHERE ROW CHANGE TIMESTAMP FOR TAB t1 > current timestamp - 1 hours;

以上查询的时间戳截止时间是您的同步运行的最后一个时间戳。

如果是这种情况,那应该可以解决您的问题。但是,您的解决方案最终将与DB2紧密地联系在一起,将来他们可能希望迁移到另一个数据库平台,并希望不需要重新访问您的同步作业。因此,重要的是要确保所有合适的人都知道您的产品将依赖于保留在DB2上,或者如果他们计划进行迁移,则迁移将包括重组数据库以使其具有“最后更改的时间戳”列,并进行任何更改。在应用程序级别进行必要的更改以填充该字段。


mysql也有类似的解决方案吗?
Fardin Behboudi

5

如果可以基于某种增量标识符或标志来完成数据同步,则它将更好更快。基本上,仅当目标数据库数据行与源数据库不同步时,才应更新它。

在SQL Server数据库中,您还可以借助Checksum fn来构建基于增量的标识符。

您应该开发一个基于SQL的作业,以便在白天或晚上的某个时间调用该作业,以触​​发此sql逻辑。当数据库使用率非常低时,最好将其作为每晚执行的SQL作业运行。如果源和目标数据库记录的增量不匹配,则仅提取这些记录。但是缺点是每次都要计算源数据行的校验和,然后将其与目标数据进行比较。

如果源数据库表中有一列“ LastModifiedDate”,则可以跳过校验和方法。这样,您的评估将在基于日期的列上执行,并且比校验和方法花费的时间更少。


谢谢,但是我不确定您的解决方案是否可以使用-在“问题”部分中查看我的修改。
Neow,2015年

由于源数据库中没有更新的时间字段,因此我们只能根据校验和或哈希值来提取合格的数据行。
卡兰2015年

由于您的源是db2。您打算如何从中提取数据?通过一些Web服务或API ..
卡兰

已使用odbc驱动程序设置了dsn。我可以使用pyodbc for Python连接并执行查询。
Neow,2015年

好的,这很好,因为您可以使用称为PyODBC的工具对远程数据库执行查询。您可以再做一件事。您可以直接将产品数据以与原始数据相同的格式拉入目标数据库中的新“登台表”,而无需进行任何检查或验证。这样,您将在目标表的目标数据库中一次性获得实时数据。然后,在第二步的稍后,您可以执行校验和操作并更新目标事务表数据。这将防止实时对源db数据进行哈希或校验和评估。
卡兰

1

使用哈希是一个好主意。由于在这种情况下安全性不是目标,因此请选择速度较快的哈希函数(md5很好)。

除非您计划将哈希计算拆分到多个线程/进程中,否则您实际上不需要将当前哈希值存储在数据库中。如果您的进程是单个脚本,则您将仅在内存中保留当前哈希,并在更新新数据库中的数据后将其作为旧哈希写入数据库。


-1

您应该已经创建了一个Windows服务,该服务将在任意时间运行,并且会在源数据库中找到更改并将这些更改插入目标数据库中。


-1(不是真正的降票,但是;)仅用于Windows建议。让我们在开发软件时不要依赖任何特定的体系结构,而只是意味着只有少数人可以使用您的东西。唯一不变的就是变化,因此最好不要依赖任何特定平台,以免让您自己和用户容易维护这些东西
pythonian29033

1
@manish kumar中最困难的部分是“它将在源数据库中找到更改”。
Narvalex
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.