22 Oracle XAを使用したアプリケーションの開発

ノート:

次の理由により、可能であればXAは使用しないでください。

  • XAではパフォーマンスが低下する可能性があります。

  • XAではインダウト・トランザクションが発生する可能性があります。

  • XAは、リカバリ可能な停止後に、アプリケーションを続行する機能を拡張するために、Oracle Database 12cリリース1 (12.1.0.1)の機能の利点を活用できない場合もあります。

不可避と思われる(たとえば、OracleとOracle以外のリソースを同一トランザクションで使用する必要がある)場合でも、XAの使用を回避できることがあります。

この章では、Oracle XAライブラリの使用方法について説明します。通常、このライブラリはトランザクション・モニターで作業するアプリケーションで使用します。XAの機能は、トランザクションが複数のデータベースと相互処理するアプリケーションで最も効果的です。

トピック:

関連項目:

22.1 X/Open DTP

X/Open Distributed Transaction Processing(DTP)アーキテクチャは、複数のアプリケーション・プログラム(AP)が複数の異なるリソース・マネージャ(RM)から提供されるリソースを共有できるようにするための、標準のアーキテクチャまたはインタフェースを定義しています。APとRM間の作業を調整し、グローバル・トランザクションを実現します。

Oracle XAライブラリは、X/Openソフトウェア・アーキテクチャのXAインタフェース仕様に準拠しています。Oracle XAライブラリは外部インタフェースであり、Oracleのクライアント側トランザクション・マネージャ(TM)以外のクライアント側TMがグローバル・トランザクションを調整可能にすることで分散トランザクションにOracle Database以外のRMを組み込めるようにします。たとえば、クライアント・アプリケーションでは、Oracle DatabaseトランザクションとNTFSファイル・システム内のトランザクションを1つのグローバル・トランザクションとして管理できます。

図22-1に、X/Open DTPモデルの例を示します。

トピック:

22.1.1 DTP用語

リソース・マネージャ(RM)

リソース・マネージャは、障害発生後に通常の状態に戻すことができる共有かつリカバリ可能なリソースを制御します。たとえば、リレーショナル・データベース、トランザクション・キューおよびトランザクション・ファイル・システムなどです。Oracle DatabaseはRMであり、障害発生後にREDOログおよびロールバック・セグメントを使用して一貫性のある状態に復帰します。

分散トランザクション

分散トランザクションは、複数の分散リソースに対する更新を伴い、分散RM間で「すべてまたはなし」のセマンティクスを必要とするクライアント・トランザクションであり、グローバル・トランザクションとも呼ばれます。

ブランチ

ブランチは、1つのRMに含まれる1つの作業単位です。複数のブランチが1つのグローバル・トランザクションを構成します。Oracle Databaseの場合、各ブランチはデータベース・サーバー内のローカル・トランザクションにマップします。

トランザクション・マネージャ(TM)

トランザクション・マネージャは、トランザクション境界を指定するためのAPIを提供し、コミットおよびリカバリを管理します。TMでは、分散RM間で「すべてまたはなし」のセマンティクスを提供する2フェーズ・コミット・エンジンが実装されます。

外部TMとは、Oracle Databaseの外部に常駐する中間層コンポーネントです。通常、データベースには固有の内部TMがあります。業界標準に準拠したTMを使用することで、Oracle Databaseは単一のトランザクション内で他の異機種間RMと共存できます。

トランザクション処理モニター(TPM)

TMは、通常、次のようなトランザクション処理モニター(TPM)が提供します。

  • Oracle Tuxedo

  • IBM Transarc Encina

  • IBM CICS

TPMは、トランザクション要求を発行するクライアント・プロセスとその要求を処理するバックエンド・サーバー間の要求フローを調整します。TPMは、基本的にネットワーク上に分散されているアプリケーション・サーバーやRMなどのように、様々な種類のバックエンド・プロセスに対してサービスを要求するトランザクションを調整します。

TPMは、分散トランザクションを完了するために必要なコミットまたはロールバックを同期化します。TPMのTM部分が、分散コミットおよび分散ロールバックの発生するタイミングを制御します。このため、分散APでTPMを利用する場合、TPMのTM部分が2フェーズ・コミット・プロトコルを制御します。RMを使用して、TMはこのタスクを実行します。

TMは分散コミットまたはロールバックを制御するため、XAインタフェースを介してOracle Database(または他のRM)と直接通信する必要があります。TMは、トランザクション内のすべてのRMに関する情報に基づいて、Oracle XAライブラリ・サブプログラムで説明するOracle XAライブラリ・サブプログラムを使用してOracle Databaseにトランザクションの処理方法を指示します。

2フェーズ・コミット・プロトコル

Oracle XAライブラリ・インタフェースは、2フェーズ・コミット・プロトコルに従います。各イベントの順序は次のとおりです。

  1. 準備フェーズでは、TMは各RMに対して、トランザクションの任意の部分をコミットできるように要求します。これが可能な場合は、RMは準備ができた状態を記録し、TMに肯定的に応答します。可能でない場合は、RMはすべての作業をロールバックし、TMに否定的に応答し、そのトランザクションに関する情報を消去します。プロトコルによって、アプリケーションまたはRMは、準備フェーズが完了する前にトランザクションを一方的にロールバックできます。

  2. フェーズ2では、TMはコミット決定を記録し、トランザクションに参加しているすべてのRMに対してコミットまたはロールバックを発行します。TMは、すべてのRMがフェーズ1に対して肯定的に応答した場合にのみ、RMのコミットを発行できます。

アプリケーション・プログラム(AP)

アプリケーション・プログラムは、トランザクション境界を定義し、トランザクションを構成するアクションを指定します。たとえば、APはプリコンパイラでもOracle Call Interface(OCI)プログラムでもかまいません。APは、RMのネイティブ・インタフェース(たとえばSQL)を使用して、RMのリソースを操作します。

TXインタフェース

アプリケーション・プログラムは、TMを介し、TXと呼ばれるインタフェースを使用してすべてのトランザクション制御操作を開始および完了します。APがXAインタフェースを直接使用することはありません。APが中間層で分岐するブランチを認識することはありません。アプリケーション・スレッドがブランチの作業を明示的に結合、休止、一時停止および再開するかわりに、トランザクション処理モニターのTM部分がAPのためにグローバル・トランザクションのブランチを管理します。最終的に、APはTMをコールしてすべてをコミットするか、または何もコミットしません。

ノート:

TXインタフェースおよびその関連のサブプログラムのネーミング規則はベンダー固有です。たとえば、tx_openコールは、使用中のシステムではtp_openと呼ばれている場合があります。また、トランザクションRPCへの入力時など、このコールが暗黙的な場合もあります。詳細は、トランザクション処理モニターに付属のマニュアルを参照してください。

密結合と疎結合

RMですべての分離セマンティクスについて単一エンティティとみなされるアプリケーション・スレッドは、密結合となります。密結合ブランチは、相互の変更を認識する必要があります。さらに、外部クライアントは、密結合セットの変更をすべて認識するか、まったく認識しない必要があります。アプリケーション・スレッドが密結合されていない場合は、疎結合となります。

動的登録と静的登録

Oracle Databaseは、動的登録と静的登録の両方をサポートします。動的登録の場合、RMは最初にアプリケーション・コールバックを実行します。静的登録の場合、関係のないRMがあっても、最初に、各RMに対してxa_startをコールする必要があります。

22.1.2 必須のパブリック情報

Oracle Databaseは、リソース・マネージャとして、表22-1に示す情報を発行する必要があります。

表22-1 Oracle Databaseが発行する必要のあるXA機能

XA機能 Oracle Databaseの詳細

xa_switch_t構造体

Oracle Databaseのxa_switch_t構造体名は、静的登録の場合はxaosw、動的登録の場合はxaoswdです。これらの構造体には、RMのエントリ・ポイントおよびその他の情報が含まれています。

xa_switch_tリソース・マネージャ

xa_switch_t構造体内のOracle Databaseのリソース・マネージャ名はOracle_XAです。

クローズ文字列

xa_closeで使用されるクローズ文字列は無視され、NULLとして扱われます。

オープン文字列

xa_openで使用されるオープン文字列の書式の詳細は、「xa_open文字列の定義」を参照してください。

