ヘッダーをスキップ
Oracle® Database管理者ガイド
11gリリース2 (11.2)
B56301-08
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

34 分散トランザクションの概念

この章の内容は、次のとおりです。

分散トランザクションの概要

分散トランザクションは1つ以上の文からなり、それらが個別に、またはグループとして、分散データベースの複数ノードのデータを更新します。たとえば、図34-1に示すデータベース構成を考えます。

図34-1 分散システム

図34-1の説明が続きます
「図34-1 分散システム」の説明

scottによって実行される次の分散トランザクションは、ローカルのsalesデータベース、リモートのhqデータベース、およびリモートのmaintデータベースを更新します。

UPDATE scott.dept@hq.us.example.com
  SET loc = 'REDWOOD SHORES'
  WHERE deptno = 10;
UPDATE scott.emp
  SET deptno = 11
  WHERE deptno = 10;
UPDATE scott.bldg@maint.us.example.com
  SET room = 1225
  WHERE room = 1163;
COMMIT;

注意:

トランザクションのすべての文が1つのリモート・ノードのみを参照している場合、そのトランザクションは分散トランザクションではなくリモート・トランザクションです。

分散トランザクションでは、次の2種類の操作が許可されます。

DMLおよびDDLトランザクション

分散トランザクションでサポートされているデータ操作言語(DML)およびデータ定義言語(DDL)操作は、次のとおりです。

  • CREATE TABLE AS SELECT

  • DELETE

  • INSERT(デフォルトおよびダイレクト・ロード)

  • UPDATE

  • LOCK TABLE

  • SELECT

  • SELECT FOR UPDATE

DML文およびDDL文はパラレルに実行でき、ダイレクト・ロードINSERT文はシリアルに実行できます。ただし、次の制限に注意してください。

  • リモート操作はすべてSELECT文である必要があります。

  • これらの文は、別の分散トランザクション内の句であってはいけません。

  • INSERTUPDATEまたはDELETE文のtable_expression_clauseで参照される表がリモートの場合、実行はパラレルではなくシリアルになります。

  • パラレルDML/DDLまたはダイレクト・ロードINSERTの発行後にリモート操作を実行することはできません。

  • XAまたはOCIを使用してトランザクションを開始した場合、そのトランザクションはシリアルに実行されます。

  • パラレル操作の実行元であるトランザクションで、ループバック操作を実行することはできません。たとえば、実際はローカル・オブジェクトのシノニムであるリモート・オブジェクトを参照することはできません。

  • トランザクションでSELECT以外の分散操作を実行する場合、DMLはパラレル化されません。

トランザクション制御文

サポートされているトランザクション制御文は、次のとおりです。

  • COMMIT

  • ROLLBACK

  • SAVEPOINT


    関連項目:

    これらのSQL文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

分散トランザクションのセッション・ツリー

分散トランザクションで文が発行されると、データベースはトランザクションに参加しているすべてのノードのセッション・ツリーを定義します。セッション・ツリーとは、セッション間の関係とセッションのロールを表す階層モデルです。セッション・ツリーの例を図34-2に示します。

図34-2 セッション・ツリーの例

図34-2の説明が続きます
「図34-2 セッション・ツリーの例」の説明

分散トランザクションのセッション・ツリーに参加しているすべてのノードは、次に示すロールを1つ以上持ちます。

ロール 説明
クライアント 異なるノードに属するデータベース内の情報を参照するノード。
データベース・サーバー 別のノードからの情報の要求を受け取るノード。
グローバル・コーディネータ 分散トランザクションの実行元ノード。
ローカル・コーディネータ 他のノードのデータを強制的に参照して、自身のトランザクション部分を完了するノード。
コミット・ポイント・サイト グローバル・コーディネータの指示に従ってトランザクションをコミットまたはロールバックするノード。

分散トランザクションのノードが果たすロールは、次の条件によって決まります。

  • トランザクションがローカルとリモートのどちらであるか。

  • ノードのコミット・ポイント強度(「コミット・ポイント・サイト」を参照)。

  • 要求されたすべてのデータがノードで使用可能か、またはトランザクションを完了するために他のノードを参照する必要があるか。

  • ノードが読取り専用かどうか。

クライアント

情報を別のノードのデータベースから参照するとき、ノードはクライアントとして機能します。参照先のノードはデータベース・サーバーです。図34-2のノードsalesは、warehouseデータベースおよびfinanceデータベースが稼働しているノードのクライアントです。

データベース・サーバー

データベース・サーバーは、クライアントがデータを要求する要求先データベースが稼働しているノードです。

図34-2では、salesノードのアプリケーションは、warehouseノードおよびfinanceノードのデータにアクセスする分散トランザクションを開始します。したがって、sales.example.comはクライアント・ノードのロールを持ち、warehouseおよびfinanceはどちらもデータベース・サーバーのロールを持ちます。この例では、アプリケーションでsalesデータベース内のデータも変更されているため、salesはデータベース・サーバーおよびクライアントです。

