将数据从Oracle同步到PostgreSQL

时间:2018-06-20 13:25:07

标签: database oracle postgresql data-synchronization

我们想将Oracle(11g)的数据(插入,更新)同步到PostgreSQL(10)。我们的方法如下:

  • Oracle中表上的触发器会在插入和更新之前使用序列中的nextval更新列。
  • PostgreSQL知道最后处理的序列号,并从Oracle> lastSequenceNumberFetched中获取行。

我们现在遇到以下问题:

  • Oracle中的会话1插入一行,写入了序列号(比方说45),但是在Oracle中未执行COMMIT。
  • Oracle的会话2插入一行,写入序列号(假设49(因为Oracle中的序列可能有间隔)),并且COMMIT在Oracle中完成。
  • PostgreSQL中的会话从SequenceNumber> 44(因为lastSequenceNumberFetched为44)从Oracle中获取行,并获得具有sequenceNumber 49的行。因此这是新的lastSequenceNumberFetched。
  • Oracle中的会话1进行提交。
  • PostgreSQL中的会话从sequenceNumber> 49的Oracle中获取行。问题是,从不获取具有sequenceNumber 45的行。

对于我们的用例,有没有更好的方法来避免数据丢失的问题?

3 个答案:

答案 0 :(得分:2)

  1. 如果您的表中没有删除操作,并且表不是很大,那么我建议在伪列{{返回的行级上使用Oracle System Change Number(SCN)。 1}}(link)。这是通过数字显示的提交时间。默认情况下,将为数据块跟踪SCN,但是您可以在行级别(关键字ORA_ROWSCN)上启用跟踪。因此,您必须使用此关键字重新创建表。在同步过程启动时,您可以通过函数调用rowdependencies获取当前的scn,然后扫描所有表dbms_flashback.get_system_change_number。缺点是此伪列未建立索引,因此您将进行全表扫描,这对于大表来说很慢。

  2. 如果使用delete语句,则必须跟踪已删除的记录。为此,您可以使用一个包含以下列的日志表:table_name,table_id_value,操作(插入/更新/删除)。该表由基本表上的触发器填充。因此,对于您的情况,当会话1提交基表中的数据时-则在日志表中有记录要处理。在会话提交之前,您不会看到它。因此,您所描述的序列号没有问题。

希望有帮助。

答案 1 :(得分:0)

这是纯粹的数据项目,还是您在这里有一些客户?如果您确实有中间层,则可以使用ORM来抽象其中的一部分,并同时写入两者。您是否在乎序列是否相同?可以执行诸如收集所有数据以进行同步的操作,因为特定的时间戳记(每个表都必须具有UTC时间戳记),然后对所有数据进行哈希处理并与Postgres中的内容进行比较。

对数据同步及其背后的原因有更多的要求可能会很有用。

在两种环境下,密钥是否必须相同?为什么? 查看数据的是同一用户,同时查看这两个数据源。 为什么您不只使用ORM来仅将一个db作为目标?为什么需要oracle和postgres?

答案 2 :(得分:0)

我看到了类似的设置。 Postgres上的一个应用程序主要用于报表和其他辅助任务,而主应用程序在Oracle上。

为方便起见,一些主应用程序表已缓存在Postgres中。但是这种设置带来了同步问题。

妥协解决方案是白天基于序列的增量同步与过夜的完整表复制的混合

关于此处提出的其他解决方案:

  • Postgres fdw处理复杂查询的速度很慢,特别是在where子句同时引用本地表和外部表时,这会给外部db带来额外的负担。
    如果将外部表缓存在postgres中,则相同的查询将运行得更快。

  • 使用序列号进行增量/差分同步-尝试过这种方法并适用于小型表,但是噩梦始于子关系,也许orm可以在这里帮助

  • 我认为理想的解决方案可能是将Oracle更改流式传输到Postgres或将更改复制到Postgres的中间过程

我不知道如何执行此操作,因为我了解它需要Oracle金门应用程序(+许可证)