ライブラリ

Oracle XAを使用するアプリケーションをリンクするために必要なライブラリには、プラットフォーム固有の名前が付けられています。TPM固有のライブラリをリンクする必要があることを除けば、通常のプリコンパイラまたはOCIプログラムをリンクする手順と同じです。

プリコンパイラ(Pro*C/C++、Pro*COBOLなど)を使用していない場合は、$ORACLE_HOME/rdbms/lib/xaonsl.oまたは$ORACLE_HOME/rdbms/lib32/xaonsl.o (64ビット・プラットフォーム上での32ビット・アプリケーションの場合)をリンクしてください。

要件

なし。XAをサポートする機能はStandard EditionおよびEnterprise Editionに含まれています。

22.2 Oracle XAライブラリ・サブプログラム

Oracle XAライブラリ・サブプログラムを使用することで、TMはトランザクションの処理方法をOracle Databaseに指示できます。一般に、TMはxa_openを使用してリソースをオープンする必要があります。通常、リソースはAPでtx_openをコールした結果としてオープンされます。一部のTMでは、アプリケーションが開始したときに、暗黙的にxa_openをコールします。

同様に、アプリケーションがリソースの使用を完了したときに発生するクローズがあります(xa_closeを使用)。このクローズが発生するのは、APがtx_closeをコールしたとき、またはアプリケーションが終了したときです。

TMはRMに対して、次のように他の複数のタスクを実行するように指示します。

  • トランザクションの開始、およびトランザクションに対するIDの対応付け

  • トランザクションのロールバック

  • トランザクションの準備およびコミット

トピック:

22.2.1 Oracle XAライブラリ・サブプログラム

表22-2に、XAライブラリ・サブプログラムを示します。

表22-2 XAライブラリ・サブプログラム

XAサブプログラム 説明:

xa_open

RMに接続します。

xa_close

RMとの接続を切断します。

xa_start

トランザクションを開始し、指定のトランザクションID(XID)に対応付けるか、またはプロセスと既存トランザクションを対応付けます。

xa_end

指定されたXIDからプロセスを切断します。

xa_rollback

指定されたXIDに対応付けられているトランザクションをロールバックします。

xa_prepare

指定されたXIDに対応付けられているトランザクションを準備します。これは、2フェーズ・コミット・プロトコルの第1のフェーズです。

xa_commit

指定されたXIDに対応付けられているトランザクションをコミットします。これは、2フェーズ・コミット・プロトコルの第2のフェーズです。

xa_recover

準備されたヒューリスティックにコミットまたはロールバックされたトランザクションのリストを取得します。

xa_forget

指定されたXIDに対応付けられているヒューリスティックに完了したトランザクションの情報を消去します。

一般に、APでは、xa_open文字列で実行されるロールを理解する以外に、表22-2に示したサブプログラムについて考慮する必要はありません。

22.2.2 Oracle XAインタフェース拡張機能

表22-3に示すように、Oracle DatabaseのXAインタフェースには、いくつかの関数が追加されています。

表22-3 Oracle XAインタフェース拡張機能

関数 説明:

OCISvcCtx *xaoSvcCtx(text *dbname)

指定されたXA接続のOCIサービス・ハンドルを戻します。dbnameパラメータは、xa_open文字列で渡されたDBパラメータと同じである必要があります。OCIアプリケーションでは、接続ハンドルを取得するために、sqlld2コールのかわりにこのルーティングを使用できます。このため、OCIアプリケーションはsqllibライブラリにリンクする必要はありません。サービス・ハンドルは、OCISvcCtxToLda(OCIバージョン8)を使用してOCIバージョン7のログイン・データ領域(LDA)に変換できます。クライアント・アプリケーションは、OCIコールを完了した後で、OCILdaToSvcCtxを使用してOracle7のLDAをサービス・ハンドルに変換する必要があります。

OCIEnv *xaoEnv(text *dbname)

指定されたXA接続のOCI環境ハンドルを戻します。dbnameパラメータは、xa_open文字列で渡されたDBパラメータと同じである必要があります。

int xaosterr(OCISvcCtx *SvcCtx,sb4 error)

Oracle Databaseエラー・コードをXAエラー・コードに変換します(動的登録にのみ適用可能)。最初のパラメータは、データベースで作業を実行するために使用するサービス・ハンドルです。2番目のパラメータは、Oracle Databaseから戻されるエラー・コードです。この関数は、OCI文から戻されたエラーがxa_startの違反によって発生したものかどうかを判断するために使用します。この関数は、エラーがXAモジュールによって生成されたものでない場合はXA_OKを戻し、エラーがXAモジュールによって生成されたものである場合は有効なXAエラーを戻します。

22.3 XAアプリケーションの開発およびインストール

この項では、Oracle XAライブラリの開発およびインストールについて説明します。

22.3.1 DBAまたはシステム管理者の責任

DBAまたはシステム管理者の責任は次のとおりです。

  1. アプリケーション開発者の支援によってオープン文字列を定義します。
  2. 静的データ・ディクショナリ・ビューDBA_PENDING_TRANSACTIONSが存在することを確認し、xa_open文字列で指定したすべてのOracleユーザーに対して、このビューのREADまたはSELECT権限を付与します。

    自分が作成したペンディング(インダウト)トランザクションをコミットまたはロールバックするOracleユーザーにFORCE TRANSACTION権限を付与します。権限の付与には、コマンドCOMMIT FORCE local_tran_idまたはROLLBACK FORCE local_tran_idを使用します。

    他のユーザーが作成したXAトランザクションをコミットまたはロールバックするOracleユーザーにFORCE ANY TRANSACTION権限を付与します。たとえば、ユーザーBが作成したトランザクションをユーザーAがコミットまたはロールバックする場合、ユーザーAにはFORCE ANY TRANSACTION権限が必要となります。

    Oracle Databaseリリース7のクライアント・アプリケーションの場合は、Oracle XAライブラリで使用されるすべてのOracle Databaseアカウントに対して、動的パフォーマンス・ビューV$XATRANS$SELECT権限を付与する必要があります。このビューは、XAライブラリのインストール時に作成されている必要があります。必要な場合は、Oracle DatabaseユーザーSYSとしてSQLスクリプトxaview.sqlを実行し、このビューを手動で作成できます。

  3. オープン文字列情報を使用して、RMをTPM構成にインストールします。TPMベンダーの指示に従ってください。

    DBAまたはシステム管理者は、Oracle Databaseに接続するプロセスをTPMシステムが開始することを認識する必要があります。TPMのマニュアルを参照して、このプロセスのためにどのような環境が存在するのか、ユーザーIDは何である必要があるかを判断してください。この環境で$ORACLE_HOMEおよび$ORACLE_SIDに正しい値が設定されていることを確認してください。

  4. XAトレース・ファイルが書き込まれるディレクトリに対する書込み許可を、そのユーザーIDに対して付与します。
  5. Oracle XAアプリケーションをオンラインにするために、適切なデータベース・インスタンスを起動します。このタスクは、TPMサーバーを開始する前に実行してください。

関連項目:

  • オープン文字列を定義する方法、およびデフォルトとは異なるOracleシステム識別子(SID)またはトレース・ディレクトリを指定する方法の詳細は、「xa_open文字列の定義」を参照してください。

  • catxpend.sqlスクリプトの位置は、使用中のプラットフォーム固有のOracle Databaseのマニュアルを参照してください。

22.3.2 アプリケーション開発者の責任

アプリケーション開発者の責任は次のとおりです。

  1. DBAまたはシステム管理者の支援によってオープン文字列を定義します。「xa_open文字列の定義」を参照してください。
  2. アプリケーションを開発します。

    プリコンパイラ用のトランザクション指向のSQL文に関する特別な制限事項を守ってください。

  3. TPMベンダーの指示に従ってアプリケーションをリンクします。

22.3.3 xa_open文字列の定義

オープン文字列は、トランザクション・モニターがデータベースをオープンするために使用します。オープン文字列内の最大文字数は256文字です。

トピック:

22.3.3.1 xa_open文字列の構文

例22-1に示す構文を使用してオープン文字列を定義できます。

次の文字列は、サンプル・パラメータ設定を示しています。

