[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
SlideShare a Scribd company logo
そんなトランザクション
マネージャで大丈夫か?
@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
おわり

More Related Content

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