Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

そんなトランザクションマネージャで大丈夫か?

19,074 views

Published on

Published in: Software
  • Be the first to comment

そんなトランザクションマネージャで大丈夫か?

  1. 1. そんなトランザクション マネージャで大丈夫か? @takezoen BizReach,Inc.
  2. 2. JTA、使っていますよね? ● JavaEEサーバ ● Seasar2 ● Spring Framework
  3. 3. トランザクションマネージャの役割 ● 複数のリソースを1つのトランザクションで処理 する ● トランザクションに参加するリソースの整合性を 保証する
  4. 4. たとえば... ● 複数のDBに対する処理 ● DBに対する処理とJMSによるメッセージ送信 DB DB プログラム DB MQ プログラム 参照・更新 メッセージ 送信・受信参照・更新 参照・更新 1トランザクションで処理する
  5. 5. 以下のどちらかであることを保証する ● すべてのリソースがコミットされる ● すべてのリソースがロールバックされる
  6. 6. どうやって保証しているのか?
  7. 7. 2フェーズコミット リソース1 リソース2 トランザクション マネージャ プログラム commit prepare? commit prepare? commit
  8. 8. 2フェーズコミット ● 全てのリソースがprepareに対してOKを返した 場合のみcommitする ● どれか1つでもprepareに対してNGを返した場 合は全てのリソースをrollbackする
  9. 9. 2フェーズコミット ● XADataSourceが必要 ● XADataSourceの実装はJDBCドライバによっ て提供される ● 非XAリソースをラップしてエミュレーションする 機能を持っている場合もある
  10. 10. XAトランザクションのSQL(MySQLの場合) mysql> XA START 'xatest'; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO account VALUES(1, 'takezoe'); Query OK, 1 row affected (0.04 sec) mysql> XA END 'xatest'; Query OK, 0 rows affected (0.00 sec) mysql> XA PREPARE 'xatest'; Query OK, 0 rows affected (0.00 sec) mysql> XA COMMIT 'xatest'; Query OK, 0 rows affected (0.00 sec)
  11. 11. 様々な最適化 ● リソースが1つの場合は1フェーズでcommitする ● 最後のリソースはprepareせずにcommitする ● 非XAリソースでも1つだけならJTAトランザク ションに参加可能
  12. 12. めでたしめでたし
  13. 13. ちょっと待った!!
  14. 14. ここからが本題です
  15. 15. 途中で落ちたらどうなるの?
  16. 16. 不整合が発生してしまう ● リソース側にトランザクションが残ってしまう ● 一部のリソースだけがコミットされた状態になっ てしまう
  17. 17. リカバリマネージャ ● トランザクションマネージャはトランザクションの 状態をトランザクションログに出力している ● リカバリマネージャはトランザクションログを見て 不正なトランザクションを自動的にリカバリする
  18. 18. リカバリマネージャ トランザクション マネージャ リカバリ マネージャ トランザクションログ トランザクション の状態を書き込み 残ってしまっている トランザクションがないか 定期的にチェック 残ってしまっている トランザクションを検出した 場合はリカバリを実行 誤検出しないよう、トランザクションマネー ジャの管理下になく、かつ一定時間ステー タスが変わっていないもの、というような チェックを行っている
  19. 19. トランザクションのリカバリとは? ● リソース側に残っているトランザクションを rollbackまたはcommitのどちらかに倒す ● 基本的には安全サイド(rollback)に倒す ● すでに1つでもリソースをcommitしてしまってい る場合は全部commitする
  20. 20. どこで落ちたかでリカバリ方法が異なる リソース1 リソース2 トランザクション マネージャ プログラム commit prepare? commit prepare? commit ここで落ちた場合は両方 rollbackする ここで落ちた場合はリソー ス2をcommitする
  21. 21. リカバリマネージャがあれば安心
  22. 22. リカバリマネージャがあれば安心 ではありません
  23. 23. リカバリマネージャではリカバリ できないケースがあります
  24. 24. トランザクションログが壊れた場合ヽ(‘ ∇‘ )ノ ● リソースに対する操作を行ってからトランザク ションログを書き込み前に死んだ場合 ● トランザクションログのファイル書き込み中に死 んだ場合
  25. 25. リソース側に残ってしまった トランザクションを手動でcommitまたは rollbackする必要があります
  26. 26. 手動リカバリ(MySQLの場合) mysql> XA RECOVER; +----------+--------------+--------------+--------+ | formatID | gtrid_length | bqual_length | data | +----------+--------------+--------------+--------+ | 1 | 6 | 0 | xatest | +----------+--------------+--------------+--------+ 1 row in set (0.00 sec) mysql> XA ROLLBACK 'xatest'; Query OK, 0 rows affected (0.00 sec) mysql> XA RECOVER; Empty set (0.00 sec) XAトランザクションが残ってしまって いる 他のリソースの状態をトランザクショ ンIDで突き合せてcommitするべき かrollbackするべきか判断し、トラン ザクションをリカバリする 残ってしまっていたXAトランザクショ ンが消えた
  27. 27. めでたしめでたし
  28. 28. ちょっと待った!!
  29. 29. Seasar2やSpringを使っている場合
  30. 30. Seasar2 ● トランザクションログを書いていない ● もちろん自動リカバリ機能もない
  31. 31. Seasar2 ● なんちゃってXADataSource <component name="xaDataSource" class="org.seasar.extension.dbcp.impl.XADataSourceImpl"> <property name="driverClassName">"oracle.jdbc.driver.OracleDriver"</property> <property name="URL">"jdbc:oracle:thin:@xxx:1521:yyy"</property> <property name="user">"aaa"</property> <property name="password">"bbb"</property> </component> Seasar2のサンプルなどにはこういった設定例が紹介されているが、これは Seasar2側で用意しているXADataSourceのなんちゃって実装で、通常の java. sql.ConnectionをラップしてXAの動作をエミュレートするもの。
  32. 32. Seasar2 ● 2フェーズコミットを行うのであればJDBCドライバが提供し ているXADataSourceの実装を使うべき ○ com.mysql.jdbc.jdbc2.optional.MysqlXADataSource ○ org.postgresql.xa.PGXADataSource <component name="xaDataSource" class="org.postgresql.xa.PGXADataSource"> <property name="serverName">"localhost"</property> <property name="databaseName">"TEST"</property> <property name="user">"xxxx"</property> <property name="password">"xxxx"</property> </component>
  33. 33. Spring Framework ● 自前ではJTA対応のトランザクションマネージャ の実装は持っていない ● JTA対応のトランザクションマネージャをSpring 上で使用するためのアダプタが用意されている ● 2フェーズコミットを使用するにはJavaEEサーバ もしくはスタンドアロンのJTA実装と組み合わせ て使用する必要がある
  34. 34. 2フェーズコミットを行う場合は APサーバのトランザクションマネージャを 使ったほうが安全です
  35. 35. まとめ
  36. 36. まとめ ● 2フェーズコミットを行う場合、手動でのリカバリが必要にな るケースが存在するということを意識しておきましょう ● 2フェーズコミットを行う場合はなるべくJavaEEサーバのトラ ンザクションマネージャを使うことをおすすめします ● そもそも2フェーズコミットを行わなくても済むのであればそ のほうがよいです ● 分散トランザクションはさらに危険がいっぱいなので近づか ないようにしましょうw
  37. 37. おわり

×