ORACLE_XA+DB=MANAGERS+SqlNet=SID1+ACC=P/username/password
  +SesTM=10+LogDir=/usr/local/xalog
ORACLE_XA+DB=PAYROLL+SqlNet=SID2+ACC=P/username/password
  +SesTM=10+LogDir=/usr/local/xalog
ORACLE_XA+SqlNet=SID3+ACC=P/username/password
  +SesTM=10+LogDir=/usr/local/xalog

次の各項では、required_fieldsおよびoptional_fieldsプレースホルダに有効なパラメータについて説明します。

ノート:

  • オープン文字列の作成時には、必須フィールドおよびオプションのフィールドをどのような順序でも入力できます。

  • すべてのフィールド名は大/小文字が区別されません。その値の大/小文字が区別されるかどうかは、プラットフォームによって異なります。

  • 実際の情報文字列の一部にプラス文字(+)を使用することはできません。

例22-1 xa_open文字列

ORACLE_XA{+required_fields...} [+optional_fields...]
22.3.3.2 xa_open文字列の必須フィールド

例22-1に示したrequired_fieldsプレースホルダは、表22-4に示す名前/値ペアのいずれかを指します。

表22-4 xa_open文字列の必須フィールド

構文要素 説明:

Acc=P//

ユーザーおよびパスワード情報が明示的には提供されないことと、オペレーティング・システム認証フォームが使用されることを指定します。

Acc=P/user/password

有効なOracle Databaseアカウントのユーザー名とパスワードを指定します。「DBAまたはシステム管理者の責任」で説明したとおり、HRにDBA_PENDING_TRANSACTIONS表のREADまたはSELECT権限があることを確認してください。

SesTm=session_time_limit

システムによりトランザクションが終了されるまでの、あるサービスから次のサービスまで、あるいはサービスからトランザクションのコミットまたはトランザクションまでの最大許容秒数を指定します。たとえば、SesTM=15は、セッション・アイドル時間の上限が15秒であることを示します。

たとえば、TPMでクライアントとサーバー間にリモート・サブプログラム・コールが使用されている場合は、SesTMは、あるRPCの完了から次のRPCの初期化の間、tx_commitまたはtx_rollbackとの間に適用されます。

値が0(ゼロ)の場合は、制限がないことを示します。値0(ゼロ)はできるだけ指定しないでください。問題があった場合に、リソースを長時間拘束することがあります。また、子プロセスにSesTM=0がある場合、親プロセスが終了した後は、SesTM設定の効果がなくなります。

関連項目:

管理者の認証の詳細は、『Oracle Database管理者ガイド』を参照してください。

22.3.3.3 xa_open文字列のオプション・フィールド

例22-1に示したoptional_fieldsプレースホルダは、表22-5に示す名前/値ペアのいずれかを指します。

表22-5 xa_open文字列のオプション・フィールド

構文要素 説明:

NoLocal= true | false

ローカル・トランザクションが許可されるかどうかを指定します。デフォルト値はfalseです。アプリケーションでローカル・トランザクションを禁止する必要がある場合は、値をtrueに設定します。

DB=db_name

Oracle Databaseプリコンパイラがデータベースの識別に使用する名前を指定します。たとえば、DB=payrollは、データベース名がpayrollであり、アプリケーション・サーバー・プログラムがこの名前をAT句で使用することを指定します。

Oracle Databaseプリコンパイラのデフォルトのデータベースのみを使用する(SQL文でAT句を使用しない)APでは、オープン文字列のDB=db_name句を省略する必要があります。明示的に指定したデータベースを使用するアプリケーションは、DB=db_nameフィールドにそのデータベース名を指定する必要があります。Oracle Databaseバージョン7のOCIプログラムでは、OCIサービス・コンテキストと等価のログイン・データ領域(Lda_Def)の正しいコンテキストを取得するために、sqlld2関数をコールする必要があります。バージョン8のOCIプログラムでは、xaoSvcCtx関数をコールして、OCISvcCtxサービス・コンテキストを取得する必要があります。

db_nameはSIDではありません。オープンするデータベースを検索するためには使用されません。このオープン文字列でオープンされたデータベースと、SQL文を実行するためにAPで使用される名前とを対応付けます。SIDは、TPMアプリケーション・サーバーのORACLE_SID環境変数か、オープン文字列のOracle Net句で指定したSIDから設定されます。Oracle Net句については、この項で後述します。一部のTPMベンダーは、同じオープン文字列を使用するサーバー・グループの名前を指定する方法を提供しています。グループ名とdb_nameの両方に対して同じ名前を選択する方が便利な場合があります。

LogDir=log_dir

Oracle XAライブラリのエラーとトレース情報が格納されるローカル・システム上のパス名を示します。デフォルトは、ORACLE_HOMEが設定されている場合は$ORACLE_HOME/rdbms/logで、それ以外の場合は現行のディレクトリを指定します。たとえば、LogDir=/xa_traceは、/xa_traceディレクトリにロギング情報があることを示しています。指定したディレクトリが存在し、アプリケーション・サーバーでそのディレクトリに確実に書き込めるようにしてください。

Objects= true | false

アプリケーションをオブジェクト・モードで初期化するかどうかを指定します。デフォルト値はfalseです。アプリケーションが、OCIRawAssignBytesなどのオブジェクト・モードを必要とする特定のAPIコールを使用する必要がある場合、trueを指定します。

MaxCur=maximum_#_of_open_cursors

データベースのオープン時に割り当てられるカーソルの数を指定します。これは、プリコンパイラ・オプションmaxopencursorsと同じ用途で機能します。たとえば、MaxCur=5は、プリコンパイラで5つのオープン・カーソルがキャッシュされることを示します。このパラメータは、ソース・コード内またはコンパイル時に指定したプリコンパイラ・オプションmaxopencursorsをオーバーライドします。

SqlNet=db_link

システムにログインするために使用するOracle Netデータベース・リンクを示します。この文字列は、tnsnames.oraのエントリである必要があります。たとえば、文字列SqlNet=inst1_dispの場合は、tnsnames.oraに定義されていれば、インスタンス1の共有サーバーに接続できます。

サーバー環境変数を制御できない場合は、SqlNetパラメータを使用してORACLE_SIDを指定できます。また、サーバーが複数のOracle Databaseインスタンスにアクセスする必要があるときにも、このパラメータを使用する必要があります。実際にリモート・データベースにアクセスせずにOracle Net文字列を使用するには、パイプ・ドライバを使用します。たとえば、SqlNet=localsid1と指定します。localsid1は、tnsnames.oraファイルで定義されている別名です。

Loose_Coupling=true | false

ロックが共有されるかどうかを示します。同じグローバル・トランザクション内の複数のOracle Databaseトランザクション・ブランチには、密結合または疎結合のどちらの方法も使用できます。ブランチが疎結合の場合は、ロックを共有できません。疎結合ブランチの場合は、値をtrueに設定します。ブランチが密結合の場合は、ロックを共有できます。密結合ブランチの場合は、値をfalseに設定します。デフォルト値はfalseです。

ノート: Oracle RACの実行時に、トランザクション・ブランチが別のOracle RACインスタンスにある場合は、Loose_Coupling=falseであってもこれらは疎結合です。

SesWt=session_wait_limit

XA_RETRYが戻される前にOracle Databaseが別のセッションに使用されているトランザクション・ブランチを待機する秒数を示します。デフォルト値は60秒です。

Threads=true | false

アプリケーションがマルチスレッドかどうかを指定します。デフォルト値はfalseです。アプリケーションがマルチスレッドである場合、設定はtrueです。

FAN=true | false

アプリケーションで高速アプリケーション通知(FAN)を使用するかどうかを指定します。デフォルト値はfalseです。アプリケーションでFANを使用する場合、設定はtrueです。

関連項目:

FANの詳細は、『Oracle Database管理者ガイド』を参照してください。

22.3.4 プリコンパイラでのOracle XAの使用

カーソルは、Oracle XAアプリケーションで使用する場合はトランザクションの存続期間のみ有効です。明示的カーソルは、トランザクションが開始した後にオープンし、コミットまたはロールバックの前にクローズする必要があります。

プリコンパイラとのインタフェースでは、次の2つのオプションがあります。

22.3.4.1 デフォルトのデータベースでのプリコンパイラの使用

