最も単純なトランザクションモードから始めて、複雑さを増していきましょう。
トランザクションなし
「トランザクションなし」の接続とは、電子メールの送信などのデータを「コミット」または「ロールバック」しない接続です。メッセージオブジェクトを電子メールサーバーに渡すと、それは受信者に送信され、どんなに訴えてもメッセージが再び返されることはありません。それは、呼び出しが戻るまでにすべての呼び出しがコミットされたかのようです。この種の接続の例には、SMTP、SMSゲートウェイ、プリンターなどへの接続が含まれます。
自動コミットがオンになっている場合は、この方法でデータベース接続を使用できると思いますが、そもそも完全なACIDデータベースがある理由について疑問が生じます...
「通常の」トランザクション
たとえばSQLデータベースへの通常の接続には、一連の状態変更コマンドを内部バッファに格納する機能があります。すべてが完了し、すべてが正常に見えると、変更のバッファ全体がデータストアに書き込まれ、他の接続が変更を確認できます。コミット前またはコミット中に問題が発生した場合は、変更のセット全体を破棄(ロールバック)できます。
このタイプの接続の重要な制限の1つは、バッファーのスコープです。バッファーは接続自体の一部です。つまり、バッファに書き込むことができるのは接続を介してのみです。
アプリケーションサーバーの重要な責任は、これらの接続を管理することです。接続プールに接続を提供するように要求すると、(単一のトランザクション内で)毎回魔法のように同じ接続を取得します。これは、あるEJBが別のEJBを呼び出す場合、またはEJBがリソースアダプタを呼び出す場合にも当てはまります(REQUIRES_TRANSACTIONセマンティクスを使用していると仮定します。これはREQUIRES_NEWでオーバーライドできます)。この動作は、1つのWeb要求が複数のEJB呼び出しを実行でき、それぞれが複数のエンティティBeanと対話でき、すべてのデータ操作が単一の内部バッファを使用した単一の接続で実行されることを意味します。すべてがコミットまたはロールバックされます。
複数の接続を持つトランザクション
これは、単一のデータベースがある場合に最適ですが、(たとえば、異なるマシン上で)別々のデータベースインスタンスと通信する場合は、(定義上)別々の接続が必要です。では、どうなるのでしょうか。EJBトランザクションは、最終的に複数の接続(一意のデータベースへの各接続)に関連付けられます。これは、次の1つの状況を除いて、うまく機能しているように見えます。
- データベースAへの接続AとデータベースBへの接続Bがあります
- AとBでDMLステートメントを実行します
- EJB接続をコミットします。アプリケーションサーバーは次のようになります。
- 接続Aをコミットします-成功
- 接続Bをコミットします-失敗し(たとえば、制約が失敗します)、接続Bがロールバックします
これは災害です。データベースAでトランザクションをコミットしましたが、これをロールバックすることはできません。ただし、トランザクション(およびEJB全体)はデータベースBでロールバックされます。
(興味深いことに、あなたの例はこれとほとんど同じです-トランザクションなしと通常のトランザクションにコミットされたデータがありますが、XAトランザクションにはコミットされていません-3つの接続の最後です)
XAトランザクション
そこでXAが登場します。これは、さまざまなデータソースに対してコミットされているトランザクションを調整するロジックを提供し、複数のデータソースにわたる単一のトランザクションをシミュレートします。XAは、XAトランザクションに採用された多数のXA接続を管理するトランザクションコーディネーターによって管理される「2フェーズコミット」でコミットします。コーディネーター
- XA接続を介して各データソースにメッセージを送信し、トランザクションをコミットできるかどうかを確認します。すべての制約とデータベースロジックは、最終コミットの直前まで実行されます。いずれかのデータベースが障害を報告した場合、XAコーディネーターはトランザクション全体をロールバックします。フェーズ1では、ほとんどすべてのトランザクション作業が実行されるため、比較的時間がかかります
- すべてのデータベースがトランザクションをコミットできることを報告すると、コーディネーターはトランザクションをコミットするためにすべてのデータベースにメッセージを送信します。これは非常に速く起こります。
フェーズ2で問題が発生した場合(たとえば、ネットワークの一部がクラッシュしたり、フェーズ1とフェーズ2の間にデータベースの1つがパワーオフされたりした場合)、2フェーズコミットが失敗する可能性があることに注意してください。
XA接続は通常の接続とは非常に異なる動作をするため、通常、非XAConnectionFactoryとは異なるオブジェクトインスタンスをインスタンス化する異なるConnectionFactoryオブジェクトが必要です。さらに、XA ConnectionFactoryには、通常のトランザクションプロパティに加えて、XAトランザクションタイムアウトなどのXAトランザクションコーディネーターの構成パラメーターが必要です。
別の制約:XA ConnectionFactoryによって作成された接続のみが、XAトランザクションおよび関連する2フェーズコミットに参加できます。XA接続と非XA接続の両方を単一のApplicationServerトランザクションに参加させることはできますが、トランザクション全体を単一のトランザクションとして確実にコミット/ロールバックすることはできません(上記のとおり)。
具体的な回答
トランザクションが一時的に失敗した場合、すべてのテーブルからすべてのデータをロールバックすることになっているのか、それともXAサービスのデータのみをロールバックすることになっているのかを知りたいのですが。
アプリケーションサーバーがコミットを試行する前にトランザクションが失敗した場合(たとえば、EJBがNPEを取得したり、意図的にロールバックしたりした場合)、各接続はロールバックを受け取り、すべてが期待どおりになるはずです。
ただし、トランザクションがコミットロジックで失敗した場合(データベースの制約など)、トランザクションマネージャーはすべてをロールバックしようとします。非XA接続がすでにコミットされている場合、これは発生しません。
私も知りたいと思いました。私が知っている「トランザクション」は、データをアトミックに転送する手順です。では、接続の作成に、接続によって実行できるトランザクションのタイプの定義が含まれるのはなぜですか?それはトランザクションのプロパティではありませんか?
XA接続自体は、XAトランザクションコーディネーターと通信する必要があるため、XA接続は通常の接続とは異なるライブラリとプロトコルを使用します。通常の接続ではこれは行われません。
また、接続プロパティでトランザクションタイプを定義する必要がある理由を知りたいのですが、トランザクションを開始するときにトランザクションのタイプを定義する必要があり、トランザクションマネージャーは特定のタイプのトランザクションを実行する必要があります。
XA接続は異なるコードを使用するため、接続プールは通常の接続と比較して異なるクラスをロードする必要があります。これが、接続プール(接続ではない)のプロパティが異なる理由です。