プライマリ・コンテンツに移動
Oracle® Database管理者ガイド
12cリリース1 (12.1)
B71301-11
目次へ移動
目次
索引へ移動
索引

前
次

35 分散トランザクションの管理

分散トランザクションの管理には、ノードのコミット・ポイント強度の指定、トランザクションの命名、およびインダウト・トランザクションの管理などのタスクが含まれます。

35.1 ノードのコミット・ポイント強度の指定

分散トランザクションでどのノードが最初にコミットされるかは、最も高いコミット・ポイント強度を持つデータベースによって決まります。

各ノードのコミット・ポイント強度を指定するときは、準備フェーズまたはコミット・フェーズ中に障害が発生した場合に最も重要なサーバーがブロックされないようにしてください。ノードのコミット・ポイント強度は、COMMIT_POINT_STRENGTH初期化パラメータによって指定します。

デフォルト値は、オペレーティング・システムによって異なります。値の範囲は、0(ゼロ)から255までの任意の整数です。たとえば、データベースのコミット・ポイント強度を200に設定するには、そのデータベースの初期化パラメータ・ファイルに次の行を追加します。

COMMIT_POINT_STRENGTH = 200

コミット・ポイント強度は、分散トランザクションでコミット・ポイント・サイトを決定する際にのみ使用されます。

データベースのコミット・ポイント強度を設定するときは、次の点を考慮してください。

  • コミット・ポイント・サイトにはトランザクションのステータスに関する情報が格納されます。他のノードがトランザクションのステータスに関する情報を必要とする場合に備えて、コミット・ポイント・サイトには、信頼性が低下したり、使用できなくなったりする頻度の高いノードを使用しないでください。

  • データベースのコミット・ポイント強度は、データベース内の重要な共有データの量に比例するように設定してください。たとえば、メインフレーム・コンピュータのデータベースは、一般にPCのデータベースよりも多くのデータをユーザー間で共有しています。したがって、メインフレームのコミット・ポイント強度は、PCのコミット・ポイント強度よりも高い値に設定します。

    関連項目:

    コミット・ポイントの概要については、「コミット・ポイント・サイト」

35.2 トランザクションの命名

トランザクションの命名が可能です。この機能は、特定の分散トランザクションを識別する際に便利であり、同じ目的のCOMMIT COMMENT文にかわるものです。

トランザクションに命名するにはSET TRANSACTION...NAME文を使用します。次に例を示します。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
     NAME 'update inventory checkpoint 0';

この例は、SERIALIZABLEに等しい分離レベルを持つ新しいトランザクションをユーザーが開始し、それに'update inventory checkpoint 0'という名前を付けたことを示しています。

分散トランザクションでは、トランザクションがコミットされるときに、名前が参加サイトに送られます。トランザクション名が存在する場合は、COMMIT COMMENTがあっても無視されます。

トランザクション名は、V$TRANSACTIONビューのNAME列に表示され、トランザクションがコミットされると、DBA_2PC_PENDINGビューのTRAN_COMMENTフィールドに表示されます。

35.3 分散トランザクション情報の表示

各データベースのデータ・ディクショナリには、オープンしているすべての分散トランザクションに関する情報が格納されています。データ・ディクショナリの表とビューを使用すると、トランザクションに関する情報を取得できます。

35.3.1 準備完了トランザクションのID番号と状態の判断

特定のトランザクションIDのグローバル・コミット番号を確認するには、DBA_2PC_PENDINGビューを使用します。このグローバル・コミット番号は、インダウト・トランザクションを手動で解決するときに使用できます。

次のビューには、ローカル・データベースで定義され、データ・ディクショナリに格納されているデータベース・リンクが表示されます。

ビュー 目的

DBA_2PC_PENDING

インダウト分散トランザクションがすべてリストされます。このビューには、インダウト・トランザクションが移入されるまで何もデータが入っていません。トランザクションが解決された後、ビューはパージされます。

関連性の最も高い列を次の表に示します(ビューのすべての列の詳細は、『Oracle Databaseリファレンス』を参照してください)。

表35-1 DBA_2PC_PENDING

説明

LOCAL_TRAN_ID

integer.integer.integer」という書式のローカル・トランザクション識別子。

注意: 接続のLOCAL_TRAN_IDGLOBAL_TRAN_IDが同じである場合、そのノードはトランザクションのグローバル・コーディネータです。

GLOBAL_TRAN_ID

global_db_name.db_hex_id.local_tran_idという書式のグローバル・データベース識別子で、db_hex_idはデータベースを一意に識別するために使用する8文字の16進数値です。この共通のトランザクションIDは、分散トランザクションのすべてのノードで同一です。

注意: 接続のLOCAL_TRAN_IDGLOBAL_TRAN_IDが同じである場合、そのノードはトランザクションのグローバル・コーディネータです。

STATE

STATEに可能な値は、次のとおりです。

  • Collecting

    通常、このカテゴリは、グローバル・コーディネータまたはローカル・コーディネータにのみ適用されます。ノードは現在他のデータベース・サーバーから情報を収集中であり、その後ノード自身が準備できるかどうかが判断されます。

  • Prepared

    ノードは準備を完了していますが、そのことをローカル・コーディネータに準備完了メッセージで通知しているかどうかは不明です。しかし、コミット要求はまだ受け取っていません。ノードは準備完了状態にあり、トランザクションのコミットに必要なローカル・リソースのロックをすべて保持しています。

  • Committed

    ノード(任意のタイプ)はトランザクションのコミットを完了していますが、トランザクションに関係している他のノードが同じように完了していない可能性があります。つまり、トランザクションは1つ以上のノードでまだ保留しています。

  • Forced Commit

    ペンディング・トランザクションは、データベース管理者の判断で強制的にコミットできます。このエントリは、ローカル・ノードでトランザクションが手動でコミットされた場合に表示されます。

  • Forced termination (rollback)

    ペンディング・トランザクションは、データベース管理者の判断で強制的にロールバックできます。このエントリは、ローカル・ノードでこのトランザクションが手動でロールバックされた場合に表示されます。

MIXED

