鎖相容性圖: 一、鎖的粒度: 比較需要註意的是RID/KEY、HoBT/PAGE這兩對兒的區別,RID和HoBT是針對堆表的,即沒有聚集索引的表。 二、鎖的模式: 1.關於其中的S、U、X鎖: 共用鎖 共用鎖(S 鎖)允許併發事務在封閉式併發控制下讀取 (SELECT) 資源。 資源上存在共用鎖(S ...
鎖相容性圖:
一、鎖的粒度:
比較需要註意的是RID/KEY、HoBT/PAGE這兩對兒的區別,RID和HoBT是針對堆表的,即沒有聚集索引的表。
二、鎖的模式:
共用鎖
共用鎖(S 鎖)允許併發事務在封閉式併發控制下讀取 (SELECT) 資源。 資源上存在共用鎖(S 鎖)時,任何其他事務都不能修改數據。 讀取操作一完成,就立即釋放資源上的共用鎖(S 鎖),除非將事務隔離級別設置為可重覆讀或更高級別,或者在事務持續時間內用鎖定提示保留共用鎖(S 鎖)。
更新鎖
更新鎖(U 鎖)可以防止常見的死鎖。 在可重覆讀或可序列化事務中,此事務讀取數據 [獲取資源(頁或行)的共用鎖(S 鎖)],然後修改數據 [此操作要求鎖轉換為排他鎖(X 鎖)]。 如果兩個事務獲得了資源上的共用模式鎖,然後試圖同時更新數據,則一個事務嘗試將鎖轉換為排他鎖(X 鎖)。 共用模式到排他鎖的轉換必須等待一段時間,因為一個事務的排他鎖與其他事務的共用模式鎖不相容;發生鎖等待。 第二個事務試圖獲取排他鎖(X 鎖)以進行更新。 由於兩個事務都要轉換為排他鎖(X 鎖),並且每個事務都等待另一個事務釋放共用模式鎖,因此發生死鎖。
若要避免這種潛在的死鎖問題,請使用更新鎖(U 鎖)。 一次只有一個事務可以獲得資源的更新鎖(U 鎖)。 如果事務修改資源,則更新鎖(U 鎖)轉換為排他鎖(X 鎖)。
排他鎖
排他鎖(X 鎖)可以防止併發事務對資源進行訪問。 使用排他鎖(X 鎖)時,任何其他事務都無法修改數據;僅在使用 NOLOCK 提示或未提交讀隔離級別時才會進行讀取操作。
數據修改語句(如 INSERT、UPDATE 和 DELETE)合併了修改和讀取操作。 語句在執行所需的修改操作之前首先執行讀取操作以獲取數據。 因此,數據修改語句通常請求共用鎖和排他鎖。 例如,UPDATE 語句可能根據與一個表的聯接修改另一個表中的行。 在此情況下,除了請求更新行上的排他鎖之外,UPDATE 語句還將請求在聯接表中讀取的行上的共用鎖。
2.關於其中的意向鎖: 意向鎖有兩種用途:- 防止其他事務以會使較低級別的鎖無效的方式修改較高級別資源。
- 提高資料庫引擎在較高的粒度級別檢測鎖衝突的效率。
資料庫引擎在表數據定義語言 (DDL) 操作(例如添加列或刪除表)的過程中使用架構修改 (Sch-M) 鎖。 保持該鎖期間,Sch-M 鎖將阻止對錶進行併發訪問。 這意味著 Sch-M 鎖在釋放前將阻止所有外圍操作。
某些數據操作語言 (DML) 操作(例如表截斷)使用 Sch-M 鎖阻止併發操作訪問受影響的表。
資料庫引擎在編譯和執行查詢時使用架構穩定性 (Sch-S) 鎖。 Sch-S 鎖不會阻止某些事務鎖,其中包括排他 (X) 鎖。 因此,在編譯查詢的過程中,其他事務(包括那些針對錶使用 X 鎖的事務)將繼續運行。 但是,無法針對錶執行獲取 Sch-M 鎖的併發 DDL 操作和併發 DML 操作。
- 使用 Transact-SQL BULK INSERT 語句或 OPENROWSET(BULK) 函數,或者您使用某個大容量插入 API 命令(如 .NET SqlBulkCopy)、OLEDB 快速載入 API 或 ODBC 大容量複製 API 來將數據大容量複製到表。
- TABLOCK指定提示或表大容量載入上的鎖表選項設置使用sp_tableoption。
關於鍵範圍鎖可以參考官網,或者另一篇博客SQL Server事務隔離級別中對於可序列化讀隔離級別的加鎖說明。
三、鎖升級
SQL Server資料庫會發生鎖升級,官網說明的鎖升級觸發條件為,如果沒有使用 ALTER TABLE SET LOCK_ESCALATION 選項來禁用表的鎖升級並且滿足以下任一條件時,觸發鎖升級:- 單個 Transact-SQL 語句在單個無分區表或索引上獲得至少 5,000 個鎖。
- 單個 Transact-SQL 語句在已分區表的單個分區上獲得至少 5,000 個鎖,並且 ALTER TABLE SET LOCK_ESCALATION 選項設為 AUTO。
- 資料庫引擎實例中的鎖的數量超出了記憶體或配置閾值。
- 如果由於鎖衝突導致無法升級鎖,則資料庫引擎每當獲取 1,250 個新鎖時便會觸發鎖升級。
- 使用READ_COMMITTED_SNAPSHOT事務隔離級別。
- 使用SNAPSHOT事務隔離級別。
- 使用READ UNCOMMITTED事務隔離級別。