- - PR -
OracleJDBC使用時のトランザクションの原子性の実現について
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-02-17 23:33
SQLException に対するエラー処理を catch や finally でおこなう際に、リソースを解放するために Connection#close をしたくなりますが、その際にいっしょに Connection#rollback をしないと、コミットされても文句を言えないのかなあ、とも思います。 すなわち close するなら rollback もかならずしないと JDBC Driver の実装依存になってしまうとも考えますが、どうでしょうか。(また close さえしなければリソースは解放されないかもしれませんが、コミットされることはない、とも考えます。) ちなみに、 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=10297&forum=12 では、Statement と ResultSet についての話ですが、Connection とは扱いが違うのかどうかなどはちょっと分かりませんでした。 | ||||||||||||
|
投稿日時: 2008-02-18 00:18
ご回答ありがとうございます。
>ほったてさま
そう言っている人がいたのですが、実際にその人が経験したのかどうかは定かではありません。私もその主張が信じられずネット上の文献をある程度探したのですが、意外なことにRDBMSでの原子性の実装についてはwikpediaなどで大雑把な手法は述べられていましたが細かい挙動について明確に述べているソースは見つかりませんでした。(Oracleのサイトも含めて) >unibonさま
私の質問の意図はこのような時のJDBCドライバの実装がrollback()をしない仕様であったり、またはrollback()する仕様で試みたが失敗したときにDBMS側で自主的に障害を検知してJDBCドライバからの命令がなくてもrollbackしてくれるのかを明確に知りたいというものです。 unibonさまがjavadocから引用された
という文章が今分かる範囲での結論であるように思います。 みなさまの見解が私の見解(通常考えうる確率ではゴミは残らない)と一緒であるように感じられて安心しました。 実績のあるRDBMSでも原子性を完全に実装するのは困難なことだとは思いますが、RDBMSベンダの原子性実装を放棄して、私の作成するJavaアプリでロールバックを実装することは(それによってリスクが減ることはまずあり得ない、というかそのような処理でautoCommit(true)にしていたら通常はリスクが高くなるので)やはりナンセンスだと思いました。 整合性を要求する複数のinsert, update文はまとめて実行し、catch節でrollback()をし、それに失敗したらログに出力するといった実装が妥当だという見解です。(そして通常はrollback()に失敗してもDBMS側で自主的にロールバックされていることを期待する。万一ロールバックされていなかった場合はログから状況を把握するしかないが、この可能性はほとんどないと認識する。) 引き続きご指摘やご経験等ございましたらご教授いただけると幸いです。 | ||||||||||||
|
投稿日時: 2008-02-18 08:06
RDBMSというかDBMSの常識としては、明示的にCOMMITするかトランザクションが
正常終了するとCOMMITされます。 明示的にROLLBACKしたり、トランザクションが異常終了すると、更新内容は無効に なります。 ROLLBACKが失敗するということは、ほったてさんも書いているように異常事態で あり、バックアップからの回復といった手段になると思います。 | ||||||||||||
|
投稿日時: 2008-02-18 11:46
例えばrollback()でSQLExceptionが返ってきたら、そのアプリはどう対応しますか?
Connection.close()しますかね? 単にトランザクションを中断してコネクションプールに返すことになりますかね? 前者ならトランザクションの状態が確定しないままセッション断ですから、セッション終了時にロールバックされますね。でも、rollback()が失敗するくらいだから、close()も失敗するかもしれませんね。その場合、既にセッションは無効になっているのでしょうから、理由はどうあれ、どっかのタイミングでOracleがきれいにクリーンアップしてくれるはずです。 コネクションプールに返した場合は・・・プールの実装とか設定に依存するかも。 別の処理がそのConnectionオブジェクトをプールから取り出して、ロールバックできなかったトランザクション内で処理を開始してしまう可能性はあると言えばありますよね。 でも普通に考えれば、rollback()のような基本的なメソッドがエラーを返す場合、そのセッションに大きな異常が発生していると考えられますから、そのConnectionオブジェクトはその後何をやってもエラーになる可能性が非常に高いでしょう。 プールからConnectionを取り出す度に、Connectionが有効かどうかをチェックしているようなら、その時に廃棄されるでしょうし、他の処理が使おうとしても何もできずにエラーになるだけ。 自分はrollback()の失敗の可能性に関しては、特に何の考慮もしていません。 | ||||||||||||
|
投稿日時: 2008-02-18 11:51
前の投稿とちょっとかぶりますが、念のため。
N/W障害とか、Oracleの特定セッションや特定プロセスのみに障害が発生するとか、Oracle全体としてみれば大した事態ではないことがほとんどだと思います。 | ||||||||||||
|
投稿日時: 2008-02-18 18:33
そっか、ネットワーク切れてればrollback投げても実行できませんな...。 | ||||||||||||
|
投稿日時: 2008-02-18 23:26
興味深いご回答ありがとうございます。
この話題はDBMSの実装やコネクションプールの実装に依存しているのでそのあたり気になるところではありますが、まずは常識的な実装がされていて気にする必要はないと考えてよい気がしました。 |