デフォルトのデータベースでプリコンパイラにインタフェースするには、オープン文字列で使用されるDB=db_nameフィールドが存在しないことを確認してください。このフィールドが存在しない場合は、デフォルトの接続が指定されます。プロセスごとに1つのデフォルト接続のみが使用できます。

次に、デフォルトのPro*C/C++接続を識別するオープン文字列の例を示します。

ORACLE_XA+SqlNet=maildb+ACC=P/username/password
  +SesTM=10+LogDir=/usr/local/logs

DB=db_nameが存在せず、空のデータベースID文字列であることを示しています。

SQL文の構文は次のようになります。

EXEC SQL UPDATE Emp_tab SET Sal = Sal*1.5;
22.3.4.2 指定されたデータベースでのプリコンパイラの使用

指定されたデータベースでプリコンパイラにインタフェースするには、オープン文字列にDB=db_nameフィールドを含めます。参照するすべてのデータベースは、対応するオープン文字列で指定した同一のdb_nameを参照する必要があります。

アプリケーションには、デフォルト・データベースの他に、名前を指定されたデータベースが1つ以上含まれることがあります。たとえば、あるデータベースで従業員の給与を更新し、別のデータベースでその従業員の部門番号(DEPTNO)を、第3のデータベースでその従業員の管理者を更新するとします。トランザクション・マネージャに例22-2のようなオープン文字列を構成します。

例22-2 オープン文字列構成のサンプル

ORACLE_XA+DB=MANAGERS+SqlNet=SID1+ACC=P/username/password
  +SesTM=10+LogDir=/usr/local/xalog
ORACLE_XA+DB=PAYROLL+SqlNet=SID2+ACC=P/username/password
  +SesTM=10+LogDir=/usr/local/xalog
ORACLE_XA+SqlNet=SID3+ACC=P/username/password
  +SesTM=10+LogDir=/usr/local/xalog

例22-2の最後のオープン文字列にDB=db_nameフィールドはありません。

アプリケーション・サーバー・プログラムでは、次のような宣言を入力します。

EXEC SQL DECLARE PAYROLL DATABASE;
EXEC SQL DECLARE MANAGERS DATABASE;

ここでも、デフォルトの接続(DBフィールドを含まない3番目のオープン文字列に対応)には宣言は必要ありません。

更新を実行するときは、次に示すような文を入力します。

EXEC SQL AT PAYROLL UPDATE Emp_Tab SET Sal=4500 WHERE Empno=7788;
EXEC SQL AT MANAGERS UPDATE Emp_Tab SET Mgr=7566 WHERE Empno=7788;
EXEC SQL UPDATE Emp_Tab SET Deptno=30 WHERE Empno=7788;

最後の文は、デフォルトのデータベースを参照しているためAT句はありません。

Oracle Databaseプリコンパイラのリリース1.5.3以上では、次に示す例のように、AT句に文字ホスト変数を使用できます。

EXEC SQL BEGIN DECLARE SECTION;
  DB_NAME1 CHARACTER(10);
  DB_NAME2 CHARACTER(10);
EXEC SQL END DECLARE SECTION;
    ...
SET DB_NAME1 = 'PAYROLL'
SET DB_NAME2 = 'MANAGERS'
    ...
EXEC SQL AT :DB_NAME1 UPDATE...
EXEC SQL AT :DB_NAME2 UPDATE...

注意:

XAアプリケーションでは、xa_openを介して作成された以外の接続を作成しないでください。XA以外の接続で実行されるすべての作業は、グローバル・トランザクションの範囲から外れることになり、個別にコミットする必要があります。

22.3.5 OCIでのOracle XAの使用

Oracle XAライブラリを使用するOracle Call Interfaceアプリケーションでは、リソース・マネージャにログインするためにOCISessionBeginをコールしないでください。ログインは、TPMを介して行うようにしてください。そのようなアプリケーションでは、関数xaoSvcCtxを実行して、リソース・マネージャへのアクセスに必要なサービス・コンテキスト構造体を取得できます。

環境ハンドルをOCI関数に渡す必要があるアプリケーションでは、そのハンドルを検索するためにxaoEnvもコールする必要があります。

アプリケーション・サーバーでは同時に複数のOracle Databaseのリソース・マネージャをオープンできるため、適切なサービス・コンテキストを取得するためには適切な引数を使用して関数xaoSvcCtxをコールする必要があります。

22.3.6 Oracle XAを使用したトランザクション制御の管理

XAライブラリを使用する場合、トランザクションは、トランザクションをコミットまたはロールバックするSQL文によっては制御されません。制御は、トランザクションを開始および終了するTMに受け入れられるAPIによって行われます。表22-2に示したXAライブラリ・サブプログラムではなく、表22-6に示したTXインタフェースなど、トランザクション・マネージャにより提供されるAPIをコールします。

TMは、通常、XAインタフェースを介してトランザクションを制御します。このインタフェースには、表22-2に示す関数が含まれています。

表22-6 TXインタフェース関数

TX関数 説明:

tx_open

リソース・マネージャにログインします。

tx_close

リソース・マネージャからログアウトします。

tx_begin

トランザクションを開始します。

tx_commit

トランザクションをコミットします。

tx_rollback

トランザクションをロールバックします。

ほとんどのTPMアプリケーションは、アプリケーション・クライアントがサービスを要求し、アプリケーション・サーバーがサービスを提供するというクライアント/サーバー・アーキテクチャを使用しています。プリコンパイラ・アプリケーションの例に示す例では、そのようなクライアント/サーバー・モデルを使用しています。サービスとは論理作業単位であり、Oracle DatabaseがRMである場合は、関連する作業単位を実行する一連のSQL文で構成されます。

たとえば、「貸方記入」というサービスが口座番号および貸方記入額を受け取ると、このサービスは、データベース内の特定の表にある情報を更新するSQL文を実行します。また、サービスはその他のサービスを要求することもあります。たとえば、「振替」サービスの場合は、「貸方記入」および「借方記入」にサービスを要求します。

通常、アプリケーション・クライアントは、トランザクション内で作業を実行するためにアプリケーション・サーバーにサービスを要求します。ただし、一部のTPMシステムでは、アプリケーション・クライアント自身がローカルにサービスを提供できます。プリコンパイラ・アプリケーションの例に示すとおり、トランザクション制御文は、クライアントまたはサーバーのどちらの側でも記述できます。

複数のプロセスを同一のトランザクションに参加させるために、TPMは参加プロセス間でトランザクション情報が伝達できる通信APIを提供しています。通信APIの例として、RPC、疑似RPC関数、送信/受信関数があります。

主要ベンダーが異なる通信関数をサポートしているため、次の例では、通信APIを汎用化するために通信疑似関数tpm_serviceを使用しています。

X/Openの準備段階の仕様には、通信関数を提供する代替方法がいくつか取り入れられています。主要TPMベンダーでは、これらの代替方法を1つ以上はサポートしています。

22.3.7 プリコンパイラ・アプリケーションの例

次の例は、プリコンパイラ・アプリケーションを示しています。アプリケーション・サーバーがTPM固有の方法でRMシステムにログインしているとします。例22-3に、アプリケーション・サーバーによって開始されるトランザクションを示します。

例22-3 アプリケーション・サーバーによって開始されるトランザクション

/***** Client: *****/
tpm_service("ServiceName");              /*Request Service*/

/***** Server: *****/
ServiceName()
{
  <get service specific data>
  tx_begin();                             /* Begin transaction boundary */
  EXEC SQL UPDATE ...;

  /* This application server temporarily becomes */
  /* a client and requests another service. */

  tpm_service("AnotherService");
  tx_commit();                             /* Commit the transaction */
  <return service status back to the client>
}

例22-4に、アプリケーション・クライアントによって開始されるトランザクションを示します。

例22-4 アプリケーション・クライアントによって開始されるトランザクション

/***** Client: *****/
tx_begin();                            /* Begin transaction boundary */
tpm_service("Service1");
tpm_service("Service2");
tx_commit();                           /* Commit the transaction */

/***** Server: *****/
Service1()
{
  <get service specific data>
  EXEC SQL UPDATE ...;
  <return service status back to the client>
}
Service2()
{
  <get service specific data>
  EXEC SQL UPDATE ...;
  ...
  <return service status back to client>
}