YESは、トランザクションの一部があるノードではコミットされ、別のノードではロールバックされたことを示します。

TRAN_COMMENT

トランザクションがコミットされると、トランザクション・コメントまたはトランザクション名(トランザクションに命名している場合)がこの列に設定されます。

HOST

ホスト・システムの名前。

COMMIT#

コミットされたトランザクションのグローバル・コミット番号。

DBA_2PC_PENDINGの関連情報を問い合せるには、次のスクリプトpending_txn_scriptを実行します(出力例も含まれています)。

COL LOCAL_TRAN_ID FORMAT A13
COL GLOBAL_TRAN_ID FORMAT A30
COL STATE FORMAT A8
COL MIXED FORMAT A3
COL HOST FORMAT A10
COL COMMIT# FORMAT A10

SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID, STATE, MIXED, HOST, COMMIT#
   FROM DBA_2PC_PENDING
/

SQL> @pending_txn_script

LOCAL_TRAN_ID GLOBAL_TRAN_ID                 STATE    MIX HOST       COMMIT#
------------- ------------------------------ -------- --- ---------- ----------
1.15.870      HQ.EXAMPLE.COM.ef192da4.1.15.870  commit   no  dlsun183   115499

この出力は、ローカル・トランザクション1.15.870がこのノードではコミットを完了しているものの、他の1つ以上のノードで保留している可能性があることを示しています。LOCAL_TRAN_IDGLOBAL_TRAN_IDのローカル部分が同じなので、このノードはトランザクションのグローバル・コーディネータです。

35.3.2 インダウト・トランザクションのセッション・ツリーのトレース

DBA_2PC_NEIGHBORSビューには、リモート・クライアントからの受信インダウト・トランザクションと、リモート・サーバーへの送信インダウト・トランザクションが表示されます。

ビュー 目的

DBA_2PC_NEIGHBORS

(リモート・クライアントからの)受信および(リモート・サーバーへの)送信インダウト分散トランザクションすべてがリストされます。また、ローカル・ノードがトランザクション内のコミット・ポイント・サイトであるかどうかも示します。

このビューには、インダウト・トランザクションが移入されるまで何もデータが入っていません。トランザクションが解決された後、ビューはパージされます。

トランザクションがインダウトのときは、セッション・ツリー内のどのノードがどのロールを実行しているのかを判断することが必要な場合があります。このビューを使用すると、次のことが判断できます。

  • 特定のトランザクションのすべての受信接続と送信接続。

  • ノードが特定のトランザクションのコミット・ポイント・サイトかどうか。

  • ノードが特定のトランザクションのグローバル・コーディネータかどうか(ノードのローカル・トランザクションIDとグローバル・トランザクションIDが同じかどうかで判断する)。

関連性の最も高い列を次の表に示します(ビューのすべての列の詳細は、『Oracle Databaseリファレンス』を参照してください)。

表35-2 DBA_2PC_NEIGHBORS

説明

LOCAL_TRAN_ID

integer.integer.integer」という書式のローカル・トランザクション識別子。

注意: 接続のLOCAL_TRAN_IDGLOBAL_TRAN_ID.DBA_2PC_PENDINGが同じである場合、そのノードはトランザクションのグローバル・コーディネータです。

IN_OUT

受信トランザクションの場合はIN、送信トランザクションの場合はOUTです。

DATABASE

受信トランザクションの場合は、このローカル・ノードから情報を要求したクライアント・データベースの名前です。送信トランザクションの場合は、リモート・サーバーの情報へのアクセスに使用されたデータベース・リンクの名前です。

DBUSER_OWNER

受信トランザクションの場合は、リモート・データベース・リンクによる接続で使用されるローカル・アカウントです。送信トランザクションの場合は、データベース・リンクの所有者です。

INTERFACE

Cはコミット・メッセージ、Nは準備完了状態を示すメッセージまたは読取り専用コミットの要求のどちらかです。

IN_OUTOUTの場合、Cは、接続のリモート側の子がコミット・ポイント・サイトであり、コミットと終了のどちらを実行するかを知っていることを意味します。Nは、ローカル・ノードの準備が完了したことをリモート・ノードに通知中であることを意味します。

IN_OUTINの場合、Cは、送信接続のリモート側のローカル・ノードまたはデータベースがコミット・ポイント・サイトであることを表します。Nは、リモート・ノードの準備が完了したことをローカル・ノードに通知中であることを意味します。

DBA_2PC_PENDINGの関連情報を問い合せるには、次のスクリプトneighbors_scriptを実行します(出力例も含まれています)。

COL LOCAL_TRAN_ID FORMAT A13
COL IN_OUT FORMAT A6
COL DATABASE FORMAT A25
COL DBUSER_OWNER FORMAT A15
COL INTERFACE FORMAT A3
SELECT LOCAL_TRAN_ID, IN_OUT, DATABASE, DBUSER_OWNER, INTERFACE 
   FROM DBA_2PC_NEIGHBORS
/

SQL> CONNECT SYS@hq.example.com AS SYSDBA
SQL> @neighbors_script

LOCAL_TRAN_ID IN_OUT DATABASE                  DBUSER_OWNER    INT
------------- ------ ------------------------- --------------- ---
1.15.870      out    SALES.EXAMPLE.COM            SYS             C

この出力は、ローカル・ノードからリモート・サーバーsalesに、トランザクション1.15.870をコミットするように送信リクエストが送られたことを示しています。salesがトランザクションをコミットし、他にコミットしたノードがない場合は、常に最初にコミットするのがコミット・ポイント・サイトであるため、salesがコミット・ポイント・サイトになります。

35.4 インダウト・トランザクションの処理方法の決定

2フェーズ・コミットの間に障害が発生すると、トランザクションはインダウトになります。Oracle Databaseソフトウェアを実行しているサーバー・システムのクラッシュ、分散処理に含まれる2つ以上のOracle Database間のネットワーク接続の切断、または未処理のソフトウェア・エラーの発生により、分散トランザクションはインダウトになります。

