3

分散トランザクションを使用して、ローカル データベースのテーブルを、地球の反対側にあるデータベースのテーブルのデータと同期しています。ネットワークは、インターネット経由で 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 Standard Edition One を使用しているため、エンタープライズ機能は利用できません。

TIA ソーレン

4

2 に答える 2

3

まず、独自のレプリケーション ソリューションを展開する必要が本当にあるのでしょうか? オラクルは、データベース・リンクが常に利用可能であることに依存することなく、あるシステムから別のシステムにデータ変更を確実にレプリケートできるように設計された Streams などのテクノロジーを提供します。これにより、記述しなければならないコードの量と、実行しなければならないメンテナンスの量も最小限に抑えられます。

アプリケーションをこのように構成する必要があると仮定すると、Oracle は 2 フェーズ コミット プロトコルを使用して、分散トランザクションがアトミックに発生するようにする必要があります。トランザクションがインダウト状態のままになっているようです。DBA_2PC_PENDING ビューでインダウト トランザクションに関する情報を確認できるはずです。その後、そのインダウト トランザクションを手動で処理できるようになります。

于 2011-02-23T14:54:24.437 に答える
1

ループの代わりに一括処理を使用することもできます。多くの場合、一括 DML によってパフォーマンスが大幅に向上します。ネットワーク ラグが大きい場合、Oracle が一度に 1 行ずつ取得すると、その差は劇的になる可能性があります。実行時間を短縮してもエラーは修正されませんが、回避には役立つはずです。(ただし、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;
/
于 2011-02-23T15:49:16.117 に答える