ローカル・コーディネータ

分散トランザクションにおいて自身のトランザクション部分を完了するために別のノードのデータを参照する必要があるノードは、ローカル・コーディネータと呼ばれます。図34-2で、salesは、直接参照しているノードwarehouseおよびfinanceを調整しているため、ローカル・コーディネータです。ノードsalesもトランザクションに関係しているすべてのノードを調整しているため、グローバル・コーディネータになります。

ローカル・コーディネータは、自身が直接やり取りするノードの間で次のようにトランザクションを調整する役目を果たします。

  • これらのノード間でトランザクションのステータス情報を受け渡します。

  • これらのノードに問合せを渡します。

  • これらのノードから問合せを受け取り、他のノードに渡します。

  • 問合せの結果を開始元のノードに返します。

グローバル・コーディネータ

分散トランザクションの実行元であるノードのことを、グローバル・コーディネータと呼びます。分散トランザクションを発行するデータベース・アプリケーションは、グローバル・コーディネータとして機能しているノードに直接接続します。たとえば、図34-2では、ノードsalesで発行されたトランザクションは、データベース・サーバーwarehouseおよびfinanceの情報を参照します。したがって、sales.example.comは、この分散トランザクションのグローバル・コーディネータになります。

グローバル・コーディネータは、セッション・ツリーの親またはルートになります。グローバル・コーディネータは、分散トランザクション処理中に次の操作を実行します。

  • 分散トランザクションのすべてのSQL文やリモート・プロシージャ・コールなどを参照先のノードに直接送り、それによってセッション・ツリーを構成します。

  • コミット・ポイント・サイト以外のすべての直接参照先ノードに対して、トランザクションの準備をするように指示します。

  • すべてのノードの準備が正常に完了した場合に、トランザクションのグローバル・コミットを開始するようにコミット・ポイント・サイトに対して指示します。

  • ノードから異常終了の応答があった場合に、トランザクションのグローバル・ロールバックを開始するようにすべてのノードに対して指示します。

コミット・ポイント・サイト

コミット・ポイント・サイトの役割は、グローバル・コーディネータの指示に従ってコミットまたはロールバックの操作を開始することです。システム管理者は、すべてのノードにコミット・ポイント強度を割り当てることで、セッション・ツリー内のノードの1つをコミット・ポイント・サイトとして必ず指定します。コミット・ポイント・サイトには、最も重要なデータを格納するノードを選択してください。

図34-3は、salesがコミット・ポイント・サイトとして機能している分散システムの例です。

図34-3 コミット・ポイント・サイト

図34-3の説明が続きます
「図34-3 コミット・ポイント・サイト」の説明

コミット・ポイント・サイトは、分散トランザクションに関係する他のすべてのノードと次の点で区別されます。

  • コミット・ポイント・サイトが準備完了状態に入ることはありません。そのため、コミット・ポイント・サイトに最も重要なデータが格納されている場合は、たとえ障害が起きたとしても、データがインダウトのままになることはありません。障害が発生すると、障害を起こしたノードは準備完了状態のままになり、インダウト・トランザクションが解決されるまで必要なロックが保持されます。

  • コミット・ポイント・サイトは、トランザクションに関係している他のノードよりも先にコミットします。実際は、コミット・ポイント・サイトでの分散トランザクションの結果によって、すべてのノードでのトランザクションがコミットされるかロールバックされるかが決まり、他のノードはコミット・ポイント・サイトの指示に従います。グローバル・コーディネータは、すべてのノードでコミット・ポイント・サイトと同様にトランザクションが完了することを保証します。

分散トランザクションのコミットの仕組み

分散トランザクションは、コミット・ポイント以外のすべてのサイトで準備が完了した後、コミットされたとみなされますが、実際には、トランザクションはコミット・ポイント・サイトで先にコミットされています。コミット・ポイント・サイトのREDOログは、このノードで分散トランザクションがコミットされるとただちに更新されます。

コミット・ポイント・ログにはコミットの記録があります。そのため、たとえ参加中のノードの一部がまだ準備完了状態であり、それらのノードで実際にトランザクションがコミットされていない場合であっても、トランザクションはコミットされたとみなされます。同様に、コミット・ポイント・サイトでコミットが記録されていない場合は、分散トランザクションはコミットされていないとみなされます。

コミット・ポイント強度

