昨晚某現場報一個重建索引失敗的問題,遠程查看后發現是自動收縮的內部會話引發的鎖申請超時,突然想起來自己的加鎖實驗還沒完成索引重建部分,今天有空正好做一下:
USE [數據庫名]
GO
ALTER INDEX <索引名> ON dbo.<表名> REBUILD PARTITION = ALL WITH ( MAXDOP = 4, ONLINE = OFF, SORT_IN_TEMPDB = OFF )
GO
先試了下聚集索引的重建,以下是相關會話的所有加鎖情況:
從以上的鎖分布情況來分析,首先我們過濾掉所有非相關表的鎖,那么整個結果集只剩下了6行:
55 5 1589580701 0 TAB S GRANT
55 5 1589580701 0 TAB S GRANT
55 5 1589580701 0 TAB S GRANT
55 5 1589580701 0 TAB S GRANT
55 5 1589580701 0 TAB Sch-M GRANT
55 5 1605580758 0 TAB Sch-M GRANT
這里出現了4個TAB類型的S鎖和一個表級的Sch-M鎖以及一個聚集索引的Sch-M鎖,從官網提供的鎖兼容圖來看S鎖和Sch-M鎖是不兼容的,因此這幾個S鎖的出現就比較詭異了,查看dm_tran_locks發現request_exec_context_id不一樣,而官網對此字段的解釋就一句:Execution context ID of the process that currently owns this request.
所以這里有一個問題:不同的request_exec_context_id代表的TAB類型的S鎖到底是什么?為何與Sch-M鎖不沖突?
在SQLOS的任務調度算法中,有一個概念叫做context switch,同計算機原理中的CPU切換一樣,意思是同一個CPU針對并發的會話進行線程切換。我們這里只有一個會話一條語句,因此猜測是并行造成的現象。
事后進行了多次測試,發現開不同的并行數(MAXDOP)目得到的S鎖數目與并行數一樣,因此這里得request_exec_context_id每個值對應一個并行線程。而針對同一個資源S鎖和Sch-M是不兼容的,因此感覺這里的S鎖是一個顯示小BUG。
Ps:下圖里的object_id與之前的不同是因為不是一個表,無需在意。
因此重建聚集索引的過程中會對表和涉及的索引加Sch-M的架構鎖,而此架構鎖與所有其他鎖沖突,因此不能再執行任何針對此表的增刪改查。
之后測試了非聚集索引的情況,加鎖情況一致因此不作討論。
文章列表