web-dev-qa-db-ja.com

インデックスの再構築が中断されました

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

役立つ情報をお寄せいただきありがとうございます。

5
amin

インデックスの再構築が完了しないのは、LCK_M_SCH_M待機タイプ。インデックスを再構築しようとするとどうなりますか、Sch-M再構築しようとしているオブジェクトに対してロックが要求されています。

以下を参照してください グラフロック互換性

enter image description here

ここでわかるように、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;

出力は次のようになります。

enter image description here

ご覧のとおり、私のALTER INDEX ... REBUILDコマンドはUPDATEクエリによってブロックされています。リクエストロックはSch-Mこの操作を完了するためにOBJECTで必要なロック。

この同時実行の競合のため、ユーザーの負荷がほとんどまたはまったくない時間帯にインデックスのメンテナンス(およびその他のメンテナンスタスク)をスケジュールすることをお勧めします。

7
Thomas Stringer

通常、大規模なインデックスメンテナンスオペレーションは、ビジネスでの使用が最小限の深夜に行われます。タスクのビジネスクリティカルな制約を知らないまま、メンテナンス期間中にデータベースに対して実行されている非クリティカルなクエリが多すぎる場合は、データベースを強制的にsingle_userモードにすることができます。もちろんこれが他の問題を引き起こさないと仮定すると、システム全体に依存します。

0
Kahn