データベース・サーバーには、必ずコミット・ポイント強度を割り当てる必要があります。データベース・サーバーが分散トランザクション内で参照される場合、そのコミット・ポイント強度の値によって、2フェーズ・コミットにおける役割が決まります。具体的には、このコミット・ポイント強度によって、どのノードが分散トランザクションのコミット・ポイント・サイトになり、他のすべてのノードより前にコミットするかが決まります。 この値を指定するには、初期化パラメータCOMMIT_POINT_STRENGTHを使用します。ここでは、データベースがコミット・ポイント・サイトを決定する仕組みについて説明します。

準備フェーズの冒頭で決定されるコミット・ポイント・サイトは、トランザクションに参加しているノードの中からのみ選択されます。次に示す一連のイベントが発生します。

  1. データベースは、グローバル・コーディネータが直接参照しているノードの中で、最も高いコミット・ポイント強度を持つノードをコミット・ポイント・サイトとして選択します。

  2. 最初に選択されたノードは、このトランザクションの情報を取得する必要のあるノードの中で、自身よりも高いコミット・ポイント強度を持っているノードがないかを判断します。

  3. トランザクションで直接参照しているノードの中で最も高いコミット・ポイント強度を持つノードか、またはそのノードのサーバーの中でより高いコミット・ポイント強度を持つもののどちらかが、コミット・ポイント・サイトになります。

  4. 最終的なコミット・ポイント・サイトが決定した後、グローバル・コーディネータは、トランザクションに参加しているすべてのノードに準備応答を送ります。

図34-4は、各ノードのコミット・ポイント強度(カッコ内の値)を示したセッション・ツリーの例です。また、コミット・ポイント・サイトとして選択されたノードも示しています。

図34-4 コミット・ポイント強度とコミット・ポイント・サイトの決定

図34-4の説明が続きます
「図34-4 コミット・ポイント強度とコミット・ポイント・サイトの決定」の説明

コミット・ポイント・サイトを決定するときは、次の条件が適用されます。

  • 読取り専用ノードは、コミット・ポイント・サイトにはなれません。

  • グローバル・コーディネータが直接参照している複数のノードが同じコミット・ポイント強度を持っている場合、データベースはそれらのうちの1つをコミット・ポイント・サイトとして指定します。

  • 分散トランザクションがロールバックで終了する場合は、準備フェーズとコミット・フェーズは不要です。したがって、データベースはコミット・ポイント・サイトを決定しません。そのかわりに、グローバル・コーディネータはROLLBACK文をすべてのノードに送り、分散トランザクションの処理を終了します。

図34-4のように、コミット・ポイント・サイトとグローバル・コーディネータがセッション・ツリーの異なるノードになることもあります。各ノードのコミット・ポイント強度は、最初に接続が確立されたときにコーディネータに渡されます。コーディネータは、2フェーズ・コミット時のコミット・ポイント・サイトを効率的に選択するために、自身が直接やり取りしている各ノードのコミット・ポイント強度を保持しています。そのため、コミットが発生するたびにコーディネータとノード間でコミット・ポイント強度を交換する必要がありません。


関連項目:


2フェーズ・コミット・メカニズム

ローカル・データベースのトランザクションとは異なり、分散トランザクションには複数のデータベースでのデータの変更が伴います。そのため、データベースは、トランザクションの変更のコミットまたはロールバックを自己完結単位として調整する必要があり、分散トランザクションの処理はより複雑になります。言い換えれば、トランザクション全体がコミットするか、またはトランザクション全体がロールバックするかのどちらかの結果になります。

データベースは、2フェーズ・コミット・メカニズムを使用することで、分散トランザクションにおけるデータの整合性を保証します。準備フェーズでは、トランザクション内の開始ノードが他の参加ノードに対して、トランザクションをコミットまたはロールバックすることを確約するように要求します。コミット・フェーズでは、開始ノードがすべての参加ノードに対して、トランザクションをコミットするように要求します。この結果が達成できない場合、すべてのノードはロールバックするように要求されます。

分散トランザクションに参加しているすべてのノードは、必ず同じ動作を実行します。つまり、ノードすべてがトランザクションをコミットするか、またはノードすべてがトランザクションをロールバックします。データベースは、分散トランザクションのコミットまたはロールバックを自動的に制御および監視しており、2フェーズ・コミット・メカニズムを使用してグローバル・データベース(トランザクションに参加しているデータベースの集まり)の整合性を維持します。このメカニズムは完全に透過的であり、ユーザーやアプリケーション開発者の側でプログラミングを行う必要はまったくありません。

コミット・メカニズムは、次の各フェーズで構成されています。データベースは、ユーザーが分散トランザクションをコミットすると、必ずこれらのフェーズを自動的に実行します。

