2013-08-01 44 views
2

SQL Server 2008 R2 - ReadCommitted隔離級別更新到獨佔鎖轉換

我試圖準確確定SQL服務器何時將更新鎖轉換爲獨佔鎖。例如,我有表dbo.TableA。 dbo.TableA有兩個列PKCol1和NCCol2。 PKCol1是一個聚集索引,NCCol2上有一個非聚集索引。如果我是執行

BEGIN TRAN 

DELETE 
FROM dbo.TableA 
WHERE NCCol2 = 1 

COMMIT TRANSACTION 

而優化器選擇掃描NCCol2找到所有候選記錄,將在非聚集索引操作掃描索引中的所有記錄。在聚簇索引刪除操作員將這些鎖轉換爲排他鎖並刪除之前,將更新鎖添加到每個候選記錄,直到它掃描完整個索引。

或者非聚集索引運算符是否會掃描每條記錄,然後將更新鎖添加到候選記錄,評估該行是否匹配,以及是否將更新鎖轉換爲排它鎖。

基本上哪個運算符將更新鎖轉換爲排他鎖,非聚集索引掃描一旦掃描發現該記錄是匹配或聚集索引刪除候選行一旦識別並傳遞給它?

聯機叢書告訴我

更新(U)

用於可更新的資源。防止當多個會話在讀取,鎖定和以後可能更新資源

專屬

用於數據修改操作,例如INSERT(X),更新發生死鎖的常見形式或DELETE。確保不能同時對同一資源進行多個更新。

其他信息1

我其實是調查其對非唯一的非聚集INT索引2發生以下後優化器選擇了以下計劃

Non-Clustered Index Scan 僵局譯爲

死鎖
  1. 受害者對dbo表進行更新鎖定。表1索引2行1
  2. 業主承擔了dbo.Table1索引2的排它鎖ROW2
  3. 受害者等待上dbo.Table1索引2更新鎖ROW2
  4. 所有者等待上dbo.Table1索引2更新鎖ROW1

這是我的理解是,執行計劃中的每個操作符都是按照從右到左的順序完整執行的。但我的理解是,更新鎖只在UPDATE/INSERT或DELETE期間轉換爲排它鎖,即聚簇索引刪除操作符。因此,我不確定爲什麼步驟2中的所有者對Index2 row2有獨佔鎖定,這表明它處於聚簇索引刪除步驟,但仍在等待更新鎖定,這將表明它也是非聚簇索引掃描步驟。它怎麼可能在同一時間的兩個步驟?

但是,如果你認爲這兩個更新和排它鎖索引過程中取得的掃描然後這個僵局會更有意義。

經過重新編譯優化器選擇上尋求聚集索引,沒有任何問題

Clustered Index Delete @Bogdan Sahlean & @布賴恩 - 非常感謝您的幫助和建議。

回答

2

語境:

DELETE語句的目標-The表具有唯一聚集索引(PK)和非聚集索引。

- 集中索引的關鍵是IDA

- 非聚集索引的密鑰是NCCol2

- TableA內容:

-- Clustered index (C index) 
NCCol2 IDA lockhash (these values are the "identifier" of locks) 
------ --- -------------- 
1  11 (29cf3326f583) 
2  22 (31178495a25a) 

-- Non-Clustered index (NC index) 
NCCol2 lockhash 
------ -------------- 
1  (8194443284a0) 
2  (61a06abd401c) 

在這種情況下:

  1. SQL Server將選擇一個Index Seek(非集羣與NCCol2鍵索引)來查找記錄和Clustered Index Delete運營商刪除記錄: enter image description here

  2. Index Seek(上NCCol2)操作者發現使用該謂詞(NNCol2=1

  3. 對於從非聚集索引的U鎖被取每個記錄的記錄(見lockhash (8194443284a0))和另一U鎖取從相應的記錄聚集索引(PK;見lockhash (29cf3326f583)

  4. 然後在聚簇索引記錄中的先前U鎖(lockhash (29cf3326f583))轉化爲X鎖和U鎖非聚集索引記錄(lockhash (8194443284a0))被轉換,也在X鎖。

  5. 兩個索引的記錄都被刪除(我認爲這是刪除這些記錄的時刻),並且之前的X鎖被釋放。

  6. 使用非聚集索引>轉到步驟#2查找另一行。

你可以攔截這些事件的使用SQL事件探查器(Lock:AquiredLock:Released)(或服務器的痕跡,擴展事件): enter image description here

TLTR:索引查找(查找記錄)>ü鎖定NC索引記錄>鎖定C索引記錄> U - > X用於C索引記錄> U - > X用於NC索引記錄>刪除記錄>重複(查找另一行)。

編輯1:Scan可能有許多原因:

1)一些implicit conversions(正如布賴恩指出)通過類型優先產生(1會如果數據庫被配置爲Simple Parametrization1TINYINT如果數據庫配置爲Force Parametrization,則具有與列類型相同的類型)。

2)索引可能被禁用。

3)它是一個過濾後的索引(link),或者是在計算列上定義的索引,並且設置(link: SET Option Requirements)不合適。

4)這是一個篩選索引,並且該數據庫已激活Parametrization Forced設置。

5)[低概率]這是一個小表,並且(由於某種原因)SQL Server選擇Scan而不是Seek

+1

+1爲內部@博格丹。只要NCCol2與其相比較的相等值相同,這種情況就會成立。例如,如果NCCol2是varchar(25)並且相等值爲int,則它將作爲nc掃描,因爲數據類型優先級要求varchar端在比較之前隱式轉換爲int。如果你沒有考慮到這一點,你顯然會比我更聰明的開發者工作。 – brian

+1

@brian:謝謝。我同意,但將隱含/顯式轉換的信息添加到我的答案中並非我的意圖。 Jonathan Kehayias在這個問題上有非常好的博客文章:[鏈接](http://www.sqlskills.com/blogs/jonathan/implicit-conversions-that-c​​ause-index-scans/)。 –

+1

再次+1。同意,但OP選擇掃描直接跳入優化器。這導致我想知道他/她在試圖理解的問題中是否沒有數據類型不匹配。無論是NCCol2 = 1還是非常低的選擇性,並且掃描比尋找便宜。不要誤解我的意思,你無法更好地解釋鎖升級。 – brian