22.3.8 プリコンパイラまたはOCIアプリケーションのTPMアプリケーションへの移行

既存のプリコンパイラまたはOCIアプリケーションを、Oracle XAライブラリを使用するTPMアプリケーションに移行するには、次の手順に従います。

  1. アプリケーション・クライアントがアプリケーション・サーバーにサービスを要求できるように、アプリケーションを「サービス」のフレームワークに再編成します。TPMには、アプリケーションでtx_open関数およびtx_close関数を使用するように要求するTPMと、ログインおよびログオフを暗黙的に実行するTPMがあります。

    オープン文字列にSqlNetパラメータを指定しないと、アプリケーションはデフォルトのOracle Netドライバを使用します。このため、ORACLE_HOMEおよびORACLE_SID環境変数を正しく定義して、アプリケーション・サーバーを立ち上げる必要があります。これは、TPMに固有の方法で行われます。これを行う方法の詳細は、TPMベンダーのマニュアルを参照してください。

  2. アプリケーションで正規の接続文および切断文を置き換えます。たとえば、接続文EXEC SQL CONNECT(プリコンパイラの場合)またはOCISessionBeginOCIServerAttachおよびOCIEnvCreate(OCIの場合)をtx_openで置き換えます。切断文EXEC SQL COMMIT/ROLLBACK WORK RELEASE(プリコンパイラの場合)またはOCISessionEnd/OCIServerDetach(OCIの場合)をtx_closeで置き換えます。
  3. アプリケーションで、グローバル・トランザクションの正規のコミット文またはロールバック文を置き換え、トランザクションを明示的に開始します。

    たとえば、tx_commit/tx_rollbackによってCOMMIT/ROLLBACK文のEXEC SQL COMMIT/ROLLBACK WORK(プリコンパイラの場合)またはOCITransCommit/OCITransRollback(OCIの場合)を置き換え、tx_beginをコールすることによってトランザクションを開始します。

    ノート:

    前述の例は、ローカル・トランザクションではなくグローバル・トランザクションにのみ該当します。ローカル・トランザクションは、Oracle APIでコミットまたはロールバックする必要があります。

  4. アプリケーションで、トランザクションを終了する前にフェッチ状態をリセットします。一般的には、release_cursor=noを使用します。release_cursor=yesは、文が1回しか実行されないことが確実なときにのみ使用します。

表22-7に、プリコンパイラまたはOCIアプリケーションをTPMアプリケーションに移行するときに、正規のOracle Database文を置き換えるTPM関数を示します。

表22-7 TPM用に置き換える文

正規のOracle Database文 TPM関数

CONNECTuser/password

tx_open(暗黙の可能性あり)

トランザクションの暗黙的な開始

tx_begin

SQL

SQLを実行するサービス

COMMIT

tx_commit

ROLLBACK

tx_rollback

切断

tx_close(暗黙の可能性あり)

22.3.9 Oracle XAライブラリ・スレッド・セーフティの管理

スレッドをサポートするトランザクション・モニターを使用する場合は、Oracle XAライブラリを使用してスレッド・セーフなアプリケーションを作成できます。ただし、注意が必要な問題がいくつかあります。

制御のスレッド(またはスレッド)とは、リソース・マネージャへの一連の接続のことです。スレッド化されていないシステムでは、各プロセスは制御のスレッドとみなされます。これは、各プロセスにはRMへの接続がそれぞれ独自にあり、それぞれが独立したRM表をメンテナンスしているためです。スレッド化されているシステムでは、各スレッドにはRMとの自律型接続があり、プライベートなRM表をメンテナンスします。このプライベートな表はスレッドのそれぞれに対して割り当てる必要があり、またスレッドが終了したときは(異常終了であっても)割当てを解除する必要があります。

ノート:

Oracle Databaseでは、データベースにアクセスする各スレッドに独自の接続が必要です。

トピック:

22.3.9.1 オープン文字列でのスレッドの指定

xa_open文字列では、Threads=句が指定されます。TMでスレッドを使用できるようにするには、この句をtrueに指定する必要があります。デフォルトは、falseです。ほとんどの場合、スレッドはTMによって作成され、アプリケーションはスレッドがいつ作成されたのか認識しません。このため、サービス・コンテキストは、TMアプリケーション用に作成される各サービス内のスタック上に割り当てることをお薦めします。そのサービス内でOracle Database関連のコールを実行する前に、xaoSvcCtx関数をコールして初期化済のOCIサービス・コンテキストを取得する必要があります。このコンテキストをサービス内でOCIコールに使用できます。

22.3.9.2 Oracle XAのスレッドにおける制限事項

スレッドを使用するときは、次の制限事項が適用されます。

  • アプリケーション・スレッドがそれぞれいつ開始されるかが明示的にトランザクション・モニターに通知されないかぎり、トランザクション・モニター上でアプリケーション・サーバー・プロセスの一部として実行されるPro*またはOCIコードをスレッド化することはできません。通常、これは、TMベンダーが提供する特別なCコンパイラを使用して実現されます。

  • Pro*文EXEC SQL ALLOCATEおよびEXEC SQL USEはサポートされません。このため、スレッド化が使用可能であるときは、埋込みSQL文を非XA接続にまたがって使用することはできません。

  • プロセスの1つのスレッドがXAを介してOracle Databaseに接続した場合、そのプロセスの他のすべてのスレッドもXAを介してOracle Databaseに接続する必要があります。1つのスレッドでEXEC SQL CONNECTを介して接続し、他のスレッドでxa_openを介して接続することはできません。

22.3.10 DBMS_XAパッケージの使用

PL/SQLアプリケーションは、DBMS_XAパッケージとともにOracle XAライブラリを使用できます。

例22-5では、1つ目のPL/SQLセッションがトランザクションを開始しますがコミットせず、2つ目のセッションがトランザクションを再開し、3つ目のセッションがコミットします。3つのセッションはすべてHRスキーマに接続されます。

例22-5 DBMS_XAパッケージの使用

REM Session 1 starts a transaction and does some work.
DECLARE
  rc  PLS_INTEGER;
  oer PLS_INTEGER;
  xae EXCEPTION;
BEGIN
  rc  := DBMS_XA.XA_START(DBMS_XA_XID(123), DBMS_XA.TMNOFLAGS);

  IF rc!=DBMS_XA.XA_OK THEN
    oer := DBMS_XA.XA_GETLASTOER();
    DBMS_OUTPUT.PUT_LINE('ORA-' || oer || ' occurred, XA_START failed');
    RAISE xae;
  ELSE DBMS_OUTPUT.PUT_LINE('XA_START(new xid=123)     OK');
  END IF;

  UPDATE employees SET salary=salary*1.1 WHERE employee_id = 100;
  rc  := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUSPEND);

  IF rc!=DBMS_XA.XA_OK THEN
    oer := DBMS_XA.XA_GETLASTOER();
    DBMS_OUTPUT.PUT_LINE('ORA-' || oer || ' occurred, XA_END failed');
    RAISE xae;
  ELSE DBMS_OUTPUT.PUT_LINE('XA_END(suspend xid=123)   OK');
  END IF;

  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE
       ('XA error('||rc||') occurred, rolling back the transaction ...');
      rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUCCESS);
      rc := DBMS_XA.XA_ROLLBACK(DBMS_XA_XID(123));

      IF rc != DBMS_XA.XA_OK THEN
        oer := DBMS_XA.XA_GETLASTOER();
        DBMS_OUTPUT.PUT_LINE('XA-'||rc||', ORA-' || oer ||
         ' XA_ROLLBACK does not return XA_OK');
        raise_application_error(-20001, 'ORA-'||oer||
         ' error in rolling back a failed transaction');
      END IF;

      raise_application_error(-20002, 'ORA-'||oer||
       ' error in transaction processing, transaction rolled back');
END;
/
SHOW ERRORS
DISCONNECT

REM Session 2 resumes the transaction and does some work.
DECLARE
  rc  PLS_INTEGER;
  oer PLS_INTEGER;
  s   NUMBER;
  xae EXCEPTION;
