【问题标题】:Insert delayed when network error and insert trigger inserting on dblink-table网络错误时插入延迟并在 dblink-table 上插入触发器插入
【发布时间】:2011-11-30 21:27:45
【问题描述】:

也许是一个奇怪的标题,我会试着解释一下。 我有两台 Oracle 服务器 serverA 和 serverB。

  • 在 serverA 上,我有一个表 tabA,其中每分钟有一行 插入。
  • 在 serverB 上,我创建了一个表 tabB,它具有相同的 结构为tabA。
  • 在服务器 A 上,我创建了一个到服务器 B 的 dblink。在 serverA 我创建了一个插入触发器,例如

在 A

create trigger tabA_trig
after insert on tabA
begin
insert into tabB@serverB(...) values(:new....,:new... etc);

exception
 when others then null;
end tabA_trig;

在创建此触发器后,每次将新行插入 tabA 时,都会向 tabB 插入新行,正如预期的那样。

但是:当 serverA 和 serverB 之间的通信中断时,我没有收到任何错误(上面的异常会解决这个问题),但是也没有数据插入到 tabA 中!很奇怪,更奇怪的是,大约 15 分钟后,新数据又被插入到 tabA 中。过了一会儿,缺失的数据开始填补这个洞,过了一会儿,没有数据丢失,插入功能正常。

示例(tabA 和 tabB,第一列时间分钟和小时,第二列值):

Network OK:
tabA 1000 22;1001 22;1002 22
tabB 1000 22;1001 22;1002 22    

Network ERROR:
About 15 minutes of no new data.

After 15 minutes:
tabA 1000 22;1001 22;1002 22;1017 22;1018 22;....
tabB 1000 22;1001 22;1002 22


After 30 minutes:
tabA 1000 22;1001 22;1002 22;1003 22;1004 22;1005 22;1006 22;1017 22;1018 22;....
tabB 1000 22;1001 22;1002 22

After 1 hour:
tabA 1000 22;1001 22;1002 22;1003 22;1004 22;1005 22;1006 22;1006 22;...;1017 22;1018 22;....
tabB 1000 22;1001 22;1002 22

如果我禁用触发器,tabA 上的插入会立即生效。

我使用触发器而不是物化视图的原因是,即使从 tabA 中删除数据,我也希望保留已复制到 tabB 的所有数据。

有人知道该怎么办吗?

【问题讨论】:

    标签: oracle


    【解决方案1】:

    首先,使用自定义触发器将数据从一个数据库复制到另一个数据库几乎肯定是个坏主意。 Oracle 提供了多种技术来帮助您实现复制。尽管您也可以查看 Streams 或 Golden Gate 甚至像 Change Data Capture (CDC) 之类的东西,但物化视图可能是您在这里想要的最简单且最有可能的内容。自定义触发器对触发插入的性能有重大影响,它们会引入各种故障场景,例如难以调试。

    由于在网络关闭时没有数据被插入tabA,但这些插入稍后出现,我倾向于怀疑正在引发某种异常,导致插入应用程序将插入排队等待稍后或者应用程序正在创建一个涉及数据库 B 或其他一些资源的分布式事务,这些资源也受到网络错误的影响,直到稍后的某个时间点才能成功提交。由于我们对您的应用程序的架构一无所知,因此很难推测得太深。您可以检查DBA_2PC_PENDING 表以查看 Oracle 是否充当任何分布式事务的分布式事务协调器,但还有许多其他软件组件可能充当事务协调器。

    【讨论】:

      【解决方案2】:

      如果两个数据库的版本相似,则为 Oracle 高级队列。设置起来有点棘手,但异步消息传递模型将处理一个或另一个数据库关闭的实例。

      至于解决方案是否过于复杂,我发现我简化了我在这里提出的问题。整个问题只有 OP 可以告诉。这个问题看起来更像是消息传递问题还是合并数据?这两种解决方案都比触发器工作得更好。

      【讨论】:

      • AQ 太过分了。为他的需要制作了一个 Fast Refresh MV。
      【解决方案3】:
      1. 您需要使用激活死连接检测 SQLNET.EXPIRETIME
      2. 我不建议您按照您的方式进行复制。您可以使用“ON COMMIT REFRESH”物化视图来实现这种复制。

      【讨论】:

      • SQLNET.EXPIRETIME 仅适用于服务器端。我不确定我是否可以在我的解决方案中使用物化视图(只有插入应该传播到 tabB)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-19
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      相关资源
      最近更新 更多