フェーズ 説明
準備フェーズ グローバル・コーディネータと呼ばれる開始ノードは、コミット・ポイント・サイト以外の参加ノードに対して、たとえ障害が起きた場合でもトランザクションをコミットまたはロールバックすることを確約するように要求します。準備ができないノードがある場合、トランザクションはロールバックされます。
コミット・フェーズ すべての参加ノードが準備完了の応答をコーディネータに伝えると、コーディネータは、コミット・ポイント・サイトにコミットを要求します。コミット・ポイント・サイトのコミット後、コーディネータは、トランザクションをコミットするように他のすべてのノードに要求します。
情報消去フェーズ グローバル・コーディネータは、トランザクションに関する情報を消去します。

この項の内容は次のとおりです。

準備フェーズ

準備フェーズは、分散トランザクションのコミットにおける1番目のフェーズです。このフェーズでは、データベースがトランザクションを実際にコミットまたはロールバックすることはありません。ここでは、分散トランザクションで参照されているすべてのノード(「コミット・ポイント・サイト」で説明されているコミット・ポイント・サイトを除く)がコミットを準備するように指示されます。ノードは、準備を完了するために次の処理を実行します。

  • REDOログの情報を記録し、それ以降障害が発生してもトランザクションをコミットまたはロールバックできるようにします。

  • 変更済の表に分散ロックを設定し、読取りを防ぎます。

各ノードは、コミットの準備が完了したという応答をグローバル・コーディネータに伝えることによって、その後トランザクションをコミットまたはロールバックすることを確約しますが、トランザクションをコミットまたはロールバックするという決定を各ノードが一方的に下すわけではありません。この確約の意味は、この時点でインスタンス障害が発生した場合、ノードはオンライン・ログのREDOレコードを使用してデータベースをリカバリし、準備フェーズに戻すことができるということです。


注意:

ノードの準備完了後に発行した問合せは、すべてのフェーズが完了するまで、関連するロック済データにアクセスできません。この時間は、障害が発生しないかぎり問題にはなりません(「インダウト・トランザクションの処理方法の決定」を参照)。

準備フェーズでの応答のタイプ

準備を指示されたノードは、次の方法で応答できます。

応答 意味
Prepared ノードのデータの変更が分散トランザクション内の文によって完了しており、ノードの準備が正常に完了しています。
読取り専用 ノードで変更されるデータがない(問合せのみ)か、または変更できないので、準備は不要です。
異常終了 ノードが正常に準備できません。

準備応答

ノードの準備が正常に完了すると、ノードは準備完了メッセージを発行します。このメッセージは、ノードの変更レコードがオンライン・ログに格納されており、ノードでコミットまたはロールバックのどちらかを実行できる準備が整っていることを示します。また、このメッセージによって、トランザクションに対して保持されているロックが障害発生時にも残ることが保証されます。

読取り専用応答

ノードが準備を要求されたときに、データベースにアクセスするSQL文がノードのデータを変更しない場合、ノードは読取り専用メッセージで応答します。このメッセージは、ノードがコミット・フェーズに参加しないことを示します。

分散トランザクションの全部または一部が読取り専用になるケースとして、次の3つがあります。

ケース 条件 結果
一部読取り専用 次のいずれかが発生した場合
  • 1つ以上のノードで問合せのみが発行された。

  • データが変更されない。

  • トリガーの起動または制約違反のために変更がロールバックされた。

読取り専用ノードは、準備を要求されたときに自身のステータスを認識します。読取り専用ノードは、読取り専用応答をローカル・コーディネータに伝えます。この結果、データベースは読取り専用ノードを以降の処理から除外するので、コミット・フェーズがより高速に完了します。
準備フェーズでの完全な読取り専用 次のすべてが発生した場合
  • データが変更されない。

  • トランザクションがSET TRANSACTION READ ONLY文で開始されていない

準備フェーズ時にすべてのノードが読取り専用であることを認識するので、コミット・フェーズは不要になります。グローバル・コーディネータにはすべてのノードが読取り専用かどうかわからないため、グローバル・コーディネータは引き続き準備フェーズを実行する必要があります。
2フェーズ・コミットなしの完全な読取り専用 次のすべてが発生した場合
  • データが変更されない。

  • トランザクションがSET TRANSACTION READ ONLY文で開始されている

このトランザクションでは問合せのみが許可されるため、グローバル・コーディネータは、2フェーズ・コミットを実行する必要がありません。また、システム変更番号(SCN)の調整がノード間でグローバルに行われるため、他のトランザクションによる変更によってグローバル・トランザクション・レベルの読込み一貫性が損なわれることはありません。このトランザクションでは、UNDOセグメントは使用されません。

分散トランザクションが読取り専用に設定されている場合、そのトランザクションでUNDOセグメントは使用されません。多数のユーザーがデータベースに接続していて、ユーザーのトランザクションがREAD ONLYに設定されていない場合は、それらのトランザクションが問合せを実行するのみであっても、UNDO領域が割り当てられます。

異常終了時のエラー

