S2.2.9 リリース

変更内容

  • S2DBCP
    • JTA トランザクションが開始される前にコネクションプールから取得したコネクションを JTA トランザクション中にクローズした場合にコネクションプールに戻されない問題を修正しました (イレギュラーな使い方での問題です).
    • JTA トランザクション中に setAutoCommit(true),commit(),rollback(),setSavePoint() が呼び出された場合に SQLException をスローするように修正しました (「JDBC3.0 Specification」の Chapter 12 「Distributed Transactions」に準拠しました).
  • S2JTA
    • jta.jarjta-1_0_1B-classes.zip をリネームしたものに置換しました.
    • 複数のリソースマネージャ (RDBMS 等) が JTA トランザクションに参加している場合の 2PC における準備 (prepare) フェーズで,あるリソースマネージャが例外をスローした場合に後続のリソースマネージャがロールバックされない問題を修正しました.
    • 複数のリソースマネージャ (RDBMS 等) が JTA トランザクションに参加している場合の 2PC における準備 (prepare) フェーズで,最後のリソースマネージャに対しては (2 フェーズではなく) 1 フェーズコミットを行う Last Resource Commit Optimization を実装しました.1 フェーズ コミットするリソースは JTA トランザクションで最初に登録されたされたリソース (通常は最初に取得されたコネクションの接続先 DB) になります.

Last Resource Commit Optimization について

複数のリソースマネージャ (RDBMS 等) が参加した分散トランザクションにおいては,2 フェーズコミットが使用されます.
2フェーズコミットは最初に全てのリソースマネージャに「prepare (準備)」が指示されます.リソースマネージャはトランザクションが確実にコミットできるように整合性制約の違反がないかチェックしたりログへの書き込みを行ったりして肯定の応答をします.
全てのリソースマネージャが prepare に対して肯定の応答を返した場合には,全てのリソースマネージャにトランザクションの commit が指示されます.
もし prepare に対して否定の応答をしたリソースマネージャが一つでもあれば,全てのリソースマネージャに rollback が指示されます.
このように 2 段階の手順を経てトランザクションをコミットするのが 2 フェーズコミットです.
(簡略化して書いてます)


例えば 3 つのリソースマネージャ DB1,DB2,DB3 があったとすると,

  • DB1 prepare → OK
  • DB2 prepare → OK
  • DB3 prepare → OK
  • DB1 commit(2PC)
  • DB2 commit(2PC)
  • DB3 commit(2PC)

ということになります.
「commit(2PC)」は 2 フェーズコミットにおける prepare の後の commit を示します.一方,1 フェーズで行われる通常のコミットを「commit(1PC)」と表記します.


Last Resource Commit Optimization は,このように複数のリソースがある場合に,最後のリソースに対しては prepare ではなく,通常の 1 フェーズコミットを指示するというものです.上の例では

  • DB1 prepare → OK
  • DB2 prepare → OK
  • DB3 commit(1PC)
  • DB1 commit(2PC)
  • DB2 commit(2PC)

ということになります.
もし DB3 が commit(1pc) に失敗 (rollback) した場合は,prepare に否定の応答をした場合と同様に扱われます.すなわち,DB1 と DB2 は rollback されます.
リソースマネージャに対して prepare と commit(2PC) という 2 回の指示をするよりも commit(1PC) を1回だけ指示する方が効率的 (DBMS 等の処理としても効率的な場合が多いらしい) であるため,Last Resource Commit Optimization と呼ばれます.


S2JTA の実装では,JTA トランザクションに最初に参加したリソースマネージャを 1PC の対象とします.これは通常,トランザクション中で最初に取得されたコネクションの接続先 DB です.実際には,prepare フェーズは JTA トランザクションに参加した順番とは逆順に行われ,最後に残ったりソースマネージャ (最初に参加したりソースマネージャ) が commit(1PC) されます.上の例では

  • DB3 prepare → OK
  • DB2 prepare → OK
  • DB1 commit(1PC)
  • DB2 commit(2PC)
  • DB3 commit(2PC)

ということになります.


Last Resource Commit Optimization のメリットは効率だけではなく,本来 XA に対応していないリソースマネージャでも安全に分散トランザクションに参加することができるようになります.
例えば XA に対応した Oracle (Oracle が提供する XADataSource を使用する) と対応していない HSQLDB (S2 が提供する XADataSource で XA をエミュレートする) を同一のトランザクション中で更新する場合,最初に HSQLDB からコネクションを取得することで,二つの DB がどちらもコミットされるかどちらもロールバックされるかという原子性 (ACID の A) が実現できます.