Sql-Server

頁面鎖定過多

  • March 23, 2016

有一個查詢:

SELECT entry_id FROM table_name 
WHERE (path_id = 7 AND value_string =  N'00020003-0004-0005-0006-000700080009' )

此查詢中的表包含數百萬條記錄。兩者path_id都有value_string自己的非聚集索引。

當我使用 SQL Server Profiler 使用Lock:Acquired事件跟踪此查詢時,我看到採取了三個 IS 頁面鎖:一個在包含value_string“00020003-0004-0005-0006-000700080009”的頁面上,一個在包含path_idas 6(這是驚人的),一個在包含path_idas的頁面上7(這是預期的)。

我獲取有關頁面資訊的方式:Lock:Acquired有一個TextData包含文本的欄位,例如1:87032; 我接受並執行

DBCC PAGE ('mc33', 1, 87032, 3) 

然後我得到這樣的輸出:

帶有頁面資訊的表格輸出

問題是:如果查詢只對 sevens 感興趣,為什麼引擎會在只包含 sixes 的頁面上放置 IS 鎖?當此查詢與某些插入並行執行時,這種“過度”鎖定會導致我們死鎖,我想知道如何擺脫這種鎖定。

定位一個值意味著從上層點錨點遍歷(這解釋了6es)。IS在 read-commited 隔離下遍歷需要鎖。這既不“過分”也不出人意料。如果我冒昧地猜測一下,我會推測這path_id是一個低選擇性值,並且該索引沒有太大幫助。

你抱怨死鎖,我建議你相應地調查它們,從死鎖圖開始。

附帶說明一下,使用基於行版本控制的隔離級別可以緩解過度鎖定(當真正引起關注時) 。如果您對 B-Tree seek 如何實際工作的底層細節感興趣,請從事務處理:概念和技術開始

詳細一點:內頁將包含一個鍵和一個指向頁/槽的指針。這意味著“從指針開始的頁麵包含於此鍵值的值”。Seek 將搜尋上頁,直到找到大於 seek-ed 值的第一個鍵。它跳轉到指針並從那裡遞歸地繼續。如果上面的頁面說“從第 148 頁開始,所有鍵都小於 8”,並且第 148 頁包含 6es,則 seek 將使用 6es 鎖定頁面。這裡沒有魔法精靈塵埃。鎖定大量 6es 清楚地表明該鍵的選擇性非常低:有許多行重複了小範圍的鍵值。

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