ノードは、正常に準備できないときに次の処理を実行します。

  1. トランザクションが現在保持しているリソースを解放し、トランザクションのローカル部分をロールバックします。

  2. 分散トランザクション内で自身を参照しているノードに対し、異常終了メッセージで応答します。

これらの処理は、分散トランザクションに関係している他のノードに伝播します。これにより、他のノードはトランザクションをロールバックできるので、グローバル・データベースのデータの整合性が保証されます。この応答によって、「トランザクションに関係しているすべてのノードが同じ物理時間でトランザクションをすべてコミットするか、またはすべてロールバックする」という分散トランザクションの基本原則が守られます。

準備フェーズの手順

準備フェーズを完了するために、コミット・ポイント・サイトを除く各ノードは次の手順を実行します。

  1. ノードは、自身の(以降参照する各ノード)に対して、コミットの準備をするように要求します。

  2. ノードは、トランザクションによって自分自身のデータまたは子のデータが変更されるかどうかをチェックします。データが変更されない場合、ノードは残りの手順を省略し、読取り専用応答を返します(「読取り専用応答」を参照)。

  3. データが変更される場合、ノードはトランザクションのコミットに必要なリソースを割り当てます。

  4. ノードは、トランザクションによる変更に対応するREDOレコードをREDOログに保存します。

  5. ノードは、トランザクションに対して保持されているロックが障害発生時にも残ることを保証します。

  6. ノードは、準備レスポンスを開始ノードに伝えます(「準備レスポンス」を参照)。あるいは、自身またはその子のいずれかが準備の試行に失敗した場合は、異常終了応答を伝えます(「異常終了時のエラー」を参照)。

これらの処理によって、ノードが後で自身のトランザクションをコミットまたはロールバックできることが保証されます。この後、準備完了ノードは、グローバル・コーディネータからCOMMITまたはROLLBACK要求を受け取るまで待機します。

各ノードの準備が完了した後、分散トランザクションはインダウトと呼ばれる状態になります(「インダウト・トランザクション」を参照)。すべての変更がコミットまたはロールバックされるまで、インダウト状態のままです。

コミット・フェーズ

コミット・フェーズは、分散トランザクションのコミットにおける2番目のフェーズです。このフェーズになる前に、分散トランザクションで参照されている、コミット・ポイント・サイト以外のすべてのノードが準備完了していること、つまり、トランザクションのコミットに必要なリソースを確保していることが保証されます。

コミット・フェーズの手順

コミット・フェーズは次の手順で構成されています。

  1. グローバル・コーディネータは、コミット・ポイント・サイトにコミットを指示します。

  2. コミット・ポイント・サイトは、コミットを実行します。

  3. コミット・ポイント・サイトは、コミットが完了したことをグローバル・コーディネータに伝えます。

  4. グローバル・コーディネータおよびローカル・コーディネータは、すべてのノードに対してトランザクションをコミットするように指示するメッセージを送ります。

  5. 各ノードで、データベースは分散トランザクションのローカル部分をコミットし、ロックを解放します。

  6. 各ノードで、データベースは、トランザクションのコミットが完了したことを示す追加のREDOエントリをローカルREDOログに記録します。

  7. 各参加ノードは、自身のコミットが完了したことをグローバル・コーディネータに伝えます。

コミット・フェーズが完了するときは、分散システムの全ノードのデータについて一貫性が保たれています。

グローバル・データベースの一貫性の保証

コミットされた各トランザクションには、そのトランザクション内部のSQL文によって行われた変更を一意に識別するためのSCNが対応付けられます。SCNは、データベースのコミット済バージョンを一意に識別する内部的なタイムスタンプの役割を持ちます。

分散システムでは、次の処理がすべて発生したときに、通信中のノードのSCNが調整されます。

  • 1つ以上のデータベース・リンクによって表されるパスを使用した接続の確立

  • 分散SQL文の実行

  • 分散トランザクションのコミット

特に、分散システムのノード間でSCNが調整されることにより、文とトランザクションの両方のレベルでグローバルな読込み一貫性が保証されるという利点があります。必要であれば、グローバルな時間ベースのリカバリを実行することもできます。

準備フェーズ時に、データベースは、トランザクションに関係しているすべてのノードで最も高いSCNを判断します。次に、コミット・ポイント・サイトにおいて最も高いSCNでトランザクションをコミットします。さらに、すべての準備完了ノードに対して、コミットの指示とともにコミットSCNを送ります。


関連項目:

読込み一貫性におけるタイム・ラグ問題の管理の詳細は、「読込み一貫性の管理」を参照してください。

情報消去フェーズ