ローカルのインダウト分散トランザクションは、手動で強制的にコミットまたはロールバックできます。この操作では一貫性の問題が生じる可能性があるため、特定の条件が成り立つとき以外は実行しないでください。

35.4.1 2フェーズ・コミットに関する問題の検出

分散トランザクションで問題が発生した場合は、エラー・メッセージによってアプリケーションに通知されます。

分散トランザクションをコミットするユーザー・アプリケーションには、次のいずれかのエラー・メッセージによって問題が通知されます。

ORA-02050: transaction ID rolled back,
           some remote dbs may be in-doubt
ORA-02053: transaction ID committed,
           some remote dbs may be in-doubt
ORA-02054: transaction ID in-doubt

アプリケーションでこれらのエラーを受け取った場合は、トランザクションに関する情報を保存するようにしてください。この情報は、後で分散トランザクションの手動リカバリが必要になった場合に使用できます。

ネットワークまたはシステムの障害のために、任意のノードでインダウト分散トランザクションが1つ以上発生した場合でも、そのノードの管理者がなんらかの処理を実行する必要はありません。ネットワークやシステムの障害が解決した後、データベースの自動リカバリ機能によって、セッション・ツリーのすべてのノードが同じ結果になるように(つまり、すべてコミットされるかすべてロールバックされる)、すべてのインダウト・トランザクションの処理が透過的に完了します。

ただし、障害が長期にわたる場合には、トランザクションを強制的にコミットまたはロールバックすることで、ロックされたデータをすべて解放できます。アプリケーションは、この操作を想定しておく必要があります。

35.4.2 手動上書きを実行するかどうかの判断

インダウト・トランザクションのオーバーライドは、特定の条件下でのみ実行する必要があります。

特定のインダウト・トランザクションを手動でオーバーライドするのは、次のいずれかの条件が存在する場合のみです。

  • インダウト・トランザクションが他のトランザクションに必要なデータをロックしている場合。この状況は、ORA-01591エラー・メッセージによってユーザーのトランザクションが妨げられたときに起こります。

  • インダウト・トランザクションは、UNDOセグメントのエクステントが他のトランザクションによって使用されることを防ぎます。インダウト分散トランザクションのローカル・トランザクションIDの最初の部分は、データ・ディクショナリ・ビューDBA_2PC_PENDINGでリストされるUNDOセグメントのIDに対応します。

  • 2フェーズ・コミットの各フェーズの完了を妨げている障害を許容される時間範囲内で訂正できない場合。このような例としては、通信ネットワークやデータベースの損傷など、リカバリに長い時間を要する障害があります。

通常、インダウト分散トランザクションをローカルで強制する場合は、別の場所の管理者と相談した上で決断する必要があります。判断を誤るとデータベースの一貫性が損われ、トレースが困難で手動での修正が必要となる恐れがあります。

これらの条件のいずれも当てはまらない場合、データベースの自動リカバリ機能を常に許可し、トランザクションを完了してください。しかし、前述のいずれかの条件に当てはまる場合には、インダウト・トランザクションのローカルでの修正を検討してください。

35.4.3 トランザクション・データの分析

トランザクションの完了を強制する場合は、入手可能な情報を分析します。

35.4.3.1 コミットまたはロールバックされたノードの特定

DBA_2PC_PENDINGビューを使用し、トランザクションをコミットまたはロールバックしたノードを探します。

トランザクションをすでに解決しているノードが見つかった場合は、そのノードで実行された処理に従うことができます。

35.4.3.2 トランザクション・コメントの確認

DBA_2PC_PENDINGTRAN_COMMENT列に、対象の分散トランザクションに関するなんらかの情報が与えられていないかを確認します。

COMMIT文のCOMMENT句にコメントが含まれているか、またはトランザクションに命名している場合は、トランザクションがコミットされると、トランザクション名がTRAN_COMMENTフィールドに設定されます。

たとえば、インダウト分散トランザクションのコメントで、トランザクションの開始元とタイプを示すことができます。

COMMIT COMMENT 'Finance/Accts_pay/Trans_type 10B';

また、この情報をトランザクション名として提供するために、SET TRANSACTION...NAME文を使用することも可能です。

35.4.3.3 トランザクション・アドバイスの確認

DBA_2PC_PENDINGADVICE列に、対象の分散トランザクションに関するなんらかの情報が与えられていないかを確認します。

アプリケーションでALTER SESSION文のADVISE句を使用すれば、分散トランザクションの別々の部分を強制的にコミットまたはロールバックする際のアドバイスを規定できます。

準備フェーズ中に各ノードに送られたアドバイスは、現行トランザクション内でそのデータベースに対し最新のDML文が実行されたときに有効なアドバイスです。

たとえば、あるノードのemp表から別のノードのemp表に従業員レコードを移動する分散トランザクションを考えます。次の一連のSQL文を追加することによって、管理者が各ノードで個別にインダウト・トランザクションを強制的に完了した場合でも、トランザクションでレコードを保護できます。

ALTER SESSION ADVISE COMMIT;
INSERT INTO emp@hq ... ;    /*advice to commit at HQ */
ALTER SESSION ADVISE ROLLBACK;
DELETE FROM emp@sales ... ; /*advice to roll back at SALES*/

ALTER SESSION ADVISE NOTHING;

与えられたアドバイスに従ってインダウト・トランザクションを手動で強制的に完了すると、最悪の場合、各ノードに従業員レコードがコピーされ、消去できなくなる可能性があります。

35.5 インダウト・トランザクションの手動上書き

COMMIT文またはROLLBACK文に、FORCEオプションと、コミットまたはロールバックするインダウト・トランザクションのローカル・トランザクションIDまたはグローバル・トランザクションIDを示すテキスト文字列を指定します。

注意:

以降のすべての例で、トランザクションはローカル・ノードでコミットまたはロールバックされます。ローカルのペンディング・トランザクション表では、このトランザクションの行のSTATE列に強制コミットまたは強制終了の値が記録されます。

35.5.1 インダウト・トランザクションの手動コミット

トランザクションIDまたはSCNを使用して、手動でインダウト・トランザクションをコミットできます。