BEGIN
  rc  := DBMS_XA.XA_START(DBMS_XA_XID(123), DBMS_XA.TMRESUME);

  IF rc!=DBMS_XA.XA_OK THEN
    oer := DBMS_XA.XA_GETLASTOER();
    DBMS_OUTPUT.PUT_LINE('ORA-' || oer || ' occurred, xa_start failed');
    RAISE xae;
  ELSE DBMS_OUTPUT.PUT_LINE('XA_START(resume xid=123)  OK');
  END IF;

  SELECT salary INTO s FROM employees WHERE employee_id = 100;
  DBMS_OUTPUT.PUT_LINE('employee_id = 100, salary = ' || s);
  rc  := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUCCESS);

  IF rc!=DBMS_XA.XA_OK THEN
    oer := DBMS_XA.XA_GETLASTOER();
    DBMS_OUTPUT.PUT_LINE('ORA-' || oer || ' occurred, XA_END failed');
    RAISE xae;
  ELSE DBMS_OUTPUT.PUT_LINE('XA_END(detach xid=123)    OK');
  END IF;

  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE
       ('XA error('||rc||') occurred, rolling back the transaction ...');
      rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUCCESS);
      rc := DBMS_XA.XA_ROLLBACK(DBMS_XA_XID(123));

      IF rc != DBMS_XA.XA_OK THEN
        oer := DBMS_XA.XA_GETLASTOER();
        DBMS_OUTPUT.PUT_LINE('XA-'||rc||', ORA-' || oer ||
         ' XA_ROLLBACK does not return XA_OK');
        raise_application_error(-20001, 'ORA-'||oer||
         ' error in rolling back a failed transaction');
      END IF;

      raise_application_error(-20002, 'ORA-'||oer||
       ' error in transaction processing, transaction rolled back');
END;
/
SHOW ERRORS
DISCONNECT

REM Session 3 commits the transaction.
DECLARE
  rc  PLS_INTEGER;
  oer PLS_INTEGER;
  xae EXCEPTION;
BEGIN
  rc  := DBMS_XA.XA_COMMIT(DBMS_XA_XID(123), TRUE);

  IF rc!=DBMS_XA.XA_OK THEN
    oer := DBMS_XA.XA_GETLASTOER();
    DBMS_OUTPUT.PUT_LINE('ORA-' || oer || ' occurred, XA_COMMIT failed');
    RAISE xae;
  ELSE DBMS_OUTPUT.PUT_LINE('XA_COMMIT(commit xid=123)  OK');
  END IF;

  EXCEPTION
    WHEN xae THEN
      DBMS_OUTPUT.PUT_LINE
       ('XA error('||rc||') occurred, rolling back the transaction ...');
      rc := DBMS_XA.XA_ROLLBACK(DBMS_XA_XID(123));

      IF rc != DBMS_XA.XA_OK THEN
        oer := DBMS_XA.XA_GETLASTOER();
        DBMS_OUTPUT.PUT_LINE('XA-'||rc||', ORA-' || oer ||
         ' XA_ROLLBACK does not return XA_OK');
        raise_application_error(-20001, 'ORA-'||oer||
         ' error in rolling back a failed transaction');
      END IF;

      raise_application_error(-20002, 'ORA-'||oer||
       ' error in transaction processing, transaction rolled back');
END;
/
SHOW ERRORS
DISCONNECT
QUIT

関連項目:

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

22.4 XAアプリケーションのトラブルシューティング

トピック:

22.4.1 Oracle XAトレース・ファイルへのアクセス

Oracle XAライブラリでは、すべてのエラーおよびトレース情報がトレース・ファイルに記録されます。この情報は、XAエラー・コードを補足するときに役立ちます。たとえばxa_open障害が発生したとき、その原因として、オープン文字列が正しくなかったか、Oracle Databaseインスタンスの検索が正常に実行されなかったか、またはログイン認可が正常に実行されなかったかを示します。

トレース・ファイル名はxa_db_namedate.trcです。db_nameはオープン文字列のフィールドDB=db_nameで指定したデータベース名で、dateは情報がトレース・ファイルに記録された日付です。オープン文字列でDB=db_nameを指定しない場合、自動的にデフォルトでNULLになります。

たとえば、xa_NULL06022005.trcは、2005年6月2日に作成されたトレース・ファイルを示しています。リソース・マネージャがオープンされたときに、DBフィールドがオープン文字列に指定されていませんでした。ファイル名xa_Finance12152004.trcは、2004年12月15日に作成されたトレース・ファイルを示しています。リソース・マネージャがオープンされたときに、DBフィールドはオープン文字列で「Finance」と指定されていました。

ノート:

オープン文字列に同一のDBフィールドおよびLogDirフィールドを持つ複数のOracle XAライブラリRMは、同じ日に発生したすべてのトレース情報を同じトレース・ファイルに記録します。

トレース・ファイルに次の内容が含まれているとします。

1032.12345.2:  ORA-01017:  invalid username/password;  logon denied
1032.12345.2:  xaolgn:  XAER_INVAL;  logon denied

表22-8に、各要素の意味を示します。

表22-8 サンプル・トレース・ファイルの内容

文字列 説明:

1032

情報が記録された時刻。

12345

プロセスID(PID)。

2

リソース・マネージャID

xaolgn

モジュール名

XAER_INVAL

XA標準での指定に従って戻されたエラー

ORA-01017

戻されたOracle Database情報

トピック:

22.4.1.1 xa_open文字列DbgFl

通常、XAトレース・ファイルはエラーが検出された場合にのみオープンされます。xa_open文字列DbgFlは、XAライブラリに関する詳細を記録するトレース機能を提供します。デフォルト値は0(ゼロ)です。次の組合せのいずれかに設定できます。

  • 0x1: XAインタフェース内の各サブプログラムの入口および出口をトレースできます。この値は、TPモニターがどのXAコールを作成し、どのトランザクション識別子を生成しているかを正確に調べるときに役立ちます。

  • 0x2: 他の非公開XAライブラリ・プログラムへの入口および出口をトレースできます。通常、これはOracle Database開発者用の機能です。

  • 0x4: OCIに対する専用コールのように、XAライブラリが作成する他の様々な関心のあるコールをトレースできます。通常、これはOracle Database開発者用の機能です。

ノート:

各フラグはub4の独立ビットであるため、複数のフラグから出力を取得するには、フラグの値の組合せを設定する必要があります。

22.4.1.2 トレース・ファイルの位置

XAアプリケーションでは、トレース・ファイルの位置が次のアルゴリズムに従って判別されます。

  1. オープン文字列で指定されているLogDirディレクトリ。

  2. オープン文字列にLogDirを指定しないと、Oracle XAアプリケーションは(Oracleホームがアクセス可能な場合は)次のディレクトリにトレース・ファイルを作成しようとします。

    • %ORACLE_HOME%\rdbms\trace(Windowsの場合)

    • $ORACLE_HOME/rdbms/log(LinuxおよびUNIXの場合)

  3. Oracle XAアプリケーションでは、Oracleホームの位置を判別できない場合、トレース・ファイルは現在の作業ディレクトリに作成されます。

22.4.2 インダウトまたはペンディングのOracle XAトランザクションの管理

インダウト・トランザクションまたはペンディング・トランザクションとは、準備はできているがデータベースに対してコミットされていないトランザクションです。一般的に、TPMシステムが提供するTMは、インダウト・トランザクションまたはペンディング・トランザクションの障害を解決し、リカバリします。次の状況では、DBAがインダウト・トランザクションをオーバーライドする必要がある場合があります。

  • 他のトランザクションが必要とするデータをロックしている場合。

  • 適切な時間の経過後も解決されない場合。

前述のような状況でインダウト・トランザクションをオーバーライドする方法の詳細、およびインダウト・トランザクションをコミットまたはロールバックするかどうかを決定する方法の詳細は、TPMのマニュアルを参照してください。

22.4.3 SYSアカウント表を使用したOracle XAトランザクションの監視

Oracle DatabaseのSYSアカウントには次のビューがあり、正規のOracle DatabaseアプリケーションおよびOracle XAアプリケーションによって生成されたトランザクションが含まれています。

  • DBA_PENDING_TRANSACTIONS

  • V$GLOBAL_TRANSACTION

  • DBA_2PC_PENDING

  • DBA_2PC_NEIGHBORS