参加ノードが自身のコミットの完了をコミット・ポイント・サイトに通知した後、コミット・ポイント・サイトは、トランザクションに関する情報を消去できます。次の手順が発生します。

  1. すべてのノードのコミットが完了したことをグローバル・コーディネータから通知された後、コミット・ポイント・サイトは、このトランザクションに関するステータス情報を消去します。

  2. コミット・ポイント・サイトは、ステータス情報を消去したことをグローバル・コーディネータに伝えます。

  3. グローバル・コーディネータは、トランザクションに関する自分自身の情報を消去します。

インダウト・トランザクション

2フェーズ・コミット・メカニズムは、すべてのノードがコミットされるかまたはロールバックを一斉に実行することを保証します。システムやネットワークのエラーのために、3つのフェーズのいずれかが失敗した場合はどうなるのでしょうか。この場合、トランザクションはインダウトになります。

分散トランザクションは、次の要因によってインダウトになる可能性があります。

  • Oracle Databaseソフトウェアを実行しているサーバー・システムがクラッシュした。

  • 分散処理に関係している複数のOracle Database間のネットワーク接続が切断された。

  • 未処理のソフトウェア・エラーが発生した。

システム、ネットワークまたはソフトウェアの問題が解決されると、RECOプロセスによってインダウト・トランザクションが自動的に解決されます。RECOがトランザクションを解決できるまで、データは読取りおよび書込みの両方についてロックされます。読取りをブロックするのは、データベースが問合せに対してどのバージョンのデータを表示すればよいかを判断できないためです。

この項の内容は次のとおりです。

インダウト・トランザクションの自動解決

データベースでは、多くの場合、インダウト・トランザクションは自動的に解決されます。たとえば、次の使用例においてlocalremoteの2つのノードがあるとします。ローカル・ノードはコミット・ポイント・サイトです。ユーザーscottは、localに接続してlocalremoteを更新する分散トランザクションを実行し、コミットします。

準備フェーズ中の障害

図34-5は、分散トランザクションの準備フェーズ中に障害が発生したときの一連のイベントを示しています。

図34-5 準備フェーズ中の障害

図34-5の説明が続きます
「図34-5 準備フェーズ中の障害」の説明

次の手順が発生します。

  1. ユーザーSCOTTLocalに接続して分散トランザクションを実行します。

  2. グローバル・コーディネータ(この例ではコミット・ポイント・サイトを兼務)は、コミット・ポイント・サイト以外のすべてのデータベースに対して、コミットまたはロールバックの指示があったときにその動作を実行することを確約するように要求します。

  3. remoteデータベースが、localに準備応答を発行する前にクラッシュします。

  4. トランザクションは、リモート・サイトのリストア時に、RECOプロセスによって各データベースで最終的にロールバックされます。

コミット・フェーズ中の障害

図34-6は、分散トランザクションのコミット・フェーズ中に障害が発生したときの一連のイベントを示しています。

図34-6 コミット・フェーズ中の障害

図34-6の説明が続きます
「図34-6 コミット・フェーズ中の障害」の説明

次の手順が発生します。

  1. ユーザーScottlocalに接続して分散トランザクションを実行します。

  2. グローバル・コーディネータ(この場合はコミット・ポイント・サイトを兼務)は、コミット・ポイント・サイト以外のすべてのデータベースに対して、コミットまたはロールバックの指示があったときにその動作を実行することを確約するように要求します。

  3. コミット・ポイント・サイトは、コミットの確約を示す準備完了メッセージをremoteから受け取ります。

  4. コミット・ポイント・サイトはトランザクションをローカルにコミットし、それからコミット・メッセージをremoteに送ってコミットを要求します。

  5. remoteデータベースはコミット・メッセージを受け取りましたが、ネットワーク障害のために応答できません。

  6. トランザクションは、ネットワークがリストアされた後、RECOプロセスによってリモート・データベースで最終的にコミットされます。


    関連項目:

    障害状況の説明と、2フェーズ・コミット中に障害が発生した場合のデータベースによる解決方法の詳細は、「インダウト・トランザクションの処理方法の決定」を参照してください。

インダウト・トランザクションの手動解決

次の場合のみ、インダウト・トランザクションを手動で解決する必要があります。

  • インダウト・トランザクションが重要なデータまたはUNDOセグメントをロックしている場合。

  • システム、ネットワークまたはソフトウェアの障害の原因をすぐに修復できない場合。

インダウト・トランザクションの解決が複雑になる場合があります。その場合は、次の手順を実行する必要があります。

  • インダウト・トランザクションのトランザクション識別番号を特定します。

  • DBA_2PC_PENDINGビューおよびDBA_2PC_NEIGHBORSビューを問い合せ、トランザクションに関係しているデータベースのコミットが完了しているかどうかを確認します。

  • 必要であれば、COMMIT FORCE文を使用してコミットを強制実行するか、またはROLLBACK FORCE文を使用してロールバックを強制実行します。


    関連項目:

    インダウト・トランザクションの解決方法の詳細は、次の項を参照してください。