35.5.1.1 インダウト・トランザクションのコミットに必要な権限

トランザクションのコミットを試みる前に、適正な権限を持っていることを確認してください。

次の要件に注意してください。

トランザクションをコミットするユーザー 必要な権限

管理者

FORCE TRANSACTION

別のユーザー

FORCE ANY TRANSACTION

35.5.1.2 トランザクションIDのみを使用したコミット

トランザクションIDを使用して、インダウト・トランザクションをコミットできます。

次のSQL文は、インダウト・トランザクションをコミットします。

COMMIT FORCE 'transaction_id';

変数transaction_idは、DBA_2PC_PENDINGデータ・ディクショナリ・ビューのLOCAL_TRAN_ID列またはGLOBAL_TRAN_ID列のどちらかで指定されているトランザクション識別子です。

たとえば、DBA_2PC_PENDINGを問い合せて、分散トランザクションのLOCAL_TRAN_ID1:45.13であることを確認するとします。

そして、次のSQL文を発行し、このインダウト・トランザクションのコミットを強制実行します。

COMMIT FORCE '1.45.13';

35.5.1.3 システム変更番号(SCN)を使用したコミット

SCNを使用して、インダウト・トランザクションをコミットできます。

必要であれば、トランザクションを強制的にコミットするときに、トランザクションのSCNを指定することもできます。この機能を使用すると、他のノードでトランザクションがコミットされたときに割り当てられたSCNを使用して、インダウト・トランザクションをコミットできます。

これにより、障害が発生した場合でも、分散トランザクションのコミット時間の同期を保つことができます。SCNは、別のノードですでにコミットされた同じトランザクションのSCNが判別できるときのみ指定してください。

たとえば、次のグローバル・トランザクションIDを使用してトランザクションを手動でコミットするとします。

SALES.EXAMPLE.COM.55d1c563.1.93.29 

まず、対象のトランザクションに関係しているリモート・データベースのDBA_2PC_PENDINGビューを問い合せます。次に、そのノードでトランザクションのコミットに使用されたSCNをメモします。そして、ローカル・ノードでトランザクションをコミットするときにこのSCNを指定します。たとえば、SCNが829381993の場合は、次の文を発行します。

COMMIT FORCE 'SALES.EXAMPLE.COM.55d1c563.1.93.29', 829381993;

関連項目:

COMMIT文の使用の詳細は、『Oracle Database SQL言語リファレンス』

35.5.2 インダウト・トランザクションの手動ロールバック

トランザクションIDを使用して、インダウト・トランザクションをロールバックできます。

インダウト分散トランザクションのロールバックを試みる前に、適正な権限を持っていることを確認してください。次の要件に注意してください。

トランザクションをコミットするユーザー 必要な権限

管理者

FORCE TRANSACTION

別のユーザー

FORCE ANY TRANSACTION

次のSQL文は、インダウト・トランザクションをロールバックします。

ROLLBACK FORCE 'transaction_id';

変数transaction_idは、DBA_2PC_PENDINGデータ・ディクショナリ・ビューのLOCAL_TRAN_ID列またはGLOBAL_TRAN_ID列のどちらかで指定されているトランザクション識別子です。

たとえば、ローカル・トランザクションIDが2.9.4のインダウト・トランザクションをロールバックするには、次の文を使用します。

ROLLBACK FORCE '2.9.4';

注意:

インダウト・トランザクションをセーブポイントまでロールバックすることはできません。

関連項目:

ROLLBACK文の詳細は、『Oracle Database SQL言語リファレンス』

35.6 データ・ディクショナリからの保留行のパージ

インダウト・トランザクション用のデータ・ディクショナリから保留中の行をパージできます。

35.6.1 データ・ディクショナリからの保留中の行のパージについて

DBMS_TRANSACTION.PURGE_MIXEDプロシージャまたはDBMS_TRANSACTION.PURGE_LOST_DB_ENTRYプロシージャを使用して、インダウト・トランザクション用のデータ・ディクショナリから保留中の行をパージできます。

インダウト・トランザクションは、RECO(リカバラ・プロセス)によってリカバリされる前に、DBA_2PC_PENDING.STATE列にCOLLECTINGCOMMITTEDまたはPREPAREDとして表示されます。COMMIT FORCEまたはROLLBACK FORCEを使用してインダウト・トランザクションを強制的に完了すると、FORCED COMMITまたはFORCED ROLLBACKの状態になることがあります。

自動リカバリでは通常、これらの状態にあるエントリが削除されます。唯一の例外として、リカバリ時に、トランザクション内の他のサイトと一貫性のない状態にある強制トランザクションが検出されるときがあります。この場合は、エントリが表内に残る可能性があり、DBA_2PC_PENDINGMIXED列の値がYESになります。これらのエントリは、DBMS_TRANSACTION.PURGE_MIXEDプロシージャを使用してクリーン・アップできます。

リモート・データベースが永続的に失われたために自動リカバリが不可能な場合は、データベースを再作成しても再作成時に新しいデータベースIDが割り当てられるため、リカバリではそのデータベースを識別できません。このような場合、DBMS_TRANSACTIONパッケージのPURGE_LOST_DB_ENTRYプロシージャを使用してエントリをクリーン・アップする必要があります。このエントリによってデータベース・リソースが保持されることはないため、エントリのクリーン・アップを急ぐ必要はありません。

関連項目:

DBMS_TRANSACTIONパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

35.6.2 PURGE_LOST_DB_ENTRYプロシージャの実行

データ・ディクショナリのインダウト・トランザクション・エントリをクリーンアップするには、DBMS_TRANSACTION.PURGE_LOST_DB_ENTRYプロシージャを使用します。

エントリをデータ・ディクショナリから手動で削除するには、次の構文を使用します(ここで、trans_idはトランザクションの識別子を表します)。

DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('trans_id');

たとえば、保留中の分散トランザクション1.44.99をパージするには、SQL*Plusで次の文を入力します。

EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('1.44.99');

