第3章 リソースマネージャ

3.1. XAResource インターフェース

トランザクションの仕様やシステムのうち一般的なリソースを定義するものもあり、任意のリソースとトランザクションを登録するのに利用できます。JTA は、はるかにXA 固有のものとなっています。javax.transaction.xa.XAResourceインターフェースは、 XA インターフェースのJava マッピングで、拡散トランザクションの処理環境にてResource Manager (リソースマネージャ)Transaction Manager (トランザクションマネージャ)の間のコントラクトを定義します。リソースアダプタは、XAResource インターフェースを実装し、トップレベルのトランザクションをリソースに紐付けるサポートをします。関係データベースは、このようなリソースの一例となっています。
外部のトランザクションマネージャがトランザクションを制御する環境にて利用するためのトランザクショナルなリソースアダプタにより、XAResource インターフェースに対応可能です。アプリケーションは複数のデータベース接続を介してデータにアクセスすることができます。各データベースの接続は、基盤のリソースマネージャインスタンスに対するプロキシオブジェクトとして機能するXAResource オブジェクトと紐付いています。また、トランザクションマネージャは、トップレベルトランザクションに参加するリソースマネージャごとにXAResource を取得します。startおよびend メソッドはリソースとトランザクションを紐付けし、紐付けを解除します。
リソースマネージャは、startendの呼出しのいずれかをデータに対して行う全作業とトランザクションを関連付けます。トランザクションのコミット時に、トランザクションマネージャはこれらのトランザクショナルなリソースマネージャに対し、2相コミットプロトコルに従いトランザクションを準備、コミットあるいはロールバックするよう指示を出します。
Java とより良く統合するために、XAResource は標準のXA インターフェースと以下の点で異なります。
  • リソースマネージャの初期化は、接続取得時にリソースアダプタにより暗黙的に実行されます。xa_openと同等となるものはありません。
  • Rmid は、引数として渡されず、Rmid はそれぞれ、別々のXAResource オブジェクトにより表現されます。
  • Java がマルチスレッド処理に対応しており、データベースの多くが非同期操作に対応していないため、非同期操作は対応していません。
  • トランザクションマネージャによりXAResource オブジェクトを正しく処理されない場合に出されるエラーの戻り値は、XAException クラスによりJava の例外にマッピングされます。
  • Thread of Control におけるDTP の概念では、 XAResourceConnection オブジェクトへのアクセスを全Java スレッドへマッピングします。例えば、2つの別スレッドは、同じ XAResource オブジェクト上でstartend 操作を実行できます。

3.1.1. XAResource 制御の継承

デフォルトでは、XAResource オブジェクトがJTA準拠のトランザクションサービスに登録されると常に、XAResource オブジェクトについて、2相コミットプロトコルの間に呼び出される順番の制御はできません。しかし、JBoss Transaction Service はcom.arjuna.ats.jta.resources.StartXAResourcecom.arjuna.ats.jta.resources.EndXAResourceのインターフェース2つの順番を制御するようサポートしています。これらのインターフェースからのXAResource インスタンスを継承することで、ご利用中のクラスインスタンスがコミットプロトコルの最初、あるいは最後のどちらに呼び出すかを管理します。

注記

特定のトランザクションに登録できるのは、各インターフェースの種類でインスタンス1つのみとなっています。
最終リソースコミット最適化 (LRCO: Last Resource Commit Optimization)は、1 相のみ対応する単一のリソース(prepare のサポートなし)を 2 相対応の参加者を操作するトランザクションへ参加させることができ、JBossTS は LRCO に対応しています。
LRCO機能を利用するため、XAResource 実装をcom.arjuna.ats.jta.resources.LastResourceCommitOptimisationマーカーインターフェースに拡張する必要があります。Transaction.enlistResourceを介してリソースを登録する際、JBoss Transaction Service があるとLastResourceCommitOptimisation 参加者のみがそれぞれのトランザクション内で利用できるようにします。コミットプロトコールの最後にご利用中のリソースが駆動され、prepare メソッドの呼出しはされません。

注記

デフォルトでは、LastResourceCommitOptimisation クラスのインスタンスを複数参加させようとすると失敗し、falseTransaction.enlistResourceから返されます。com.arjuna.ats.jta.allowMultipleLastResources プロパティをtrueに設定することでこの動作をオーバーライドすることができます。詳細については、必ず1相対応リソースの複数登録に関する項を参照するようにしてください。
拡散環境でLRCOを利用するには、介入サポートを無効にする必要があります。ただし、暗黙的なコンテキスト伝播を利用することはできます。

3.1.2. 1 相対応リソースの複数参加

同一トランザクション内にある複数の参加者 (リソース)間で結果の一貫性 (アトミック性) を保つため、永続トランザクションログとともに2相コミットプロトコルを使います。前述した通り、1相対応リソースを処理する際、LRCO を利用するとリソース間でアトミックな結果 (all or nothing) を実現することができます。
しかし、同一のトランザクション内に複数の1相対応リソースを登録している場合もあるでしょう。例えば、同一のトランザクション内でレガシーのデータベースをレガシーのJMS 実装として実行している場合などです。このような場合、いずれのリソースもprepareステートに入らないため、複数のリソース間でトランザクションの結果においてアトミック性を獲得することができません。他のリソースステートを認識せず、後続のリソースが異なる選択をした場合でもそれを取り消す方法なしに、トランザクションのコーディネータが指示を出すとすぐにコミットあるいはロールバックします。そのため、データの破損やヒューリスティックな結果が発生することがあります。
このような場合、以下のいずれかの方法を採ってください:
  • 補正トランザクションのリソースをラップ
  • レガシー実装を2相対応と同等なものに移行
これらのオプションが実行できない場合、JBoss Transaction Service では、LRCO を使うことで複数の1相対応リソースを同一のトランザクション内に参加させることができます。LRCO については本項にて前述しています。

重要

LRCO サポートが有効になっていても、JBoss Transaction Service はこのサポートを検出すると警告を出します。このログメッセージは、"You have chosen to enable multiple last resources in the transaction manager. This is transactionally unsafe and should not be relied upon.”か、あるいは、このトランザクションに1相対応リソースが複数登録されている場合は“This is transactionally unsafe and should not be relied on.”となります。