暂停索引重建

ami*_*min 6 index sql-server sql-server-2012

在 SQL Server 2012 中,索引重建作业需要很长时间(最多 8 小时)。然而,甚至没有完成一次索引重建,所以我停止了索引作业。

在监控 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
Run Code Online (Sandbox Code Playgroud)

提前感谢您提供任何有用的信息。

Tho*_*ger 7

您的索引重建未完成的原因是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
Run Code Online (Sandbox Code Playgroud)

现在,如果一个会话正在执行查询,并且它保持锁打开(我使用的是更新查询而不是提交事务):

use TestDB;
go

begin tran;

    update dbo.ConcurrencyTest
    set some_int = 2
    where id = 7;

--commit tran;
Run Code Online (Sandbox Code Playgroud)

如果另一个会话尝试在该表上重建聚集索引:

use TestDB;
go

alter index PK_ConcurrencyTest_Id
on dbo.ConcurrencyTest
rebuild;
go
Run Code Online (Sandbox Code Playgroud)

它将被初始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;
Run Code Online (Sandbox Code Playgroud)

我的输出如下所示:

在此处输入图片说明

正如您在此处看到的,我的ALTER INDEX ... REBUILD命令被UPDATE查询阻止。请求锁是完成此操作Sch-M所需的锁OBJECT

由于这种并发冲突,建议在用户负载很少或没有的时段内安排索引维护(以及其他维护任务)。


Kah*_*ahn 0

我们通常将较大的索引维护操作安排在业务使用最少的午夜进行。在不了解任务的关键业务约束的情况下,您可能希望强制数据库进入 single_user 模式,以防在维护期间对数据库运行太多非关键查询。当然,假设这不会导致其他问题,这取决于整个系统。