このプロシージャは、自動リカバリによってトランザクションを解決できないほどの大幅な再構成を行った場合にのみ実行してください。たとえば、次のような場合です。

  • リモート・データベースが完全に失われた場合

  • ソフトウェアを再構成した結果、2フェーズ・コミットの機能がなくなった場合

  • TPMonitorなどの外部トランザクション・コーディネータからの情報が失われた場合

35.6.3 DBMS_TRANSACTIONを使用する時期の判断

通常、分散トランザクションの状態に基づいて特定のアクションを実行する必要があります。

次の表は、分散トランザクションに関する各種の状態と、それに対して管理者が実行すべき処理を示したものです。

STATE列 グローバル・トランザクションの状態 ローカル・トランザクションの状態 通常の処理 代替処理

Collecting

ロールバック

ロールバック

なし

PURGE_LOST_DB_ENTRY(自動リカバリでトランザクションを解決できない場合のみ)

Committed

Committed

Committed

なし

PURGE_LOST_DB_ENTRY(自動リカバリでトランザクションを解決できない場合のみ)

Prepared

不明

Prepared

なし

強制コミットまたは強制ロールバック

Forced commit

不明

Committed

なし

PURGE_LOST_DB_ENTRY(自動リカバリでトランザクションを解決できない場合のみ)

Forced rollback

不明

ロールバック

なし

PURGE_LOST_DB_ENTRY(自動リカバリでトランザクションを解決できない場合のみ)

Forced commit

混合

Committed

非一貫性部分を手動で削除してからPURGE_MIXEDを使用する

-

Forced rollback

混合

ロールバック

非一貫性部分を手動で削除してからPURGE_MIXEDを使用する

-

35.7 インダウト・トランザクションの手動コミット: 例

例は、手動によるインダウト・トランザクションのコミットを示しています。

図35-1は、分散トランザクションのコミット中の障害を示しています。この障害例では、準備フェーズは完了しています。しかし、コミット・フェーズ時に、コミット・ポイント・サイトがトランザクションをコミットしていても、コミット・ポイント・サイトのコミット確認がグローバル・コーディネータに到達しません。インダウト・トランザクションは他のトランザクションにとっても重要なものであるため、在庫データはロックされており、アクセスできません。また、インダウト・トランザクションがコミットまたはロールバックされるまで、ロックが必ず保持されます。

図35-1 インダウト分散トランザクションの例

図35-1の説明が続きます
「図35-1 インダウト分散トランザクションの例」の説明

手動により、インダウト・トランザクションのローカル部分を強制できます。

35.7.1 手順1: ユーザーからのフィードバックの記録

例は、インダウト・トランザクションのユーザーからのフィードバックの記録を示しています。

インダウト・トランザクションのロックと競合を起こしているローカル・データベース・システムのユーザーは、次のエラー・メッセージを受け取ります。

ORA-01591: lock held by in-doubt distributed transaction 1.21.17

この場合、1.21.17はインダウト分散トランザクションのローカル・トランザクションIDです。どのインダウト・トランザクションを強制処理すればよいかを特定するために、問題を報告したユーザーからこのID番号を聞き、記録しておきます。

35.7.2 手順2: DBA_2PC_PENDINGの問合せ

例は、DBA_2PC_PENDINGデータ・ディクショナリ・ビューのインダウト・トランザクションに関する情報の問合せを示しています。

SQL*Plusを使用してwarehouseに接続した後、ローカルのDBA_2PC_PENDINGデータ・ディクショナリ・ビューを問い合せて、インダウト・トランザクションに関する情報を取得します。

CONNECT SYS@warehouse.example.com AS SYSDBA
SELECT * FROM DBA_2PC_PENDING WHERE LOCAL_TRAN_ID = '1.21.17';

データベースは次の情報を返します。

Column Name            Value
---------------------- --------------------------------------
LOCAL_TRAN_ID          1.21.17
GLOBAL_TRAN_ID         SALES.EXAMPLE.COM.55d1c563.1.93.29
STATE                  prepared
MIXED                  no
ADVICE
TRAN_COMMENT           Sales/New Order/Trans_type 10B
FAIL_TIME              31-MAY-91
FORCE_TIME
RETRY_TIME             31-MAY-91
OS_USER                SWILLIAMS
OS_TERMINAL            TWA139:
HOST                   system1
DB_USER                SWILLIAMS
COMMIT#

35.7.2.1 グローバル・トランザクションIDの判断

グローバル・トランザクションIDは、分散トランザクションのすべてのノードで同一である共通のトランザクションIDです。

次のような書式で記録されています。

global_database_name.hhhhhhhh.local_transaction_id

説明:

  • global_database_nameは、グローバル・コーディネータのデータベース名です。

  • hhhhhhhhは、グローバル・コーディネータの内部データベース識別子(16進値)です。

  • local_transaction_idは、グローバル・コーディネータで割り当てられた、対応するローカル・トランザクションIDです。

グローバル・コーディネータでは、グローバル・トランザクションIDの最後の部分とローカル・トランザクションIDが一致します。この例では、これらの番号が一致していないため、warehouseがグローバル・コーディネータではないことがわかります。

LOCAL_TRAN_ID          1.21.17
GLOBAL_TRAN_ID         ... 1.93.29

35.7.2.2 トランザクションの状態の判断

DBA_2PC_PENDINGデータ・ディクショナリ・ビューのSTATE列は、トランザクションの状態を示します。

このノードのトランザクションは、準備完了状態です。

STATE          prepared 

したがって、warehouseは、自身のコーディネータからコミット要求またはロールバック要求が送られてくるのを待っています。

35.7.2.3 コメントまたはアドバイスの確認

DBA_2PC_PENDINGデータ・ディクショナリ・ビューのTRANS_COMMENT列は、トランザクションのために含まれているコメントを示し、ADVICE列はアドバイスを提供します。

トランザクションのコメントまたはアドバイスに、このトランザクションに関する情報が含まれている可能性があります。トランザクションに関する情報が含まれていれば、そのコメントを利用します。この例では、トランザクションのコメントに開始元とトランザクション・タイプが含まれています。

TRAN_COMMENT           Sales/New Order/Trans_type 10B

