Sql-Server

SQL Server - 在事務回滾期間我有什麼訪問權限?

  • May 1, 2016

正如標題所說,在回滾事務時,我是否具有對整個數據庫的讀/寫訪問權限?

還是僅對事務未寫入的表進行讀/寫訪問?什麼是鎖定行為?

如果我確實有讀取權限,當我讀取一個事務回滾寫入的表時會發生什麼(查詢是失敗還是只是等待)?

抱歉這些問題,我試過線上閱讀(ROLLBACK TRANSACTION (Transact-SQL)),但似乎沒有觸及到這個深度。

答案實際上很大程度上取決於您的隔離級別、正在回滾的事務持有什麼類型的鎖,以及您的非回滾會話試圖做什麼。

步驟 1) 什麼被鎖定?

ROLLBACK發布之前,該事務已經完成工作並獲得了鎖。您可以通過查看查看這些鎖的詳細資訊sys.dm_tran_locks

SELECT tl.resource_type, tl.resource_associated_entity_id,
      tl.request_status, tl.request_mode, tl.request_session_id,
      tl.resource_description
FROM sys.dm_tran_locks tl
WHERE tl.request_session_id = <ROLLBACK session id>;

resource_typeresource_associated_entity_id告訴你什麼被鎖定。如果resource_type是“對象”,那麼resource_associated_entity_idobject_id. 如果resource_type是“Key”或“Page”,resource_associated_entity_id則為hobt_id. 有更多類型要解碼,但這兩種涵蓋了大多數場景。

SELECT tl.resource_type, tl.resource_associated_entity_id,tl.resource_database_id,
      CASE WHEN resource_type = 'OBJECT' 
               THEN object_name(tl.resource_associated_entity_id,tl.resource_database_id)
           WHEN resource_type IN ('KEY','PAGE')
               THEN object_name(p.object_id)
       END AS resource_name,
      tl.request_status, tl.request_mode, tl.request_session_id,
      tl.resource_description
FROM sys.dm_tran_locks tl
LEFT JOIN sys.partitions p ON p.hobt_id = tl.resource_associated_entity_id
                          AND tl.resource_database_id = db_id()
WHERE tl.request_session_id = <ROLLBACK session id>;

最後,鎖定模式提供了有關如何使用該鎖定的資訊。BOL列出了所有不同的鎖定模式。

第 2 步:什麼會被阻止?

如果正在回滾的事務沒有鎖定對象,則ROLLBACK不會阻塞其他會話。那部分很容易。

這些鎖是否會導致阻塞將取決於您的隔離級別以及您要執行的操作。Paul White有一個關於隔離級別的非常深入的系列,您可以閱讀該系列以了解很多細節。

讀、寫和隔離級別的不同組合會產生不同的阻塞結果。一般來說,寫總是阻塞寫。但是,寫入可能會或可能不會阻止讀取。在 SQL Server 的預設READ_COMMITTED隔離級別下,寫入將阻止讀取。如果您正在使用READ_COMMITTED_SNAPSHOT(又名“RCSI”又名“使用行版本控制讀取送出”),那麼寫入不會阻塞讀取。

在所有情況下,如果另一個會話被 中的會話阻塞ROLLBACK,則等待會話將一直等到ROLLBACK釋放鎖。

您應該從兩個不同的角度來看待這一點 - 發出 ROLLBACK 的連接和所有其他連接的角度。

發出連接很簡單:不,您無權訪問。ROLLBACK 是同步執行的。在 ROLLBACK 成功之前,此連接無法執行任何其他操作。(如果它因任何原因失敗,您將處於痛苦的世界中,並且可能與 MS 支持人員交談。)

對於所有其他連接,沒有變化。在 ROLLBACK 啟動之前他們可以做的任何事情,他們都可以在它進行時做。事務 B 是否可以讀取被事務 A 鎖定的值將取決於 A 持有的鎖的類型以及 B 正在執行的隔離級別。對於那些提供最高數據完整性保證的組合,B 通常會等待 A 完成並釋放鎖。如果 B 設法讀取 A 已鎖定的值,並且 A 更改了該值,DBMS 將不會神奇地進入應用程序並更改以前讀取的值。請注意,這與如果 B 第二次讀取同一行將收到相同的結果不同。

隨著事務執行工作(即更改各行中的值),鎖定被佔用1. 這些鎖可防止 DBMS 中的各種並發活動破壞彼此的工作。它們允許多個使用者連接到單個數據庫並並行執行工作,同時保持數據完整。它們有助於實現並發和隔離——兩個非常值得熟悉的大主題。可以對行、頁或表進行鎖定。如果單個行被一個連接鎖定,則所有其他行將可供其他連接使用。如果整個表被鎖定,那麼在釋放鎖之前,沒有其他連接可以在該表上工作。(我在這裡滑過整個世界的精妙之處以保持重點。)隨著工作的進行,這些鎖被逐步獲取,一次一個。此外,“之前”和“之後”

在 ROLLBACK 期間,DBMS 通過日誌文件反向處理所做的每個更改,獲取“之前”值並將它們替換到表的數據中。當它返回到 BEGIN TRANSACTION 語句時,所有表的值都將恢復到它們開始時的狀態,並且我們保證沒有其他使用者會因為鎖定而執行沖突更改。

可以想像,ROLLBACK 可以在撤消更改時釋放鎖。然而,我寧願認為它不會。由於最初正在完成工作,可能有幾個原因需要鎖定一行,比如它被更新了兩次。要使 ROLLBACK 上的增量鎖釋放起作用,必須記錄這兩個更新以及鎖本身,這是很多內部簿記,希望這是一個罕見的事件。所以我寧願認為所有的鎖都被持有,直到所有的數據都回到它開始的時候,然後所有的鎖都被釋放了。

此時,所有其他事務都可以繼續進行,就好像回滾事務從未存在一樣。那些等待先前鎖定的物品的人從沉睡中醒來,並允許訪問現在解鎖的值。

1這方面有很多變化。隔離級別很重要。多值並發控制很重要。我限制討論以盡可能簡潔地回答實際問題,而不涉及所有配置選項、警告和特殊情況。

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