Oracle XAアプリケーションによって生成されたトランザクションの場合は、次に示す列情報がDBA_2PC_NEIGHBORS表に適用されます。

  • DBID列は常にxa_orcl

  • DBUSER_OWNER列は常にdb_namexa.oracle.com

db_nameは、オープン文字列で常にDB=db_nameと指定されることに注意してください。オープン文字列にこのフィールドを指定しないと、この列の値はOracle XAアプリケーションが生成するトランザクションについてはNULLxa.oracle.comになります。

たとえば、次のSQL文を使用すると、Oracle XAアプリケーションによって生成されたインダウト・トランザクションの詳細情報を取得できます。

SELECT * 
FROM DBA_2PC_PENDING p, DBA_2PC_NEIGHBORS n
WHERE p.LOCAL_TRAN_ID = n.LOCAL_TRAN_ID
AND n.DBID = 'xa_orcl';

別の方法として、トランザクション処理モニターが使用するフォーマットIDがわかっている場合は、DBA_PENDING_TRANSACTIONSまたはV$GLOBAL_TRANSACTIONを使用できます。DBA_PENDING_TRANSACTIONSでは準備済トランザクションの両方のリストが提供されますが、V$GLOBAL_TRANSACTIONSでは、すべてのアクティブなグローバル・トランザクションのリストが提供されます。

22.5 Oracle XAの問題および制限事項

トピック:

22.5.1 Oracle XAアプリケーションでのデータベース・リンクの使用

Oracle XAアプリケーションは、次の制限事項に違反しないかぎり、データベース・リンク経由で他のOracle Databaseインスタンスにアクセスできます。

  • 共有サーバー構成を使用する必要があります。

    トランザクション処理モニター(TPM)は、共有サーバーを使用してOracle Database Aへの接続をオープンします。データベース・リンクに必要なオペレーティング・システム・ネットワーク接続は、専用サーバー・プロセスではなくディスパッチャによってオープンされます。このため、様々なサービスやスレッドでトランザクションを操作できます。

    この制限事項が満たされていない場合、XAトランザクション内でデータベース・リンクを使用すると、専用サーバー・プロセスと他方のOracle Database Bの間にオペレーティング・システム・ネットワーク接続が作成されます。このネットワーク接続は専用サーバー・プロセス間で移動できないため、データベースAのこの専用サーバー・プロセスから連結解除することはできません。データベース・リンクを介してデータベースBにアクセスするときに、ORA-24777エラーが戻されます。

  • アクセスする他のデータベースは、別のOracle Databaseである必要があります。

この制限事項が満たされている場合、Oracle Databaseはデータベース・リンクを許可し、トランザクション・プロトコルを他のOracle Databaseインスタンスに伝播(準備、ロールバックおよびコミット)します。

共有サーバー構成を使用できない場合は、リモート・データベースにEXEC SQL AT構文を使用してPro*C/C++アプリケーション経由でアクセスします。

init.oraパラメータOPEN_LINKS_PER_INSTANCEは、移行可能なオープン・データベース・リンク接続の数を指定します。これらのdblink接続は、トランザクションのコミット後に接続をキャッシュできるように、XAトランザクションによって使用されます。接続を作成したユーザーがトランザクションも作成した場合、別のトランザクションがデータ・リンク接続を使用できます。このパラメータは、1つのセッションにおけるリモート・データベースへの同時オープン接続の最大数(データベース・リンクを含む)を指定するinit.oraパラメータOPEN_LINKSとは異なります。OPEN_LINKSパラメータは、XAアプリケーションには適用できません。

22.5.2 Oracle XAアプリケーションでのトランザクション・ブランチの管理

同じグローバル・トランザクション内の複数のOracle Databaseトランザクション・ブランチには、密結合または疎結合のどちらの方法も使用できます。トランザクション・ブランチが密結合の場合は、ロックを共有できます。そのため、あるトランザクション・ブランチでのCOMMIT前更新は、同じグローバル・トランザクションに属する他のブランチで参照可能です。疎結合トランザクション・ブランチの場合、ブランチはロックを共有せず、他のブランチでの更新を認識しません。

密結合ブランチの場合、Oracle Databaseは文を実行する前にDXロックを取得します。システムが文の実行前にロックを取得しないため、疎結合トランザクション・ブランチの同時実行性が増します。デメリットは、すべてのトランザクション・ブランチが2フェーズ・コミットを実行する必要があることです。XAの1フェーズ最適化は使用できません。

表22-9に、密結合ブランチと疎結合ブランチのトレードオフを示します。

表22-9 密結合および疎結合トランザクション・ブランチ

属性 密結合ブランチ 疎結合ブランチ

2フェーズ・コミット

読取り専用最適化

[全ブランチについて準備、最後のブランチについてコミット]

2フェーズ

[全ブランチについて準備およびコミット]

シリアライズ

データベース・コール

なし

22.5.3 Oracle Real Application Clusters(Oracle RAC)でのOracle XAの使用

Oracle Database 11gリリース1(11.1)では、XAトランザクションは複数のOracle RACインスタンスにまたがって、XAを使用するすべてのアプリケーションでOracle RAC環境を活用し、アプリケーションの可用性とスケーラビリティを拡張できるようになりました。

ノート:

分散トランザクションと組み合せた外部プロシージャ・コールアウトはサポートされません。

トピック:

22.5.3.1 GLOBAL_TXN_PROCESSES初期化パラメータ

初期化パラメータGLOBAL_TXN_PROCESSESは、各Oracle RACインスタンスのGTXnバックグラウンド・プロセス数を指定します。デフォルト値は1です。

分散トランザクションが複数のOracle RACインスタンスにまたがる場合、このパラメータはクラスタ全体でデフォルト値のままとします。これにより、Oracle RACインスタンス全体にわたって実行される作業単位は、リソースを共有し、単一のトランザクションとして機能します(つまり、作業単位は密結合となります)。また、クラスタ内の任意のノードへの2フェーズ・コミット要求の送信も可能となります。

関連項目:

GLOBAL_TXN_PROCESSESの詳細は、『Oracle Databaseリファレンス』を参照してください。

22.5.3.2 Oracle RACでのトランザクション・ブランチの管理

ノート:

このトピックは、次のいずれかが当てはまる場合に適用されます。

  • 初期化パラメータGLOBAL_TXN_PROCESSESはすべてのOracle RACインスタンスの初期化ファイルのデフォルト値でない。

  • Oracle XAアプリケーションが以前に連結解除されたトランザクションのブランチを再開または結合する。

Oracle Databaseでは、様々なインスタンスがOracle RACの異なるトランザクション・ブランチで操作できます。たとえば、ノード1がブランチAで操作し、ノード2がブランチBで操作できます。Oracle Database 11gリリース1(11.1)より前は、トランザクション・ブランチが異なるインスタンスにある場合は疎結合であり、ロックを共有しませんでした。この場合、Oracle Databaseでは、様々なアプリケーション・スレッドの異なる作業単位が、リソースを共有しない個別エンティティとして処理されました。

また、複数のインスタンスが1つのトランザクション・ブランチで操作する場合もあります。たとえば、次のように1つのトランザクションがノード1およびノード2にあるとします。

ノード1

  1. xa_start

  2. SQL操作

  3. xa_end (SUSPEND)

ノード2

  1. xa_start (RESUME)

  2. xa_prepare

  3. xa_commit

  4. xa_end

直前の順序では、ノード2は物理的に異なるノード(ノード1)にあるブランチを再開しないため、Oracle Databaseではエラーが戻されます。

Oracle Database 11gリリース1 (11.1)より前のリリースでは、Oracle RACで密結合を実現する方法として分散トランザクション処理(DTP)サービス、つまりカーディナリティ(1)によって、ロード・バランシングが有効かどうかに関係なくすべての密結合ブランチが確実に同じインスタンスに配置されるサービスを使用していました。中間層コンポーネントは、常に1つのOracle RACインスタンスにマップする共通の論理データベース・サービス名を使用して、Oracle Databaseをアドレス指定しました。データベース・インスタンスの物理特性は、データベース・サービスの中間名リゾルバによって隠されました。DTPサービスを使用すると、密結合グローバル・トランザクションの参加者はすべて1つのインスタンス上でブランチを作成できました。