また、SET TRANSACTION...NAME文によって、トランザクション名として提供されている可能性もあります。

この情報から、トランザクションのローカル部分をコミットすべきか、またはロールバックすべきかを決める際に役立つ情報を得ることができます。インダウト・トランザクションに有益なコメントが付けられていない場合は、その他の管理作業を実行し、セッション・ツリーをトレースして、トランザクションをすでに解決しているノードを探す必要があります。

35.7.3 手順3: ローカル・ノードでのDBA_2PC_NEIGHBORSの問合せ

この手順の目的は、セッション・ツリーを探索してコーディネータを見つけ、最終的にグローバル・コーディネータに到達することです。

それと同時に、トランザクションをすでに解決しているコーディネータが見つかる場合もあります。見つからない場合は、最終的にコミット・ポイント・サイトを探し出します(コミット・ポイント・サイトでは、常にインダウト・トランザクションが解決されています)。セッション・ツリーをトレースするには、各ノードのDBA_2PC_NEIGHBORSビューを問い合せます。

この例では、warehouseデータベースでこのビューを問い合せます。

CONNECT SYS@warehouse.example.com AS SYSDBA
SELECT * FROM DBA_2PC_NEIGHBORS
  WHERE LOCAL_TRAN_ID = '1.21.17'
  ORDER BY SESS#, IN_OUT;

Column Name            Value
---------------------- --------------------------------------
LOCAL_TRAN_ID          1.21.17
IN_OUT                 in
DATABASE               SALES.EXAMPLE.COM
DBUSER_OWNER           SWILLIAMS
INTERFACE              N
DBID                   000003F4
SESS#                  1
BRANCH                 0100

35.7.3.1 データベースのロールとデータベース・リンク情報の取得

DBA_2PC_NEIGHBORSビューは、インダウト・トランザクションに対応付けられた接続に関する情報を提供します。

情報は、接続が受信(IN_OUT = in)か送信(IN_OUT = out)かによって異なります。

IN_OUT 意味 DATABASE DBUSER_OWNER

in

このノードは別のノードのサーバーです。

このノードに接続しているクライアント・データベースの名前がリストされます。

インダウト・トランザクションに対応するデータベース・リンク接続のローカル・アカウントがリストされます。

out

このノードは他のサーバーのクライアントです。

リモート・ノードに接続しているデータベース・リンクの名前がリストされます。

インダウト・トランザクションのデータベース・リンクの所有者がリストされます。

この例では、IN_OUT列によって、warehouseデータベースがsalesクライアント(DATABASE列に示されている)のサーバーであることがわかります。

IN_OUT                 in
DATABASE               SALES.EXAMPLE.COM

warehouseへの接続は、swilliamsアカウント(DBUSER_OWNER列に示されている)からのデータベース・リンクを介して確立されています。

DBUSER_OWNER           SWILLIAMS

35.7.3.2 コミット・ポイント・サイトの判別

INTERFACE列は、ローカル・ノードまたは下位ノードがコミット・ポイント・サイトかどうかを示します。

INTERFACE              N

INTERFACE列が示すように、warehouseもその子もコミット・ポイント・サイトではありません。

35.7.4 手順4: 全ノードでのデータ・ディクショナリ・ビューの問合せ

この時点で、各設置ノードの管理者に連絡を取り、グローバル・トランザクションIDを使用して手順2および3を繰り返すように各管理者に依頼できます。

注意:

これらのノードに別のネットワークを介して直接接続できる場合は、手順2および3を独力で実行できます。

たとえば、salesおよびhqで手順2および3を実行すると、次の結果が返されます。

35.7.4.1 salesでのペンディング・トランザクションの状態の確認

この段階では、salesの管理者がDBA_2PC_PENDINGデータ・ディクショナリ・ビューを問い合せます。

SQL> CONNECT SYS@sales.example.com AS SYSDBA
SQL> SELECT * FROM DBA_2PC_PENDING
   > WHERE GLOBAL_TRAN_ID = 'SALES.EXAMPLE.COM.55d1c563.1.93.29';

Column Name            Value
---------------------- --------------------------------------
LOCAL_TRAN_ID          1.93.29
GLOBAL_TRAN_ID         SALES.EXAMPLE.COM.55d1c563.1.93.29
STATE                  prepared
MIXED                  no
ADVICE
TRAN_COMMENT           Sales/New Order/Trans_type 10B
FAIL_TIME              31-MAY-91
FORCE_TIME
RETRY_TIME             31-MAY-91
OS_USER                SWILLIAMS
OS_TERMINAL            TWA139:
HOST                   system1
DB_USER                SWILLIAMS
COMMIT#

35.7.4.2 salesでのコーディネータとコミット・ポイント・サイトの判別

次に、salesの管理者はDBA_2PC_NEIGHBORSを問い合せて、グローバル・コーディネータ、ローカル・コーディネータおよびコミット・ポイント・サイトを判別します。

SELECT * FROM DBA_2PC_NEIGHBORS
   WHERE GLOBAL_TRAN_ID = 'SALES.EXAMPLE.COM.55d1c563.1.93.29'
   ORDER BY SESS#, IN_OUT;

この問合せは、次の3行を返します。

  • warehouseへの接続

  • hqへの接続

  • ユーザーが確立した接続

warehouse接続の行に対応する情報を、書式を変えて示すと次のようになります。

Column Name            Value
---------------------- --------------------------------------
LOCAL_TRAN_ID          1.93.29
IN_OUT                 OUT
DATABASE               WAREHOUSE.EXAMPLE.COM
DBUSER_OWNER           SWILLIAMS
INTERFACE              N
DBID                   55d1c563
SESS#                  1
BRANCH                 1

hq接続の行に対応する情報を、書式を変えて示すと次のようになります。

Column Name            Value
---------------------- --------------------------------------
LOCAL_TRAN_ID          1.93.29
IN_OUT                 OUT
DATABASE               HQ.EXAMPLE.COM
DBUSER_OWNER           ALLEN
INTERFACE              C
DBID                   00000390
SESS#                  1
BRANCH                 1

