DBK*_*DBK 7 sql-server deadlock sql-server-2016
我有 SQL Server 2016 SP2 (13.0.5237.0)。这是我最近在系统中注意到的死锁图。死锁优先级高的进程被选为牺牲品(可能是因为与其他进程相比日志使用率高)。但这不应该发生。这是 SQL 中引入的缺陷吗?有没有办法防止死锁优先级高的进程成为受害者?这是死锁xml:
<deadlock>
<victim-list>
<victimProcess id="process1d3ea515848" />
</victim-list>
<process-list>
<process id="process1d3ea515848" taskpriority="10" logused="5800" waitresource="OBJECT: 9:290100074:0 " waittime="4711" ownerId="359850034" transactionname="user_transaction" lasttranstarted="2019-07-31T08:12:25.267" XDES="0x1d2f62d1840" lockMode="Sch-M" schedulerid="3" kpid="10320" status="suspended" spid="52" sbid="0" ecid="0" priority="5" trancount="4" lastbatchstarted="2019-07-31T08:13:30.990" lastbatchcompleted="2019-07-31T08:13:29.427" lastattention="1900-01-01T00:00:00.427" clientapp=".Net SqlClient Data Provider" hostname="XXX" hostpid="14944" loginname="NT AUTHORITY\SYSTEM" isolationlevel="read committed (2)" xactid="359850034" currentdb="9" currentdbname="XXX" lockTimeout="4294967295" clientoption1="673415200" clientoption2="128056">
<executionStack>
<frame procname="CreatePartition" line="30" stmtstart="2052" stmtend="2218" sqlhandle="0x03000900d670d75323ec7f0094aa000001000000000000000000000000000000000000000000000000000000">
ALTER PARTITION FUNCTION... </frame>
<frame procname="CreatePartitions" line="26" stmtstart="1618" stmtend="1788" sqlhandle="0x030009000f95cb5424ec7f0094aa000001000000000000000000000000000000000000000000000000000000">
EXEC CreatePartition </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 9 Object Id = 1422628111] </inputbuf>
</process>
<process id="process1d4593028c8" taskpriority="0" logused="0" waitresource="METADATA: database_id = 9 DATA_SPACE(data_space_id = 65601), lockPartitionId = 0" waittime="21105" ownerId="359870992" transactionname="sqlsource_transform" lasttranstarted="2019-07-31T08:14:29.460" XDES="0x1d4911c8de0" lockMode="Sch-S" schedulerid="4" kpid="5052" status="suspended" spid="93" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2019-07-31T08:14:29.460" lastbatchcompleted="2019-07-31T08:14:29.447" lastattention="1900-01-01T00:00:00.447" clientapp=".Net SqlClient Data Provider" hostname="XXX" hostpid="14944" loginname="NT AUTHORITY\SYSTEM" isolationlevel="read committed (2)" xactid="359870992" currentdb="9" currentdbname="XXX" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="GetXXX" line="17" stmtstart="-1" sqlhandle="0x03000900abe7e85629eb7f0094aa000001000000000000000000000000000000000000000000000000000000">
CREATE PROC [dbo].[GetXXX]
AS
BEGIN
SET NOCOUNT ON;
SELECT ... </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 9 Object Id = 1458104235] </inputbuf>
</process>
</process-list>
<resource-list>
<objectlock lockPartition="0" objid="290100074" subresource="FULL" dbid="9" objectname="TableXXX" id="lock1d4eeca4f80" mode="Sch-S" associatedObjectId="290100074">
<owner-list>
<owner id="process1d4593028c8" mode="Sch-S" />
</owner-list>
<waiter-list>
<waiter id="process1d3ea515848" mode="Sch-M" requestType="wait" />
</waiter-list>
</objectlock>
<metadatalock subresource="DATA_SPACE" classid="data_space_id = 65601" dbid="9" lockPartition="0" id="lock1d48e40dc00" mode="Sch-M">
<owner-list>
<owner id="process1d3ea515848" mode="Sch-M" />
</owner-list>
<waiter-list>
<waiter id="process1d4593028c8" mode="Sch-S" requestType="wait" />
</waiter-list>
</metadatalock>
</resource-list>
</deadlock>
Run Code Online (Sandbox Code Playgroud)
死锁优先级高的进程被选为受害者...
我之前在维护操作中遇到过这种情况 - 特别是索引重组,如我的博客中所述:SQL Server 中的死锁受害者选择 - 异常?
在那种情况下,我能够重现该问题,当与具有最低死锁优先级 (-10) 的进程发生死锁时,将具有最高死锁优先级 (10) 的进程选为受害者。
有没有办法防止死锁优先级高的进程成为受害者?
我知道的唯一解决方案是避免在用户活动繁重时执行这些操作(分区切换、更改分区功能、索引维护)。最好在某种维护窗口期间。
似乎在选择死锁受害者的方式中有一些内部因素,即“知道”其中一个操作是维护任务,并且以某种方式进行了硬编码,以将其选择为非维护用户查询的受害者。以上只是我的观察,只是推测。
...可能是因为与其他进程相比,日志使用率高
就其价值而言,这实际上与通常选择死锁受害者的方式相反。日志使用率较高的进程不会被选为受害者,因为它需要更多的工作来回滚它。
Stack Overflow 上也有一个与您类似的有趣示例,这意味着获取SCH-M锁是问题的一部分(考虑到我们正在讨论的操作类型,这是有道理的):Why would SQL Server's SET DEADLOCK_PRIORITY HIGH not受到尊重?