INDEX REBUILD和INDEX REORGANIZE和UPDATE STATISTICS是否涉及Sch-M的案例分析
總結
1、等待SCH_M的操作一般是涉及DDL的語句
2、等待SCH_S的操作一定是它前面的操作還在執行DDL並持有SCH_M還沒有結束
3、
重新生成索引online on有三個階段,開始階段佔用表的一個S鎖,索引操作的主要階段佔用表的一個意向共享 (IS)鎖,結束階段佔用表本身的一個Sch-M鎖
4、重新生成索引online on和刪除索引它們的快結束階段,如果這個快結束階段的過程比較長,則會一直持有表對應的SCH_M鎖,此時對該表執行WITH (NOLOCK)查詢也被會阻塞。
5、ALTER INDEX REORGANIZE重新組織索引使用的系統資源最少,並且是聯機操作。也就是說,不保留長期阻塞性表鎖,且對基礎表的查詢或更新可以在ALTER INDEX REORGANIZE事務處理期間繼續進行。
不更新表或索引的統計資訊,只對葉子級別的索引進行碎片整理,不對樹幹級別的索引進行碎片整理
6、ALTER INDEX REBUILD重新生成索引
會刪除並重新建立索引。這可以聯機完成,也可以離線完成,重新生成索引聯機執行(ON),則索引操作期間可以用此表中的資料進行查詢和修改資料。預設為OFF。
更新索引本身的統計資訊但是不更新表的統計資訊,對整個索引進行碎片整理
7、ALTER INDEX REORGANIZE不會佔用表本身的架構修改鎖(SCH_M)
8、UPDATE STATISTICS會佔用架構修改鎖(SCH_M),但是佔用的是表對應的MD的SCH_M而不是表本身的SCH_M
9、一旦某表的S鎖被P1佔用,則其後的會話P2如果需要佔用表的SCH_M鎖,則P2被P1堵塞,再其後的會話P3如果需要佔用表本身的SCH_S比如select table,P3不堵塞,再其後的會話P4如果需要佔用表本身的SCH_M或表對應MD的SCH_M,則P4被P2堵塞,這樣就是P4被P2堵塞,P2被P1堵塞
10、一表正在index rebuild online操作時,無法同時對錶執行index reorganize操作,否則會報錯The indexes on table "XXX" cannot be reorganized because there is already an online index build or rebuild in progress on the table.
11、
sys.dm_tran_locks的request_mode、resource_associated_entity_id、request_status、resource_type四個欄位可以看到一個會話需要請求的鎖型別、需要請求的物件的ID、該請求的當前狀態、需要請求的物件的資源型別(OBJECT表本身、METADATA表的後設資料、DATABASE表對應的資料庫名稱、FILE表對應的檔案、PAGE表對應的頁、HOBT表對應的堆或B樹)
SQL Server 資料庫引擎在表資料定義語言 (DDL) 操作(例如新增列或刪除表)的過程中使用架構修改 (Sch-M) 鎖。 保持該鎖期間,Sch-M 鎖將阻止對錶進行併發訪問。 這意味著 Sch-M 鎖在釋放前將阻止所有外圍操作。
某些資料操作語言 (DML) 操作(例如表截斷)使用 Sch-M 鎖阻止併發操作訪問受影響的表。
SQL Server 資料庫引擎在編譯和執行查詢時使用架構穩定性 (Sch-S) 鎖。 Sch-S 鎖不會阻止某些事務鎖,其中包括排他 (X) 鎖。 因此,在編譯查詢的過程中,其他事務(包括那些針對表使用 X 鎖的事務)將繼續執行。 但是,無法針對表執行獲取 Sch-M 鎖的併發 DDL 操作和併發 DML 操作。
所有查詢,包括在基於行版本控制的隔離級別下執行的事務,都在編譯和執行期間獲取 Sch-S(架構穩定性)鎖。 因此,當併發事務持有表的 Sch-M(架構修改)鎖時,將阻塞查詢。 例如,資料定義語言 (DDL) 操作在修改表的架構資訊之前獲取 Sch-M 鎖。 查詢事務,包括在基於行版本控制的隔離級別下執行的事務,都會在嘗試獲取 Sch-S 鎖時被阻塞。 相反,持有 Sch-S 鎖的查詢將阻塞嘗試獲取 Sch-M 鎖的併發事務。
所有查詢(包括那些帶有 READUNCOMMITTED 和 NOLOCK 提示的查詢)都會在編譯和執行過程中獲取 Sch-S(架構穩定性)鎖。 因此,當併發事務持有表的 Sch-M(架構修改)鎖時,將阻塞查詢。 例如,資料定義語言 (DDL) 操作在修改表的架構資訊之前獲取 Sch-M 鎖。 所有併發查詢(包括那些使用 READUNCOMMITTED 或 NOLOCK 提示執行的查詢)都會在嘗試獲取 Sch-S 鎖時被阻塞。 相反,持有 Sch-S 鎖的查詢將阻塞嘗試獲取 Sch-M 鎖的併發事務。
ON | OFF } <as applies to rebuild_index_option>
指定在索引操作期間基礎表和關聯的索引是否可用於查詢和資料修改操作。 預設為 OFF。
ON
在索引操作期間不持有長期表鎖。 在索引操作的主要階段,源表上只使用意向共享 (IS) 鎖。 這樣,即可繼續對基礎表和索引進行查詢或更新。 操作開始時,將對源物件保持極短時間的共享 (S) 鎖。 操作結束時,如果建立非聚集索引,將對源持有極短時間的 S 鎖;當聯機建立或刪除聚集索引時,或者重新生成聚集或非聚集索引時,將獲取 SCH-M(架構修改)鎖。 對本地臨時表建立索引時,ONLINE 不能設定為 ON。
在索引操作的主要階段,源表上只使用意向共享 (IS) 鎖。 索引重新生成開始時表上需要一個 S 鎖,聯機重新生成索引結束時表上需要一個 Sch-M 鎖。 不過兩個鎖都是短的後設資料鎖,特別是 Sch-M 鎖必須等待所有阻塞事務完成。 在等待期間,Sch-M 鎖在訪問同一表時阻止在此鎖後等待的所有其他事務
OFF
在索引操作期間應用表鎖。 建立、重新生成或刪除聚集索引、空間索引或 XML 索引或者重新生成或刪除非聚集索引的離線索引操作將獲得對錶的架構修改 (Sch-M) 鎖。 這樣可以防止所有使用者在操作期間訪問基礎表。 建立非聚集索引的離線索引操作將對錶獲取共享 (S) 鎖。 這樣可以防止更新基礎表,但允許讀操作(如 SELECT 語句)。
重新組織索引
使用最少系統資源重新組織索引。 透過對葉級頁以物理方式重新排序,使之與葉節點的從左到右的邏輯順序相匹配,進而對錶和檢視中的聚集索引和非聚集索引的葉級進行碎片整理。 重新組織還會壓縮索引頁。 壓縮基於現有的填充因子值。
手工執行alter index all on dbo.secmaster rebuild with (online on)的spid是713,被548堵塞,548只是一個select操作但是存放在一個事務裡,該事務沒有釋放,該事務持有表本身的sch_s,713執行index rebuild online on的結束階段需要表本身的sch_m,所以713被堵塞
DBCC INPUTBUFFER (713)
EventType Parameters EventInfo
Language Event 0 alter index all on dbo.secmaster rebuild with (online on)
DBCC INPUTBUFFER (548)
EventType Parameters EventInfo
Language Event 0 exec [dbo].[Alerts_GetSymbolData]
select nt_username,hostname,program_name,cmd,spid,blocked,lastwaittype,waitresource from sys.sysprocesses where spid in (713,548)
nt_username hostname program_name
cmd spid blocked lastwaittype waitresource
wondawebprocess PANALERTKSTG1 jTDS
SELECT 548 0 ASYNC_NETWORK_IO
lukes WONCNFORIDB SSMS - Query
ALTER INDEX 713 548 LCK_M_SCH_M TAB: 22:1771153355:0
取消713上面alter index rebuild 的操作,再手工執行alter index all on dbo.secmaster reorganize spid仍是713,沒有堵塞,可以正常執行完畢,548事務沒有釋放,該事務持有表本身的sch_s,713執行index reorganize不需要表本身的sch_m,所以713不被堵塞
DBCC INPUTBUFFER (713)
EventType Parameters EventInfo
Language Event 0 alter index all on dbo.secmaster reorganize
DBCC INPUTBUFFER (548)
EventType Parameters EventInfo
Language Event 0 exec [dbo].[Alerts_GetSymbolData]
select nt_username,hostname,program_name,cmd,spid,blocked,lastwaittype,waitresource from sys.sysprocesses where spid in (713,548)
nt_username hostname program_name
cmd spid blocked lastwaittype waitresource
wondawebprocess PANALERTKSTG1 jTDS
SELECT 548 0 ASYNC_NETWORK_IO
lukes WONCNFORIDB SSMS - Query
DBCC 713 0 WRITELOG
713上面alter index reorganize的操作完畢後,再手工執行update statistics dbo.secmaster仍是713,沒有堵塞,可以正常執行完畢,548事務沒有釋放,該事務持有表本身的sch_s,713執行update statistics不需要表本身的sch_m,只需要表對應的MD的sch_m,所以713不被堵塞
DBCC INPUTBUFFER (713)
EventType Parameters EventInfo
Language Event 0 update statistics dbo.secmaster
DBCC INPUTBUFFER (548)
EventType Parameters EventInfo
Language Event 0 exec [dbo].[Alerts_GetSymbolData]
select nt_username,hostname,program_name,cmd,spid,blocked,lastwaittype,waitresource from sys.sysprocesses where spid in (713,548)
nt_username hostname program_name
cmd spid blocked lastwaittype waitresource
wondawebprocess PANALERTKSTG1 jTDS
SELECT 548 0 ASYNC_NETWORK_IO
lukes WONCNFORIDB SSMS - Query
UPDATE STATISTIC 713 0 RESERVED_MEMORY_ALLOCATION_EXT
select nt_username,hostname,program_name,cmd,* from sys.sysprocesses where spid in (517,384,608,498,816) or nt_username='lukes' and dbid=22
nt_username hostname program_name
cmd spid blocked lastwaittype waitresource dbid
wondawebprocess PANALERTKSTG1 jTDS
SELECT
384 0 ASYNC_NETWORK_IO 6
SQLPROCESS STAGINGDB11 SQLAgent - TSQL JobStep (Job XXAD : Step 2)
CREATE INDEX
498 517 LCK_M_SCH_S TAB: 22:1771153355:0 22
SQLPROCESS STAGINGDB11 SQLAgent - TSQL JobStep (Job YYA7 : Step 1)
ALTER INDEX
517 384 LCK_M_SCH_M TAB: 22:1771153355:0 5
SQLPROCESS STAGINGDB11 SQLAgent - TSQL JobStep (Job ZZ02 : Step 5)
INSERT
608 498 LCK_M_S KEY: 22:844424932360192 (44a4d8a0238a) 22
lukes WONCNFORIDB SSMS - Query
UPDATE STATISTIC 744 517 LCK_M_SCH_M MD: database_id = 22 STATS(object_id = 1771153355, stats_id = 75), lockPartitionId = 0 22
lukes WONCNFORIDB SSMS - Transact-SQL IntelliSense
SELECT 769 498 LCK_M_S KEY: 22:562949958270976 (73d3e88aa61a) 22
lukes WONCNFORIDB SSMS - Transact-SQL IntelliSense
SELECT 779 498 LCK_M_S KEY: 22:1125899909070848 (056183c7bee9) 22
lukes WONCNFORIDB SSMS - Query
ALTER INDEX 814 816 LCK_M_SCH_S MD: database_id = 22 STATS(object_id = 1771153355, stats_id = 75), lockPartitionId = 0 22
SQLPROCESS STAGINGDB11 SQLAgent - TSQL JobStep (Job WWCA : Step 1)
UPDATE 816 744 LCK_M_SCH_S MD: database_id = 22 STATS(object_id = 1771153355, stats_id = 75), lockPartitionId = 0 22
備註:alter index rebuild with (online on)會話是814被堵塞,814等待816的update對應表object_id=1771153355的MD的LCK_M_SCH_S
,816等待744的UPDATE STATISTIC表object_id=1771153355的MD的LCK_M_SCH_S,744等待517表object_id=1771153355的MD的LCK_M_SCH_M
,517等待384表object_id=1771153355表本身的LCK_M_SCH_M
,384就是一個查詢但是佔用了表本身的SCH_S
select request_session_id,request_lifetime,request_type,request_mode,resource_associated_entity_id,request_status,resource_type,resource_subtype,resource_description
from sys.dm_tran_locks where resource_database_id=22 and request_session_id in (517,384) order by 1
request_session_id request_lifetime request_type request_mode resource_associated_entity_id request_status resource_type resource_subtype resource_description
384 0 LOCK Sch-S 35670239 GRANT OBJECT
384 0 LOCK Sch-S 1771153355 GRANT OBJECT
517 536870912 LOCK Sch-M 1771153355 WAIT OBJECT
517 33554432 LOCK Sch-M 1771153355 GRANT OBJECT INDEX_OPERATION
517 0 LOCK S 0 GRANT DATABASE DDL
517 33554432 LOCK Sch-S 0 GRANT METADATA DATA_SPACE data_space_id = 3
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 89
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 88
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 87
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 86
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 85
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 84
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 83
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 82
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 81
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 80
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 79
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 78
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 77
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 76
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 75
517 0 LOCK Sch-S 0 GRANT METADATA STATS object_id = 1771153355, stats_id = 75
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 74
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 2
517 0 LOCK Sch-S 0 GRANT METADATA INDEXSTATS object_id = 1771153355, index_id or stats_id = 1
備註:真正的堵塞是第三行517對應WAIT這一行,517等待的表1771153355本身的Sch-M,表1771153355本身的Sch-s被第二行384拿著沒有釋放
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30126024/viewspace-2749291/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- rebuild index 和 recreate index (重新建立index) 的區別RebuildIndex
- 【羅玄】從鎖的角度看rebuild index online和rebuild indexRebuildIndex
- alter index rebuild和rebuild online的區別IndexRebuild
- 聊聊索引Index Rebuild和Rebuild Online(下)索引IndexRebuild
- 聊聊索引Index Rebuild和Rebuild Online(上)索引IndexRebuild
- alter index ind1 rebuild 和alter index ind1 rebuild onlineIndexRebuild
- rebuild indexRebuildIndex
- index rebuildIndexRebuild
- rebuild index 排序RebuildIndex排序
- sybase rebuild indexRebuildIndex
- alter index rebuild與index_statsIndexRebuild
- ORACLE中index的rebuildOracleIndexRebuild
- Index rebuild --case 1IndexRebuild
- 關於move table和rebuild index批量操作的記錄RebuildIndex
- Index Online RebuildIndexRebuild
- 【江楓 】Oracle 9i和10g在create index和rebuild index的統計資訊的區別OracleIndexRebuild
- alter index rebuild 與 rebuild onlineIndexRebuild
- alter index compute statistics與analyze index的比較Index
- create index , rebuild index troubleshooting 索引故障解決IndexRebuild索引
- rebuild index online和create index online及沒有online的區別RebuildIndex
- analyze index 時validate structure和compute statistics的區別IndexStruct
- create index online 與rebuild index onlineIndexRebuild
- create index online 與rebuild index onlineIndexRebuild
- Oracle alter index rebuild 說明OracleIndexRebuild
- pk 、unique index 和 index 區別Index
- index rebuild online的問題IndexRebuild
- 大資料量rebuild index的經歷大資料RebuildIndex
- best practice of rebuild your partition table local index online by using: "update indexes"RebuildIndex
- INDEX UNIQUE SCAN,INDEX FULL SCAN和INDEX FAST FULL SCANIndexAST
- 建立檢視和淺析LOCAL INDEX和GLOBAL INDEXIndex
- Index Full Scans和Index Fast Full ScansIndexAST
- MYSQL中的type:index 和 Extra:Using indexMySqlIndex
- 重建索引index rebuild online vs offline vs index coalesce vs index shrik space索引IndexRebuild
- Index Full Scan和Index Fast Full Scan行為差異分析(上)IndexAST
- Index Full Scan和Index Fast Full Scan行為差異分析(下)IndexAST
- 加快create / rebuild index的3個點(zt)RebuildIndex
- 加快建立索引(create / rebuild index) 的幾點索引RebuildIndex
- 關於rebuild index online 及drop index後重建問題RebuildIndex