×
  • Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
 

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

on

  • 127 views

 

Statistics

Views

Total Views
127
Views on SlideShare
123
Embed Views
4

Actions

Likes
0
Downloads
0
Comments
0

1 Embed 4

https://twitter.com 5

Accessibility

Categories

Upload Details

Uploaded via SlideShare as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
Post Comment
Edit your comment

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

    • そんなトランザクション マネージャで大丈夫か? @takezoen BizReach,Inc.
    • JTA、使っていますよね? ● JavaEEサーバ ● Seasar2 ● Spring Framework
    • トランザクションマネージャの役割 ● 複数のリソースを1つのトランザクションで処理 する ● トランザクションに参加するリソースの整合性を 保証する
    • たとえば... ● 複数のDBに対する処理 ● DBに対する処理とJMSによるメッセージ送信 DB DB プログラム DB MQ プログラム 参照・更新 メッセージ 送信・受信参照・更新 参照・更新 1トランザクションで処理する
    • 以下のどちらかであることを保証する ● すべてのリソースがコミットされる ● すべてのリソースがロールバックされる
    • どうやって保証しているのか?
    • 2フェーズコミット リソース1 リソース2 トランザクション マネージャ プログラム commit prepare? commit prepare? commit
    • 2フェーズコミット ● 全てのリソースがprepareに対してOKを返した 場合のみcommitする ● どれか1つでもprepareに対してNGを返した場 合は全てのリソースをrollbackする
    • 2フェーズコミット ● XADataSourceが必要 ● XADataSourceの実装はJDBCドライバによっ て提供される ● 非XAリソースをラップしてエミュレーションする 機能を持っている場合もある
    • 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)
    • 様々な最適化 ● リソースが1つの場合は1フェーズでcommitする ● 最後のリソースはprepareせずにcommitする ● 非XAリソースでも1つだけならJTAトランザク ションに参加可能
    • めでたしめでたし
    • ちょっと待った!!
    • ここからが本題です
    • 途中で落ちたらどうなるの?
    • 不整合が発生してしまう ● リソース側にトランザクションが残ってしまう ● 一部のリソースだけがコミットされた状態になっ てしまう
    • リカバリマネージャ ● トランザクションマネージャはトランザクションの 状態をトランザクションログに出力している ● リカバリマネージャはトランザクションログを見て 不正なトランザクションを自動的にリカバリする
    • リカバリマネージャ トランザクション マネージャ リカバリ マネージャ トランザクションログ トランザクション の状態を書き込み 残ってしまっている トランザクションがないか 定期的にチェック 残ってしまっている トランザクションを検出した 場合はリカバリを実行 誤検出しないよう、トランザクションマネー ジャの管理下になく、かつ一定時間ステー タスが変わっていないもの、というような チェックを行っている
    • トランザクションのリカバリとは? ● リソース側に残っているトランザクションを rollbackまたはcommitのどちらかに倒す ● 基本的には安全サイド(rollback)に倒す ● すでに1つでもリソースをcommitしてしまってい る場合は全部commitする
    • どこで落ちたかでリカバリ方法が異なる リソース1 リソース2 トランザクション マネージャ プログラム commit prepare? commit prepare? commit ここで落ちた場合は両方 rollbackする ここで落ちた場合はリソー ス2をcommitする
    • リカバリマネージャがあれば安心
    • リカバリマネージャがあれば安心 ではありません
    • リカバリマネージャではリカバリ できないケースがあります
    • トランザクションログが壊れた場合ヽ(‘ ∇‘ )ノ ● リソースに対する操作を行ってからトランザク ションログを書き込み前に死んだ場合 ● トランザクションログのファイル書き込み中に死 んだ場合
    • リソース側に残ってしまった トランザクションを手動でcommitまたは rollbackする必要があります
    • 手動リカバリ(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トランザクショ ンが消えた
    • めでたしめでたし
    • ちょっと待った!!
    • Seasar2やSpringを使っている場合
    • Seasar2 ● トランザクションログを書いていない ● もちろん自動リカバリ機能もない
    • 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の動作をエミュレートするもの。
    • 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>
    • Spring Framework ● 自前ではJTA対応のトランザクションマネージャ の実装は持っていない ● JTA対応のトランザクションマネージャをSpring 上で使用するためのアダプタが用意されている ● 2フェーズコミットを使用するにはJavaEEサーバ もしくはスタンドアロンのJTA実装と組み合わせ て使用する必要がある
    • 2フェーズコミットを行う場合は APサーバのトランザクションマネージャを 使ったほうが安全です
    • まとめ
    • まとめ ● 2フェーズコミットを行う場合、手動でのリカバリが必要にな るケースが存在するということを意識しておきましょう ● 2フェーズコミットを行う場合はなるべくJavaEEサーバのトラ ンザクションマネージャを使うことをおすすめします ● そもそも2フェーズコミットを行わなくても済むのであればそ のほうがよいです ● 分散トランザクションはさらに危険がいっぱいなので近づか ないようにしましょうw
    • おわり