インダウト・トランザクションのシステム変更番号の関連性

SCNは、コミット済バージョンのデータベースの内部的なタイムスタンプです。Oracle Databaseサーバーは、SCNクロック値を使用することでトランザクションの一貫性を保証します。たとえば、ユーザーがトランザクションをコミットするとき、データベースはそのコミットのSCNをREDOログに記録します。

データベースは、SCNを使用して、異なるデータベース間での分散トランザクションを調整します。たとえば、データベースは、次のときにSCNを使用します。

  1. アプリケーションがデータベース・リンクを使用して接続を確立するとき。

  2. 分散トランザクションが、それに関係しているすべてのデータベースの中で最も高いグローバルSCNでコミットされるとき。

  3. コミット・グローバルSCNが、トランザクションに関係しているすべてのデータベースに送られるとき。

SCNは、トランザクションが失敗した場合も含め、トランザクションの同期化されたコミット・タイムスタンプとして機能するため、分散トランザクションにとって非常に重要な存在です。トランザクションがインダウトになった場合、管理者はこのSCNを使用して、グローバル・データベースへの変更を調整できます。トランザクション・コミットのグローバルSCNは、分散リカバリの実行時など、後でトランザクションの識別に使用することもできます。

分散トランザクション処理: 事例

この使用例では、ある会社がsales.example.comおよびwarehouse.example.comという異なるOracle Databaseサーバーを持っています。ユーザーが売上レコードをsalesデータベースに挿入すると、対応付けられたレコードがwarehouseデータベースで更新されます。

この分散処理の事例では、次のことを示します。

  • セッション・ツリーの定義。

  • コミット・ポイント・サイトがどのように決定されるか。

  • 準備メッセージがいつ送られるか。

  • トランザクションがいつ実際にコミットされるか。

  • トランザクションに関するどのような情報がローカルに格納されるか。

第1段階: クライアント・アプリケーションによるDML文の発行

営業部門で、営業担当がSQL*Plusを使用して売上注文を入力し、コミットします。アプリケーションは次のようなSQL文を発行し、salesデータベースに注文を入力して、warehouseデータベースのinventory表を更新します。

CONNECT scott@sales.example.com ...;
INSERT INTO orders ...;
UPDATE inventory@warehouse.example.com ...;
INSERT INTO orders ...;
UPDATE inventory@warehouse.example.com ...;
COMMIT;

これらのSQL文は単一の分散トランザクションの一部であり、発行されるすべてのSQL文がユニットとして成功または失敗することが保証されています。文をユニットとして扱うことにより、注文が設定されていても、注文を反映するように在庫が更新されていないという事態を防ぐことができます。実際は、トランザクションによってグローバル・データベースのデータの一貫性が保証されています。

トランザクションの各SQL文が実行されると、図34-7のようにセッション・ツリーが定義されます。

図34-7 セッション・ツリーの定義

図34-7の説明が続きます
「図34-7 セッション・ツリーの定義」の説明

トランザクションの次の点に注意してください。

  • トランザクションを開始するのは、salesデータベースで実行されている注文入力アプリケーションです。したがって、分散トランザクションのグローバル・コーディネータは、sales.example.comになります。

  • 注文入力アプリケーションは、新しい売上レコードをsalesデータベースに挿入し、warehouseデータベースのinventory表を更新します。したがって、ノードsales.example.comwarehouse.example.comはどちらもデータベース・サーバーになります。

  • sales.example.comはinventory表を更新するため、warehouse.example.comのクライアントになります。

この段階では、この分散トランザクションのセッション・ツリーの定義が完了します。ツリー内の各ノードは、必要なデータ・ロックを獲得して、ローカル・データを参照するSQL文を実行します。これらのロックは、SQL文の実行が完了した後も、2フェーズ・コミットが完了するまで保持されます。

第2段階: Oracle Databaseによるコミット・ポイント・サイトの判別

データベースは、COMMIT文の直後にコミット・ポイント・サイトを判別します。図34-8のように、グローバル・コーディネータのsales.example.comがコミット・ポイント・サイトとして判別されます。


関連項目:

コミット・ポイント・サイトの判別の詳細は、「コミット・ポイント強度」を参照してください。

図34-8 コミット・ポイント・サイトの判別

図34-8の説明が続きます
「図34-8 コミット・ポイント・サイトの判別」の説明

第3段階: グローバル・コーディネータによる準備応答の送信