前の問合せから得られた情報によって、次のことがわかります。

  • salesは、ローカル・トランザクションIDとグローバル・トランザクションIDが一致しているため、グローバル・コーディネータです。

  • このノードからは送信接続が2つ確立されていますが、受信接続は確立されていません。したがって、salesは別のノードのサーバーではありません。

  • コミット・ポイント・サイトは、hqまたはそのサーバーの1つです。

35.7.4.3 HQでのペンディング・トランザクションの状態の確認

この段階では、hqの管理者がDBA_2PC_PENDINGデータ・ディクショナリ・ビューを問い合せます。

SELECT * FROM DBA_2PC_PENDING@hq.example.com
   WHERE GLOBAL_TRAN_ID = 'SALES.EXAMPLE.COM.55d1c563.1.93.29';

Column Name            Value
---------------------- --------------------------------------
LOCAL_TRAN_ID          1.45.13
GLOBAL_TRAN_ID         SALES.EXAMPLE.COM.55d1c563.1.93.29
STATE                  COMMIT
MIXED                  NO
ACTION
TRAN_COMMENT           Sales/New Order/Trans_type 10B
FAIL_TIME              31-MAY-91
FORCE_TIME
RETRY_TIME             31-MAY-91
OS_USER                SWILLIAMS
OS_TERMINAL            TWA139:
HOST                   SYSTEM1
DB_USER                SWILLIAMS
COMMIT#                129314

この時点で、トランザクションを解決しているノードが見つかりました。ビューが示しているように、このノードではコミットが完了しており、コミットID番号が割り当てられています。

STATE                  COMMIT
COMMIT#                129314

したがって、自分のローカル・データベースでインダウト・トランザクションを強制的にコミットできます。この調査結果を他の管理者に伝えれば、他の場所での解決に役立つ可能性があります。

35.7.5 手順5: インダウト・トランザクションのコミット

グローバルIDを使用してインダウト・トランザクションをコミットします。

salesデータベースの管理者と連絡を取り、グローバルIDを使用してインダウト・トランザクションを手動でコミットするように依頼します。

SQL> CONNECT SYS@sales.example.com AS SYSDBA
SQL> COMMIT FORCE 'SALES.EXAMPLE.COM.55d1c563.1.93.29';

同時に、warehouseデータベースの管理者として、グローバルIDを使用してインダウト・トランザクションを手動でコミットします。

SQL> CONNECT SYS@warehouse.example.com AS SYSDBA
SQL> COMMIT FORCE 'SALES.EXAMPLE.COM.55d1c563.1.93.29';

35.7.6 手順6: DBA_2PC_PENDINGを使用したMIXED結果のチェック

トランザクションを手動で強制的にコミットまたはロールバックした後も、ペンディング・トランザクション表の対応する行はそのまま残っています。トランザクションの状態は、トランザクションをどのように強制完了したかに応じて変わります。

Oracle Databaseには、必ずペンディング・トランザクション表があります。これは、2フェーズ・コミットの各フェーズの進行に従って分散トランザクションに関する情報を格納する特別な表です。データベースのペンディング・トランザクション表は、DBA_2PC_PENDINGデータ・ディクショナリ・ビューを介して問い合せることができます(詳細は表35-1を参照)。

また、ペンディング・トランザクション表で特に重要なものとして、DBA_2PC_PENDING.MIXEDに示されるMIXED結果フラグがあります。ペンディング・トランザクションを強制的にコミットまたはロールバックする場合は、選択を誤る可能性があります。たとえば、ローカル管理者がトランザクションをロールバックしたにもかからわず、他のノードではそのトランザクションをコミットしてしまうといったことが考えられます。このような誤った判断は自動的に検出され、対応するペンディング・トランザクションのレコードに損傷フラグが設定されます(MIXED=yes)。

RECOバックグラウンド・プロセスは、ペンディング・トランザクション表の情報を使用して、インダウト・トランザクションの状態を最終決定します。また、管理者がペンディング・トランザクション表の情報を使用して、保留中の分散トランザクションの自動リカバリ手順を手動で上書きすることもできます。

RECOによって自動解決されたトランザクションはすべて、保留中のトランザクション表から削除される。また、管理者によって正しく解決されたインダウト・トランザクションに関する情報も、RECOが通信を再確立したときにチェックされて、すべてペンディング・トランザクション表から自動的に削除されます。ただし、管理者が解決したことによってノード間にまたがってMIXEDの結果が生じた行は、DBMS_TRANSACTIONS.PURGE_MIXEDを使用して手動で削除しないかぎり、関係しているすべてのノードのペンディング・トランザクション表にそのまま残ります。

35.8 ロックによるデータ・アクセスの障害

SQL文を発行すると、データベースは文を正常に実行するために必要なリソースのロックを試みます。しかし、要求されたデータが、コミットされていない他のトランザクションの文によって現在保持されていて、長時間ロックされたままになっていると、タイムアウトが発生します。

35.8.1 トランザクションのタイムアウト

リモート・データベースのロックを必要とするDML文は、要求したデータのロックを別のトランザクションが所有している場合にブロックされる可能性があります。

このようなロックによってSQL文の要求がブロックされ続けると、次の一連のイベントが発生します。

  1. タイムアウトが発生します。

  2. データベースは文をロールバックします。

  3. データベースは次のエラー・メッセージをユーザーに返します。

    ORA-02049: time-out: distributed transaction waiting for lock
    

トランザクションによってデータは変更されていないので、タイムアウトの結果として必要な処理はありません。アプリケーションでは、デッドロックが発生したものとして処理を継続してください。文を実行したユーザーは、後で同じ文の再実行を試みることができます。それでもロックが続く場合には、ユーザーは管理者に連絡して問題を報告してください。

35.8.2 インダウト・トランザクションによるロック

ローカル・データベースのロックを必要とする問合せまたはDML文は、インダウト分散トランザクションによるリソースのロックのために無期限にブロックされる可能性があります。

この場合、データベースは次のエラー・メッセージを発行します。

ORA-01591: lock held by in-doubt distributed transaction identifier