Oracle Database 11gリリース1 (11.1)では、密結合ブランチでのXAトランザクションのサポートにDTPサービスは不要になりました。デフォルトでは、異なるOracle RACインスタンスにある密結合ブランチは密結合のままとなります。つまり、Oracle RACインスタンス全体でロックとリソースを共有します。

たとえば、DTPサービスを使用すると、次の一連のアクションが同じインスタンス上で発生します。

  1. xa_start
  2. SQL操作
  3. xa_end (SUSPEND)
  4. xa_start (RESUME)
  5. SQL操作
  6. xa_prepare
  7. xa_commitまたはxa_rollback

さらに、それぞれが同じDTPサービスでOracle RMをアドレス指定する場合は、複数の密結合ブランチが同じインスタンスにあります。

クラスタのインスタンスをすべて活用するには、分散トランザクションを管理する各ノードに1つ以上、複数のDTPサービスを作成します。グローバル分散トランザクションのブランチは、すべて同じインスタンスに存在します。そのため、Oracle RACクラスタのすべてのインスタンスおよびノードを利用して多数の分散XAトランザクションのロード・バランシングを実行し、アプリケーションのスループットを最大化できます。

関連項目:

Real Application Clusters構成で分散トランザクションを管理する方法を学習するには、『Oracle Real Application Clusters管理およびデプロイメント・ガイド』を参照してください。

22.5.3.3 Oracle RACでのDTPサービス(10.2)を使用したインスタンス・リカバリの管理

Oracle Database 10gリリース2(10.2)より前は、Oracle RACでの障害検出とフェイルオーバーおよびフェイルバックのトリガーはTMで実行されていました。インダウト・トランザクションに関する情報をDBA_2PC_PENDINGに確実に伝播させるために、TMではインダウト・トランザクションの解決に進む前にxa_recoverを起動する必要がありました。インスタンスに障害が発生した場合、XAクライアント・ライブラリはSYS.DBMS_XA.DIST_TXN_SYNCプロシージャを実行して障害を起こしたインスタンスのUNDOセグメントがリカバリされたことを確認するまで、他のインスタンスにフェイルオーバーできませんでした。Oracle Database 10gリリース2(10.2)では、処理中のトランザクションに関する十分な情報がTMにあれば、このようにxa_recoverを起動するという要件はありません。

ノート:

Oracle Database 9gリリース2(9.2)以降のリリースでは、xa_recoverはリモート・サイトで分散データ操作言語(DML)が完了するまで待機する必要があります。

Oracle RACでDTPサービスを使用すると、次のようなメリットがあります。

  • インスタンス障害の検出が自動化されます。

  • インスタンスのフェイルオーバーとフェイルバックが自動化されます。インスタンスに障害が発生すると、このインスタンスで管理されているDTPサービスが他のインスタンスにフェイルオーバーします。このフェイルオーバーにより、クライアントは強制的に再接続されますが、サービスの論理名は変わりません。フェイルオーバーは自動的で、管理者が介入する必要はありません。管理者は、サービス再配置文を使用してフェイルバックを実行できますが、フェイルバック関連のリカバリはすべてデータベース・サーバー内で自動的に処理されます。

  • クライアントではなくOracle Databaseがインスタンスのリカバリを実行できます。データベースでは、中間層TMの関与を必要とせずに、他のインスタンスによって準備されたトランザクションの状態を判別できます。

関連項目:

22.5.3.4 Oracle RACのXIDのグローバル一意性

Oracle Database 11gリリース1(11.1)より前のリリースでは、Oracle RACデータベースでは指定されたXIDがクラスタ内のXAトランザクションで一意であるかどうかは判断できません。

たとえば、Oracle RACインスタンス1にXID Fmt(x).Tx(1).Br(1)、Oracle RACインスタンス2に別のXID Fmt(x).Tx(1).Br(1)があるとします。XIDがOracle RACインスタンス間で一意ではありませんが、どちらもブランチを開始してSQLを実行できます。

Oracle Database 11gリリース1 (11.1)では、Oracle RACデータベースはOracle RACインスタンス間の重複するXIDを検出し、重複したXIDを持つブランチが開始しないようにしています。

関連項目:

Oracle RACでのサービスおよび分散トランザクション処理の詳細は、『Oracle Real Application Clusters管理およびデプロイメント・ガイド』を参照してください。

22.5.3.5 密結合と疎結合

同じグローバル・トランザクション内の複数のOracle Databaseトランザクション・ブランチには、密結合または疎結合のどちらかを使用できます。通常、結合のタイプはxa_open文字列のLoose_Couplingフィールドで定義します(詳細は、表22-5を参照してください)。ただし、Oracle RACの実行時に、トランザクション・ブランチが別のOracle RACインスタンスにある場合は、Loose_Coupling=falseであってもこれらは疎結合です。

関連項目:

22.5.4 SQLに基づくOracle XAの制限事項

この項では、次のSQL操作に関する制限事項について説明します。

22.5.4.1 ロールバックおよびコミット

グローバル・トランザクションの進行状況の調整および監視はトランザクション・マネージャが行うため、グローバル・トランザクションのロールバックまたはコミットを独立して行うOracle Database固有の文をアプリケーションに入れないでください。ただし、ローカル・トランザクションではロールバックおよびコミットを使用できます。

グローバル・トランザクションの途中で、プリコンパイラ・アプリケーションにEXEC SQL ROLLBACK WORKを使用しないでください。同様に、OCIアプリケーションでは、OCITransRollbackまたはバージョン7で同等のorolを実行しないでください。グローバル・トランザクションをロールバックするには、tx_rollbackをコールします。

同様に、グローバル・トランザクションの途中で、プリコンパイラ・アプリケーションにEXEC SQL COMMIT WORK文を使用しないでください。OCIアプリケーションでは、OCITransCommitまたはバージョン7で同等のocomを実行しないでください。たとえば、tx_commitまたはtx_rollbackを使用して、グローバル・トランザクションを終了してください。

22.5.4.2 DDL文

CREATE TABLEなどのデータ定義言語(DDL)文は、暗黙的なコミットを意味するためOracle XAアプリケーションでは実行できません。

22.5.4.3 セッション状態

Oracle Databaseでは、セッション状態が複数のTPMサービス間で有効であることを保証しません。たとえば、あるTPMサービスがセッション変数(グローバル・パッケージ変数など)を更新した場合、同じグローバル・トランザクションの一部として実行している別のTPMサービスにはこの変更が認識されないことがあります。セーブポイントは1つのTPMサービス内で使用してください。アプリケーションが、別のTPMサービスで作成されたセーブポイントを参照しないようにしてください。同様に、アプリケーションが、別のTPMサービスで実行されたカーソルからフェッチしないようにしてください。

22.5.4.4 EXEC SQL

接続および切断にEXEC SQL文を使用しないでください。つまり、EXEC SQL CONNECTEXEC SQL COMMIT WORK RELEASEまたはEXEC SQL ROLLBACK WORK RELEASEを使用しないでください。

22.5.5 その他の制限事項

  • Oracle XAとゲートウェイの両方を同じセッションで使用できません。

  • Oracle Databaseでは、関連付けの移行はサポートされません(関連付けの移行とは、トランザクション・マネージャが中断中のブランチ関連付けを別のブランチで再開する手段です)。

  • XAのオプションの機能である非同期XAコールはサポートされません。

  • TRANSACTIONS初期化パラメータを、グローバル・トランザクションの同時実行予測数に設定します。初期化パラメータOPEN_LINKS_PER_INSTANCEは、移行可能なオープン・データベース・リンク接続の数を指定します。これらのデータベース・リンク接続は、トランザクションのコミット後に接続をキャッシュできるように、XAトランザクションによって使用されます。

  • スレッドごとのxa_openコールの最大数は32です。

  • TPモニター・ベースのXAアプリケーションを構築する場合、リンク・ラインで、TPモニター・ライブラリ(ax_regおよびax_unreg記号を定義する)をOracle Databaseクライアント共有ライブラリの前に指定する必要があります。プラットフォームで共有ライブラリがサポートされていない場合、またはリンカーがリンク・ライン内のライブラリの順序を区別しない場合は、Oracle Databaseの非共有クライアント・ライブラリを使用します。これらのリンク制限は、XAの動的登録(Oracle XAスイッチxaoswd)を使用する場合のみ適用できます。