【问题标题】:Securing Oracle distributed transactions against network failures保护 Oracle 分布式事务免受网络故障的影响
【发布时间】:2011-07-02 17:34:39
【问题描述】:

我正在使用分布式事务将本地数据库中的表与地球另一端数据库中的表中的数据同步。 网络通过互联网上的 vpn 连接。 大多数情况下它工作正常,但是当连接在活动事务期间中断时,锁会阻止作业再次运行。 我无法终止锁定会话。尝试这样做只会返回“ORA-00031:会话标记为杀死”,并且在我循环本地数据库之前它实际上并没有被杀死。

同步作业基本上是

CURSOR TRANS_CURSOR IS    
SELECT COL_A, COL_B, COL_C    
 FROM REMOTE_MASTERTABLE@MY_LINK    
 WHERE UPDATED IS NULL;    

BEGIN    
  FOR TRANS IN TRANS_CURSOR LOOP    

    INSERT INTO LOCAL_MASTERTABLE    
      (COL_A, COL_B, COL_C)    
    VALUES    
      (TRANS.COL_A, TRANS.COL_B, TRANS.COL_C);    

    INSERT INTO LOCAL_DETAILSTABLE (COL_A, COL_D, COL_E)
      SELECT COL_A, COL_D, COL_E
      FROM REMOTE_DETAILSTABLE@MY_LINK
      WHERE COL_A = TRANS.COL_A;

    UPDATE REMOTE_MASTERTABLE@MY_LINK SET UPDATED = 1 WHERE COL_A = TRANS.COL_A;    
  END LOOP;    
END;

任何使此同步操作更能容忍网络丢失的想法将不胜感激。 我使用的是 Oracle 标准版一,因此没有可用的企业功能。

TIA 索伦

【问题讨论】:

    标签: oracle transactions locking distributed dblink


    【解决方案1】:

    首先,您真的需要推出自己的复制解决方案吗? Oracle 提供了诸如 Streams 之类的技术,这些技术旨在允许您将数据更改从一个系统可靠地复制到另一个系统,而无需依赖始终可用的数据库链接。这也最大限度地减少了您必须编写的代码量和您必须执行的维护量。

    假设您的应用程序确实需要以这种方式进行配置,Oracle 将不得不使用两阶段提交协议来确保分布式事务以原子方式发生。听起来交易处于不确定状态。您应该能够在 DBA_2PC_PENDING 视图中看到information about in-doubt transactions。然后您应该能够manually handle that in-doubt transaction

    【讨论】:

    • 感谢您将我指向 DBA_2PC_PENDING 视图,我将在下一次锁定时进行调查。 Oracle Streams 不适合我,我正在运行标准版(一)。顺便说一句,Streams 不是被 GoldenGate 技术取代了吗?
    • @TheRoadrunner - 即使在 Standard Edition One 中,11g 也支持 Streams(有一些限制)和物化视图复制(尽管不支持多主物化视图复制)。
    • 那么我将不得不再次考虑流。与此同时,线路又断了,我处于锁定状态 - 但 DBA_2PC_PENDING 中什么都没有?
    【解决方案2】:

    您可能希望使用批量处理而不是循环。 Bulk DML 通常可以带来巨大的性能提升,如果存在大量网络延迟,那么如果 Oracle 一次检索一行,则差异可能会很大。减少运行时间不会修复错误,但它应该有助于避免它。 (尽管 Oracle 可能已经在幕后进行了这种优化。)

    编辑

    批量处理可能会有所帮助,但最好的解决方案可能是仅使用 SQL 语句。我做了一些测试,下面的版本比原来的运行速度快了大约 20 倍。 (尽管很难知道我的示例数据和自引用数据库链接对您的真实数据建模的程度。)

    BEGIN
        INSERT INTO LOCAL_MASTERTABLE    
          (COL_A, COL_B, COL_C)    
        SELECT COL_A, COL_B, COL_C    
         FROM REMOTE_MASTERTABLE@MY_LINK
         WHERE UPDATED IS NULL;    
    
        INSERT INTO LOCAL_DETAILSTABLE (COL_A, COL_D, COL_E)
          SELECT REMOTE_DETAILSTABLE.COL_A, REMOTE_DETAILSTABLE.COL_D, REMOTE_DETAILSTABLE.COL_E
          FROM REMOTE_DETAILSTABLE@MY_LINK
            INNER JOIN (SELECT COL_A FROM REMOTE_MASTERTABLE@MY_LINK WHERE UPDATED IS NULL) TRANS
            ON REMOTE_DETAILSTABLE.COL_A = TRANS.COL_A;
    
        UPDATE REMOTE_MASTERTABLE@MY_LINK SET UPDATED = 1 WHERE UPDATED IS NULL;
    END;
    /
    

    【讨论】:

    • 感谢您的建议。我正在使用批量插入。这只是一个过于简单的示例。我一次只对主表使用一行,批量插入七个左右的详细信息表,导致每条主记录有数百条记录。
    • @TheRoadRunner 我错过了什么吗?您的示例仍然显示 loop..insert。
    • @Sathya:正如我所写,仍在主表上循环,但在明细表上进行批量插入。
    猜你喜欢
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 2012-04-05
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多