- PR -

OracleJDBC使用時のトランザクションの原子性の実現について

投稿者投稿内容
会議室デビュー日: 2008/02/17
投稿数: 6
投稿日時: 2008-02-17 02:20
Oracle JDBCドライバでOracleのデータ操作を行う際に質問があります。


JDBCにおけるDBのトランザクションの原子性は
Connection.commit()とConnection.rollback()によって実現されるそうですが、
あるinsert文の処理の成功後にrollback()を呼び出す際、rollback()に失敗した場合は原始性は保障されないのでしょうか。

よろしくおねがいします。

Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2008-02-17 08:14
commitの呼び出しに成功しない限りは、insertは実現しません。
なので、rollback()に失敗しても原始性は保障されます。
会議室デビュー日: 2008/02/17
投稿数: 6
投稿日時: 2008-02-17 20:26
ご回答ありがとうございます。

私もそう思っていたのですが、先日職場でrollback()に失敗するとゴミが残るという主張をしている人がいました。そこで原子性についてネット上の文献を探しても概念は詳しく説明されていますがDBMSの挙動について具体的な記述がなかなか見つかりませんでした。実際のところゴミが残るという状況が(バグではなくて実装上)あり得るのか、そしてJDBCを使うJavaアプリにおいてOracleの原子性を信用した設計はするべきではないのかどうか知りたいと思いました。

http://otndnld.oracle.co.jp/document/products/timesten/html/E05167-02/Operations_Guide-09-3.htmに以下の記述がありました。

原子性は、トランザクションがロールバックされた場合、ログを使用してその結果を元に戻すことで実現されます。ロールバックは、ODBC SQLTransact関数またはJDBC Connection.rollbackメソッドを使用するか、または障害発生時にトランザクションがコミットされなかったことによるデータ・ストアのリカバリ中に、アプリケーションによって明示的に発生させることができます。

この記述における「アプリケーション」とはOracleのDBMSアプリケーションのことで、JDBCで明示的にConnection.rollbackに成功しなくても障害発生時はDBMS側で障害を検知して自主的にロールバック処理が行われると考えてよいのでしょうか。

よろしくお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-02-17 20:34
ただたんにプログラムのコードで setAutoCommit(false); にしていないだけではないでしょうか?
http://www.atmarkit.co.jp/fjava/rensai/jdbc03/jdbc03.html

会議室デビュー日: 2008/02/17
投稿数: 6
投稿日時: 2008-02-17 21:55
説明不足ですみません。
setAutoCommit(false)に設定していることが前提での質問です。

質問したい点としては
JDBCを使うJavaアプリ設計において、rallback()できなかったときに「ゴミ」が残る危険性を考慮して、Javaアプリ側で独自にロールバック処理(再び整合性を回復するためのinsert文を流すとか。。)を実装する必要があるのかどうかをお聞きしたいです。(そんなときにJavaでの独自ロールバック処理が成功する筈ない気もしますが。)
皆様はどうされていらっしゃいますでしょうか。

よろしくお願いします。
会議室デビュー日: 2008/02/17
投稿数: 6
投稿日時: 2008-02-17 21:59
すみません。
Javaアプリ側で独自にロールバック処理(再び整合性を回復するためのinsert文を流すとか。。)を実装する場合はsetAutoCommit(true)にするか、一つ一つの更新の度にcommit()を実行した上でということです。
ほったて
ベテラン
会議室デビュー日: 2007/11/10
投稿数: 68
投稿日時: 2008-02-17 23:07
引用:

湯さんの書き込み (2008-02-17 21:55) より:

JDBCを使うJavaアプリ設計において、rallback()できなかったときに「ゴミ」が残る危険性を考慮して、Javaアプリ側で独自にロールバック処理(再び整合性を回復するためのinsert文を流すとか。。)を実装する必要があるのかどうかをお聞きしたいです。(そんなときにJavaでの独自ロールバック処理が成功する筈ない気もしますが。)
皆様はどうされていらっしゃいますでしょうか。




どっからそんな話が出たのか不明ですが...。ってかその「ゴミ」とやらは本当にデータの話なんでしょうかね。
(Oracleの動作としてありえない)

OracleってかRDBMS一般の話でしょうが、ミドルウェアが何であろうと、commitがきちんと完了したトランザクションのデータは必ず保障されますし(*)、逆にcommitが完了しなかったトランザクションは何があっても有効にはなりません。他のセッションから見ることはできませんし(Oracleでは)、もしそのトランザクションを発行してたセッションが異常終了した場合は、RDBMSのプロセスによってロールバックされます。トランザクション実行中にインスタンスがダウンしたときなんかは、起動処理の最中にロールバックされます(バージョンによりますが)。

ってかrollbackが失敗するってそんなあることでしょうかねぇ(UNDO破損? そりゃ大事だ)...。commitが失敗することは分散トランザクションとかでたまにありますけど。


* 時間ベースリカバリは忘れてください。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-02-17 23:16
引用:

湯さんの書き込み (2008-02-17 21:55) より:
質問したい点としては
JDBCを使うJavaアプリ設計において、rallback()できなかったときに「ゴミ」が残る危険性を考慮して、Javaアプリ側で独自にロールバック処理(再び整合性を回復するためのinsert文を流すとか。。)を実装する必要があるのかどうかをお聞きしたいです。(そんなときにJavaでの独自ロールバック処理が成功する筈ない気もしますが。)


私は、commit() しなければ、ロールバックするに決まっているじゃないか、と思っているのですが、それはただの思い込みなのかもしれません。証明しろと言われると自信がありません。
ちなみに、Oracle の実装ではなく、JDBC の仕様を見ると、たとえば、
http://java.sun.com/javase/ja/6/docs/ja/api/java/sql/Connection.html#close()
には、
引用:

close メソッドの呼び出し前に、アプリケーションでアクティブなトランザクションを明示的にコミットまたはロールバックすることを強くお勧めします。close メソッドが呼び出され、かつアクティブなトランザクションが存在する場合、その結果は実装で定義されたものになります。


と、書かれています。ということは、コミットされても文句は言えない?しかし、そんな不親切な実装があるのか?Oracle ならあってもおかしくない?

スキルアップ/キャリアアップ(JOB@IT)