web-dev-qa-db-ja.com

コミット後のロールバック

アプリケーションがフリーズしたため、複数のデータベースセッションがあり、そのうちの1つが他のセッションをブロックしています。複数のセッションで実行されているトランザクションがあります。他のセッションでのロックリクエストのタイムアウトのため、ヘッドブロッカーを強制終了する必要があります。そのセッションを終了した後、他のユーザーがデータの損失を報告しています。彼らはトランザクションをコミットしたと確信していますが、まだロールバックされているようです。後でデータが欠落している一部のドキュメントが印刷されているため、彼らはそれを証明することさえできます。

別のセッションでのロールバックが原因で、コミットされたトランザクションがロールバックされている可能性はありますか?私はそうは思いませんが、 COMMITドキュメント を読んだ後、疑問があります。それは言う:

@@ TRANCOUNTが1より大きい場合、COMMIT TRANSACTIONは@@ TRANCOUNTを1だけ減らし、トランザクションはアクティブのままです。

TRANCOUNTドキュメント を読むと、

現在の接続で発生したBEGIN TRANSACTIONステートメントの数を返します。

現在の接続はセッションと同じですか、それとも複数のセッションが同じ接続を共有できますか(おそらくプールによる)?そして、彼らが共有できる場合、これはトランザクションとどのように関係しますか?これらのアクティブなトランザクションがコミットされた後で、後でロールバックされている可能性がありますか?

[編集]より明確にするために、一部のユーザーはデータがヘッドブロッカーと競合しないため、ロックタイムアウトを取得しませんでした。彼らはトランザクションをコミットしましたが、それらのトランザクションはヘッドブロッカーを殺した後にロールバックされたようです。

[Update 2018-03-29]新しいインシデントの後、問題が発生している間に調査する機会がありました。トランザクションログは、問題がコミットされないネストされたトランザクションであると結論付けました。問題の原因となったアプリケーションはフリーズされていなかったため、ユーザーはアプリケーションを閉じるまで気付かなかった。その時点で、トランザクションがロールバックされたため、データを失った。私は可能な限り最良の回答を受け入れましたが、それはコミットされたトランザクションをロールバックすることが不可能であると私に言ったものでした。それは本当に不可能だと思います。本当の問題を見つけるのは難しいです。

4
Martin

一般に、トランザクションは正確のいずれかです。

  • 関与する
  • ロールバック

コミットされたトランザクションは決してロールバックされません。
すべてのRDBMSがこのように動作します ACIDの原則

現在、このルールに違反しているように見える場合がいくつかあります。しかし、そうではありません。

ただし、これらのケースを見る前に、異なるユーザーセッションは接続を共有しません。各ユーザー/クライアントはSQLへの1つの接続を持ち、すべてが互いに分離されています。接続プーリングはこれに影響を与えません。

セーブポイント

トランザクションを保存して、このセーブポイントにロールバックできます。

つまり、セーブポイントを使用すれば、部分的にコミット/ロールバックできますが、実際のコードでこれを実行する人は見たことがありません。これ以上拡大しない。

ネストされたトランザクション

トランザクションをネストできますが、実際には何も意味しません
簡単に言うと、@@ TRANCOUNTが1より大きくても、SQL Serverには実際にはネストされた変換はありません。

  • Beginは@@ TRANCOUNTを1つインクリメントします
  • ロールバックは@@ TRANCOUNTをゼロに設定します
  • コミットにより@@ TRANCOUNTが1つ減ります

より詳しい説明は this SO answer です。

11
gbn

1)コミットされたトランザクションのロールバックについて。 「@@ TRANCOUNTが1より大きい場合」で参照したドキュメントは、単一のセッションでトランザクションをネストすると発生します。 https://technet.Microsoft.com/en-us/library/ms189336%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396

その場合、最後のトランザクションは、その作業とネストされたトランザクションをコミットまたはロールバックします。

2)あなたが説明したのは、複数のトランザクションを開始したいがブロックされている複数のセッションです。要求しているトランザクションが互換性のあるロックを利用できず、アプリケーションがデータを保存できなかったため、「データの損失」が発生しています。 「データ損失」という用語は、実際にはアプリケーションの問題であるため使用しました。トランザクションが失敗したことを認識し、トランザクションを再試行するか、エンドユーザーに警告するようにアプリケーションをコーディングして、予期しないことがないようにします。

データベースエンジンは、設計されたとおりのことを行い、ACID原則の違反を防止しました。

1
Steve Hansen