我们对此类工作使用封闭流程。
从远程系统获取数据到暂存表中,导入到产品表中。
如果任何东西都可以随意插入到临时表中,并且有子表,那么您可能会在临时表中创建所有子记录之前导入到生产数据库中。
如果您可以自由地将列添加到暂存表(远程端将忽略),或者如果暂存表具有唯一/非重复的 IDENTITY 或 GUID,那么您可以创建一个并行表。
理想情况下,在暂存表中创建行的例程将使用批次编号,然后在成功时创建“批次编号完成”记录。所以你有一个信号量来阻止你导入,直到所有关联的记录都进来。
(它们可以插入到事务块中,但您必须确信插入到暂存表中的所有进程都遵守了这一点)。
给定 IDENTITY / GUID,我将创建一个 1:1 的“错误表”来存储任何描述导入失败的消息。
您可以选择将失败的行移动或复制到单独的故障暂存表中,这样主暂存表就不会被阻塞,并且更容易确保故障被整理出来(我认为是由人)。
说了这么多,这里对我们的具体流程做一个更详细的描述:
为了最小化带宽和更新(即减少阻塞和最小化不必要的事务日志条目等),我们执行以下操作:
在源机器上保存正在传输的表的副本。这有用于更新和操作的附加列(更新或删除标志 - 更新包括插入,并且插入可能在目标获得该行之前再次更新......)
插入到这个表中,新的行都可以
仅当至少一列存在差异时才会更新此表 - 因此可以(如果相当 CPU 密集型)将整个源表与暂存表进行比较以找出发生了什么变化。更新设置已更新列。(注意时钟何时返回)
如果在源表中找不到它们,我们会定期标记 stagin 表行 Action=Deleted。
数据从 Source 复制到 Destination 上的相同表,其中 Updated-on 是在最后一次传输之后。
在目标服务器上,检查数据并将其导入生产的例程仅在更新日期工作(处理自上次更新日期以来的所有内容)
所有临时表都在一个单独的数据库中,该数据库具有最少的日志记录——如果数据库恢复,数据库将自动从“上次更新日期”刷新,因此我们的目标是最小化事务日志。我们不会将临时表存储在生产数据库中(它将具有完整的事务日志记录),以避免 TLogs 膨胀
同样,如果这些过程是连续的,这样它们就不会同时发生,这将很有帮助,否则需要某种批次编号来防止传输存在父/子表的部分完成的批次。
我们以 Source 数据库的方式传输数据,只在 Destination 端进行数据操作。这样做的原因是,如果数据操作错误,并且我们修复了它,我们只需要在目标端重新运行它 - 源数据都存在于目标端的临时表中。如果我们在源端进行操作,我们也必须再次重新传输所有数据。
对于调试,在暂存表中具有更新日期是有帮助的。我们经常得到“为什么这不同”并且看到更新后告诉我们目标端的操作是否有问题(即我们有显示预期源数据的最近数据)或源端(没有找到最近的数据! )