SQL Server 2012では、インデックスの再構築ジョブに非常に長い時間がかかります(最大8時間)。ただし、インデックスの再構築が1つも完了しなかったため、インデックスジョブを停止しました。
SQLタスクの監視:
state = SUSPENDED
, comment = ALTER INDEX
, APPLICATION name = Microsoft SQL server Management Studio
, Query Wait = LCK_M_SCH_M
, Head Blocker = object lock
lock Partition = 15
objid=585105175
subresource=FULL
dbid=5
id=lockaa7aae200
mode=Sch-S
associatedObjectId=585105175 1386
役立つ情報をお寄せいただきありがとうございます。
インデックスの再構築が完了しないのは、LCK_M_SCH_M
待機タイプ。インデックスを再構築しようとするとどうなりますか、Sch-M
再構築しようとしているオブジェクトに対してロックが要求されています。
以下を参照してください グラフロック互換性:
ここでわかるように、Sch-M
ロックは、ほぼすべてのロックシナリオ(共有、排他、更新、スキーマの安定性など)と競合します。
これは、環境で何が起こっているかを示す小さな例です。テストデータベースにテストオブジェクトを作成するには:
use TestDB;
go
create table dbo.ConcurrencyTest
(
id int identity(1, 1) not null
constraint PK_ConcurrencyTest_Id primary key clustered,
some_int int not null
default 1
);
go
insert into dbo.ConcurrencyTest
default values;
go 100
ここで、1つのセッションがクエリを実行していて、ロックが開いたままの場合(更新クエリを使用しており、トランザクションをコミットしていません):
use TestDB;
go
begin tran;
update dbo.ConcurrencyTest
set some_int = 2
where id = 7;
--commit tran;
そして、別のセッションがそのテーブルのクラスター化インデックスを再構築しようとした場合:
use TestDB;
go
alter index PK_ConcurrencyTest_Id
on dbo.ConcurrencyTest
rebuild;
go
最初のUPDATE
クエリによってブロックされます。以下の小さな診断クエリでこれを確認できます。
select
l.resource_type,
l.resource_associated_entity_id,
l.request_mode,
l.request_status,
l.request_session_id,
st.text as blocked_sql_text,
r.blocking_session_id,
stb.text as blocking_sql_text
from sys.dm_tran_locks l
inner join sys.dm_exec_connections c
on l.request_session_id = c.session_id
left join sys.dm_exec_requests r
on l.request_session_id = r.session_id
inner join sys.dm_exec_connections cb
on r.blocking_session_id = cb.session_id
cross apply sys.dm_exec_sql_text(c.most_recent_sql_handle) st
cross apply sys.dm_exec_sql_text(cb.most_recent_sql_handle) stb
where l.resource_database_id = db_id('TestDB')
and l.request_status = 'WAIT'
and r.blocking_session_id is not null
and r.blocking_session_id > 0;
出力は次のようになります。
ご覧のとおり、私のALTER INDEX ... REBUILD
コマンドはUPDATE
クエリによってブロックされています。リクエストロックはSch-M
この操作を完了するためにOBJECT
で必要なロック。
この同時実行の競合のため、ユーザーの負荷がほとんどまたはまったくない時間帯にインデックスのメンテナンス(およびその他のメンテナンスタスク)をスケジュールすることをお勧めします。
通常、大規模なインデックスメンテナンスオペレーションは、ビジネスでの使用が最小限の深夜に行われます。タスクのビジネスクリティカルな制約を知らないまま、メンテナンス期間中にデータベースに対して実行されている非クリティカルなクエリが多すぎる場合は、データベースを強制的にsingle_userモードにすることができます。もちろんこれが他の問題を引き起こさないと仮定すると、システム全体に依存します。