この場合、データベースはSQL文をただちにロールバックします。文を実行したユーザーは、後で同じ文の再実行を試みることができます。ロックが持続する場合、ユーザーは管理者に連絡して、インダウト分散トランザクションのIDなども含めて問題を報告する必要があります。

2フェーズ・コミットの重要な部分の処理中に障害が発生する確率は低いため、このような状況が起こる可能性はほとんどありません。仮にこのような障害が発生した場合でも、ネットワーク障害やシステム障害から迅速にリカバリできれば、手動で介入しなくても問題は自動的に解決されます。したがって、この種の問題は、ユーザーやデータベース管理者に検出される前に解決されるのが普通です。

35.9 分散トランザクション障害のシミュレーション

自動的にトランザクションのローカル部分を解決するRECOを観察するため、または手動でインダウト分散トランザクションを解決してその結果を観察するために、分散トランザクションの障害を強制できます。

35.9.1 分散トランザクションの強制障害

COMMIT文のCOMMENTパラメータには、コメントを挿入できます。

分散トランザクションの2フェーズ・コミットのフェーズ時に意図して障害を発生させるには、COMMENTパラメータに、次のコメントを挿入します。

COMMIT COMMENT 'ORA-2PC-CRASH-TEST-n';

コメント内のnには、次の整数のいずれかが入ります。

n 影響

1

収集後コミット・ポイントをクラッシュ

2

収集後コミット・ポイント・サイト以外をクラッシュ

3

準備前にクラッシュ(コミット・ポイント・サイト以外)

4

準備後にクラッシュ(コミット・ポイント・サイト以外)

5

コミット前にコミット・ポイント・サイトをクラッシュ

6

コミット後にコミット・ポイント・サイトをクラッシュ

7

コミット前にコミット・ポイント・サイト以外をクラッシュ

8

コミット後にコミット・ポイント・サイト以外をクラッシュ

9

情報消去前にコミット・ポイント・サイトをクラッシュ

10

情報消去前にコミット・ポイント・サイト以外をクラッシュ

たとえば、ローカルのコミット・ポイント強度がリモートのコミット・ポイント強度よりも高く、双方のノードが更新されている場合、次の文では、次のメッセージが返されます。

COMMIT COMMENT 'ORA-2PC-CRASH-TEST-7';

ORA-02054: transaction 1.93.29 in-doubt
ORA-02059: ORA_CRASH_TEST_7 in commit comment

この時点で、インダウト分散トランザクションがDBA_2PC_PENDINGビューに表示されます。対応している場合は、RECOがそのトランザクションを自動的に解決します。

35.9.2 RECOの有効化と無効化

Oracle DatabaseインスタンスのRECOバックグラウンド・プロセスは、分散トランザクションに伴う障害を自動的に解決します。ノードのRECOバックグラウンド・プロセスは、時間間隔を指数関数的に広げながら、インダウト分散トランザクションのローカル部分のリカバリを試みます。

RECOは、障害を起こしたトランザクションに関係している他のノードに対して、既存の接続を使用するか、または新しい接続を確立できます。接続が確立されると、RECOはすべてのインダウト・トランザクションを自動的に解決します。各データベースのペンディング・トランザクション表内にインダウト・トランザクションに対応している行があれば、自動的に削除されます。

ENABLE/DISABLE DISTRIBUTED RECOVERYオプションを指定してALTER SYSTEM文を使用すると、RECOを使用可能または使用禁止にできます。たとえば、RECOを一時的に使用禁止にして2フェーズ・コミットの障害を強制的に発生させ、インダウト・トランザクションを手動で解決できます。

次の文は、RECOを使用禁止にします。

ALTER SYSTEM DISABLE DISTRIBUTED RECOVERY;

一方、次の文はRECOを使用可能にし、インダウト・トランザクションが自動的に解決されるようにします。

ALTER SYSTEM ENABLE DISTRIBUTED RECOVERY;

35.10 読込み一貫性の管理

Oracle Databaseの分散読込み一貫性の実装には重要な制限事項があります。

問題の原因は、各システムには独自のSCNがあり、データベースの内部的なタイムスタンプとして表示できることです。Oracle Databaseサーバーは、SCNを使用して、どのバージョンのデータが問合せから返されるかを判断します。

分散トランザクションのSCNは、各リモートSQL文の最後、および各トランザクションの最初と最後に同期化されます。2つのノード間の通信量が多く、特に分散更新がある場合には、この同期化が頻繁に実行されます。しかし、分散システムのSCNの絶対的な同期を保つための実用的な手段は存在しません。つまり、あるノードのSCNが別のノードのSCNと比べて幾分古くなるというような状況が常に存在します。

このようなSCNの食い違いから、実行した問合せがわずかに古いスナップショットを使用する可能性があり、その問合せ結果には、リモート・データベースに対する最新の変更が含まれていません。そのため、問合せを実行したときに、読込み一貫性に従ってデータが取得されているにもかからわず、そのデータが古い場合があります。そのような問合せによって取得したデータはすべて古いSCNに基づいているため、ローカルに実行した更新トランザクションによってリモート・ノードの2つの表が更新された場合、次回のリモート・アクセスで両方の表から選択したデータには、更新前のデータが含まれることになります。

SCNが食い違っているために起こりうる結果の1つとして、SELECT文が2つ連続している場合に、それら2つの文の間でDMLをまったく実行していなくても各文で異なるデータが取得されることがあります。たとえば、UPDATE文を発行して、リモート・データベースで更新をコミットしたとします。このリモート表に基づくビューに対してSELECT文を発行すると、ビューには更新された行が表示されません。次にSELECT文を発行するときは、更新された行が表示されます。

次の手法を使用すると、問合せの直前に2つのシステムのSCNが必ず同期化されます。

  • SCNはリモート問合せの最後に同期化されるので、各リモート問合せの前に、同じサイトでSELECT * FROM DUAL@REMOTEというようなダミーのリモート問合せを実行します。

  • SCNはすべてのリモート・トランザクションの最初に同期化されるので、リモート問合せを発行する前に、現行トランザクションをコミットまたはロールバックします。