Sql-Server

送出後回滾

  • November 9, 2018

我有多個數據庫會話,其中一個由於凍結的應用程序而阻止了其他數據庫會話。有在多個會話上執行的事務。由於其他會話上的鎖定請求超時,我需要殺死頭部阻止程序。殺死該會話後,其他使用者報告了數據失去。我很確定他們已經送出了他們的交易,但他們似乎仍然被回滾了。他們甚至可以證明這一點,因為一些文件已經列印出來,之後失去了數據。

是否有可能由於另一個會話的回滾而回滾已送出的事務?我認為不會,但在閱讀了COMMIT 文件後,我有疑問。它說:

如果@@TRANCOUNT 大於1,COMMIT TRANSACTION 將@@TRANCOUNT 僅遞減1,並且事務保持活動狀態。

閱讀它說的TRANCOUNT 文件:

返回目前連接上發生的 BEGIN TRANSACTION 語句數。

那麼目前連接是否與會話相同,或者多個會話可以共享同一個連接(可能通過池化)?如果他們可以分享,這與交易有什麼關係?這些活動事務是否會在稍後甚至在它們被送出之後被回滾?

$$ edit $$更清楚地說,一些使用者沒有獲得鎖定超時,因為他們的數據沒有與頭部攔截器衝突。他們送出了交易,但這些交易似乎在殺死頭部阻止程序後被回滾。 **$$ Update 2018-03-29 $$**在發生新事件後,我有機會在問題發生時對其進行調查。事務日誌得出結論,問題是一個從未送出的嵌套事務。導致問題的應用程序沒有被凍結,因此使用者在關閉應用程序之前從未註意到它。那時他失去了他的數據,因為事務被回滾了。我接受了可能的最佳答案,那就是告訴我不可能回滾已送出的事務。我想這真的不可能,只是很難找到真正的問題。

通常,交易恰好是其中之一

  • 堅定的
  • 回滾

送出的事務永遠不會回滾。

這是所有 RDBMS 的運作方式,基於ACID 原則

現在,在一些不同的情況下,這條規則可能看起來被打破了。但事實並非如此。

不過,在我們查看這些情況之前,不同的使用者會話不共享連接。每個使用者/客戶端都有一個到 SQL 的連接,並且所有連接都是相互隔離的。連接池不會影響這一點。

保存點

你可以保存一個事務並回滾到這個保存點,

也就是說,如果您使用保存點,您可以部分送出/回滾,但我從未見過有人在現實生活中的程式碼中這樣做。我不會再展開了。

嵌套事務

您可以嵌套事務,但它們實際上並沒有任何意義

簡單地說,即使@@TRANCOUNT 可以大於一,SQL Server 也沒有真正的嵌套事務。

  • A begin 將@@TRANCOUNT 加一
  • 回滾會將@@TRANCOUNT 設置為零
  • 送出將@@TRANCOUNT 減一

更長的解釋在這個 SO answer

引用自:https://dba.stackexchange.com/questions/188653