Sql-Server-2016
為什麼在層次結構中的更高級別使用意圖鎖,為什麼不使用正常鎖?
本文建議在鎖層次結構的較高級別使用意圖鎖,以指示已在較低級別上獲取鎖。這種機制的想法是,如果 SQL Server 想要在頁面或表上放置鎖,則不需要檢查每一行是否有活動鎖。
例如,如果我更新 AdventureWorks 中的一行:
USE AdventureWorks2014; BEGIN TRAN; UPDATE Person.Person SET LastName = 'Smith' WHERE BusinessEntityID = 1;
然後在另一個會話中,執行
sp_whoisactive
withget_locks
以查看使用了哪些鎖:
EXEC sp_whoisactive @get_locks = 1;
我可以看到以下內容:
<Locks> <Lock resource_type="KEY" index_name="IX_Person_LastName_FirstName_MiddleName" request_mode="X" request_status="GRANT" request_count="2" /> <Lock resource_type="KEY" index_name="PK_Person_BusinessEntityID" request_mode="X" request_status="GRANT" request_count="1" /> <Lock resource_type="OBJECT" request_mode="IX" request_status="GRANT" request_count="1" /> <Lock resource_type="PAGE" page_type="*" index_name="IX_Person_LastName_FirstName_MiddleName" request_mode="IX" request_status="GRANT" request_count="4" /> <Lock resource_type="PAGE" page_type="*" index_name="PK_Person_BusinessEntityID" request_mode="IX" request_status="GRANT" request_count="1" /> </Locks>
這支持了上面的文章所說的——我們在兩個相關索引上有一個排他的行(鍵)鎖,因此頁面和對像有 IX 鎖。
如果我嘗試在另一個會話中選擇該行:
SELECT * FROM Person.Person WHERE BusinessEntityID = 1
該查詢確實被阻止了。
因此,我的問題是,為什麼意圖鎖與“正常”鎖不同?為什麼 SQL Server 不只是在表上放置 X 鎖?
我想我已經找到了答案(如果我的理解有誤,請更正)
經過多讀後,我在這裡找到了一個簡單的矩陣:
與 IX 鎖相比,X 鎖與其他鎖的兼容性似乎較差。
如果我們因為讀取一行而在表上放置 X 鎖,我們無法在該表上獲得 IS 鎖,但如果我們在表上有 IX 鎖,我們可以獲得 IS 鎖。
如果我理解正確的話,如果我們用 X 鎖鎖定表來更新一行,我們就不能讀取不同的行,因為讀取不能在表上放置 IS。但是,如果我們使用 IX,它可以獲得所需的 IS 鎖。
以下測試似乎證明了這種情況:
更新單行:
USE AdventureWorks2016; BEGIN TRAN; UPDATE Person.Person SET LastName = 'Smith' WHERE BusinessEntityID = 1;
在另一個會話中,選擇與正在更新的行不同的行
SELECT * FROM Person.Person WHERE BusinessEntityID = 2
此行返回而不被阻塞
但是,如果我要獲得 X 鎖:
USE AdventureWorks2016; BEGIN TRAN; UPDATE Person.Person WITH (TABLOCKX) SET LastName = 'Smith' WHERE BusinessEntityID = 1;
此查詢現在被阻止:
SELECT * FROM Person.Person WHERE BusinessEntityID = 2