如何在SQL Server中对索引约束强制执行键锁

问题描述 投票:0回答:1

我正在处理死锁问题,该问题仅在数据量很大时才会发生。在获取SQL Sentry日志时,我可以看到该锁是SP内下一行中Identity列pk_tab12上的聚集索引(TAB_ID)上的键锁...

DELETE Mytable
OUTPUT deleted.field1, deleted.field2 INTO @temptabledeclaredbeforequery
WHERE TAB_ID = tabID

错误

“错误:1205,严重性:13,状态:51,位于第25行的proc SP_myproc中: 消息:(进程ID 103)已在另一个进程的锁定资源上死锁,并已被选为死锁受害者。

当我看到执行计划时,该索引没有显示任何问题。但是,我计划通过更改为非聚集索引来修复它。我想知道的是,如何在开发环境中重现/强制死锁,以便可以检查修复程序是否有效?

注意:我提供的信息只是一个示例,因为我无法提供实际信息。对不起!

sql sql-server deadlock
1个回答
0
投票

基于提供的信息,我不希望此查询出现死锁,但是它可以与其他并发查询死锁。

死锁很难在高并发工作负载中可靠地重现,但是我通过在不同的SSMS查询窗口中运行死锁中涉及的查询并与sp_getapplock同步执行,从而取得了一些成功,因此它们几乎在同一时刻运行。下面是此技术的示例:

获得会话1的排他锁以同步执行:

EXEC sp_getapplock @Resource = N'deadlock-synch', @LockMode = 'Exclusive', @LockOwner = 'Session';
GO

在会话2上执行查询1,等待释放锁:

EXEC sp_getapplock @Resource = N'deadlock-synch', @LockMode = 'Shared', @LockOwner = 'Session';
GO
--query 1 involved in deadlock
DELETE Mytable
OUTPUT 
deleted.field1
deleted.field2
INTO @temptabledeclaredbeforequery
where TAB_ID = tabID
GO
EXEC sp_releaseapplock @Resource = N'deadlock-synch', @LockOwner = 'Session';
GO

在会话3上执行查询2,等待释放锁:

EXEC sp_getapplock @Resource = N'deadlock-synch', @LockMode = 'Shared', @LockOwner = 'Session';
GO
--query 2 involved in deadlock
SELECT *
FROM MyTable
JOIN YourTable ON YourTable.Column1 = MyTable.Column1;
GO
EXEC sp_releaseapplock @Resource = N'deadlock-synch', @LockOwner = 'Session';
GO

最后,释放会话1的排他锁以开始执行:

EXEC sp_releaseapplock @Resource = N'deadlock-synch', @LockOwner = 'Session';
GO
© www.soinside.com 2019 - 2024. All rights reserved.