4

JDBC を使用して MySQL データベースに接続する Java コードがいくつかあります。その後、コードはいくつかの読み取り操作を実行してから、すべて同じ接続を使用して 1 回の更新を実行します。例外がある場合は、 thenconnection.rollback()が呼び出されます。例外がなければconnection.commit()呼び出されます。この段階で、テストを実行するたびに接続が新しく作成されます (つまり、接続はプールからのものではありません)。私のコードは 1 つの接続のみを作成し、テスト全体で使用されます。

使用中の接続connection.setAutoCommit(false)は、接続インスタンスが作成された直後に呼び出されました。

何らかの理由で、例外が発生しconnection.rollback()て呼び出されると、更新がロールバックではなくコミットされていることがわかります。

デバッグにより、以下を確認しました。

  • を呼び出した後、予想どおり の値connection.setAutoCommit(false)connection.getAutoCommit()返しますfalse。また、予想どおり、自動コミットがオフであることを示す"Select @@session.autocommit"の値を返します。0

  • を呼び出す直前にconnection.rollback()、予想どおり、自動コミットがオフになっていることが同じチェックで示されます。

  • connection.commit()は確実に呼び出されておらず、connection.rollback()確実に呼び出されています。

また、ステートメントを明示的に実行しようと"rollback;"しましたが、問題は解決しません。"Set AUTOCOMMIT = 0;"また、接続を作成した後にステートメントを明示的に実行しようとしました。

私のテーブルはすべて InnoDB のストレージ エンジンを使用しています。自動コミットをオフにして SQL Workbench を使用すると、ロールバックとコミットが期待どおりに機能します。

MySQL バージョン '5.0.91-community-nt' を使用しています。MySQL jdbc ドライバーのバージョンは 5.1.19 です。私はJava 5を使用しています。

自動コミットがオフになっていて、コミットが呼び出されず、ロールバックが明示的に呼び出されているにもかかわらず、更新がコミットされる理由について何か提案はありますか?

乾杯。

4

1 に答える 1

2

OP で参照しているコードは単一のブロックではなく、複数のクラスに分散しています。コードの例に対する上記のクエリを満たすために、問題を説明する単一のコード ブロックを用意しました。コードのブロックが完成したら、問題を再現できることを確認するためにテストしました。問題を再現できませんでした。ロールバックは問題なく機能しました。これにより、プロダクション コードを調べて、私がまとめたコード ブロックを超えて実行していたすべてのことを解決する必要がありました。

本番コードは、一時テーブルの作成と削除の両方を行うことがわかりました。最も関連するのは、更新の実行後に一時テーブルを削除し、例外があるかどうかに関係なく一時テーブルを削除することです。MySQL でテーブルを削除すると、暗黙的なコミット呼び出しが発行されることがわかりました。したがって、例外をスローするコードと connection.rollback() を呼び出すコードの間にテーブルがドロップされ、暗黙的な呼び出しがコミットされます。したがって、私の「自動コミット」の問題です。

于 2012-11-07T13:53:43.750 に答える