準備段階では、次の手順が実行されます。

  1. データベースがコミット・ポイント・サイトを判別した後、グローバル・コーディネータは、コミット・ポイント・サイトを除くセッション・ツリーの直接参照先のノードすべてに準備メッセージを送ります。この例では、準備を要求されるノードはwarehouse.example.comのみです。

  2. ノードwarehouse.example.comは準備を試みます。トランザクション内のローカルに独立した部分をコミットし、自身のローカルREDOログにコミット情報を記録できることをノードが保証できれば、そのノードは正常に準備できます。この例では、sales.example.comがコミット・ポイント・サイトなので、warehouse.example.comのみが準備メッセージを受け取ります。

  3. ノードwarehouse.example.comは、準備完了メッセージでsales.example.comに応答します。

各ノードが準備を終えると、準備を要求した側のノードに応答メッセージが送り返されます。応答に応じて、次のいずれかの動作が発生します。

  • 準備を要求されたノードのいずれかが、グローバル・コーディネータに対して異常終了メッセージで応答した場合、グローバル・コーディネータはすべてのノードに対してトランザクションのロールバックを指示し、操作が完了します。

  • 準備を要求されたすべてのノードがグローバル・コーディネータに対して準備完了メッセージまたは読取り専用メッセージで応答した場合、つまり、正常に準備できた場合は、グローバル・コーディネータがコミット・ポイント・サイトに対してトランザクションのコミットを要求します。

図34-9 準備メッセージの送信と確認

図34-9の説明が続きます
「図34-9 準備メッセージの送信と確認」の説明

第4段階: コミット・ポイント・サイトによるコミット

コミット・ポイント・サイトによるトランザクションのコミットでは、次の手順が実行されます。

  1. ノードsales.example.comは、warehouse.example.comの準備が完了しているという確認を受け取り、トランザクションをコミットするようにコミット・ポイント・サイトに指示します。

  2. この時点で、コミット・ポイント・サイトはトランザクションをローカルにコミットし、この操作を自身のローカルREDOログに記録します。

warehouse.example.comがまだコミットを完了していない場合でも、このトランザクションの結果は事前に決まっています。言い換えれば、指定したノードのコミット機能が遅延したとしても、トランザクションはすべてのノードでコミットされます

第5段階: コミット・ポイント・サイトによるグローバル・コーディネータへのコミットの通知

この段階では、次の手順が実行されます。

  1. コミット・ポイント・サイトは、トランザクションがコミットされたことをグローバル・コーディネータに伝えます。この例ではコミット・ポイント・サイトとグローバル・コーディネータが同一のノードであるため、操作は必要ありません。コミット・ポイント・サイトは、トランザクションがコミットされたことを自身のオンライン・ログに記録しているため、この事実を把握しています。

  2. グローバル・コーディネータは、分散トランザクションに関係している他のすべてのノードでトランザクションがコミットされたことを確認します。

第6段階: グローバルおよびローカル・コーディネータによる全ノードへのコミットの要求

トランザクション内のすべてのノードによるトランザクションのコミットでは、次の手順が実行されます。

  1. コミット・ポイント・サイトでのコミットがグローバル・コーディネータに通知された後、グローバル・コーディネータは、直接参照している他のすべてのノードに対してコミットを指示します。

  2. コミットの指示を受けたローカル・コーディネータは、次に自身のサーバーに対してコミットを指示し、以下同様にコミットの指示が伝播されます。

  3. グローバル・コーディネータを含む各ノードは、トランザクションをコミットし、該当するREDOログ・エントリをローカルに記録します。各ノードのコミットが完了すると、そのトランザクションのためにローカルに保持されていたリソース・ロックが解放されます。

図34-10では、コミット・ポイント・サイトとグローバル・コーディネータを兼務しているsales.example.comが、トランザクションのローカルのコミットをすでに完了しています。この時点でsaleswarehouse.example.comに対してトランザクションのコミットを指示します。

図34-10 ノードへのコミットの指示

図34-10の説明が続きます
「図34-10 ノードへのコミットの指示」の説明

第7段階: グローバル・コーディネータとコミット・ポイント・サイトによるコミットの完了

トランザクションのコミットの完了は、次の手順で実行されます。

  1. すべての参照先ノードとグローバル・コーディネータがトランザクションのコミットを完了した後、グローバル・コーディネータはこれをコミット・ポイント・サイトに通知します。

  2. このメッセージを待っていたコミット・ポイント・サイトは、この分散トランザクションに関するステータス情報を消去します。

  3. コミット・ポイント・サイトは、完了したことをグローバル・コーディネータに伝えます。つまり、コミット・ポイント・サイトは、分散トランザクションのコミットに関する情報を保持しません。2フェーズ・コミットに関係しているすべてのノードでトランザクションのコミットが正常に完了すると、それらのノードで今後ノード自身のステータスを判断する必要はないため、このような処理が許可されます。

  4. グローバル・コーディネータは、トランザクション自体に関する情報を消去することでトランザクションを完了します。

COMMITフェーズの完了後、分散トランザクションそのものが完了します。これまで説明した手順は、1秒以内に自動的に実行されます。