死锁优先级高被选为死锁受害者

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)

Jos*_*ell 8

死锁优先级高的进程被选为受害者...

我之前在维护操作中遇到过这种情况 - 特别是索引重组,如我的博客中所述:SQL Server 中的死锁受害者选择 - 异常?

在那种情况下,我能够重现该问题,当与具有最低死锁优先级 (-10) 的进程发生死锁时,将具有最高死锁优先级 (10) 的进程选为受害者。

有没有办法防止死锁优先级高的进程成为受害者?

我知道的唯一解决方案是避免在用户活动繁重时执行这些操作(分区切换、更改分区功能、索引维护)。最好在某种维护窗口期间。

似乎在选择死锁受害者的方式中有一些内部因素,即“知道”其中一个操作是维护任务,并且以某种方式进行了硬编码,以将其选择为非维护用户查询的受害者。以上只是我的观察,只是推测。


...可能是因为与其他进程相比,日志使用率高

就其价值而言,这实际上与通常选择死锁受害者的方式相反。日志使用率较高的进程不会被选为受害者,因为它需要更多的工作来回滚它。


Stack Overflow 上也有一个与您类似的有趣示例,这意味着获取SCH-M锁是问题的一部分(考虑到我们正在讨论的操作类型,这是有道理的):Why would SQL Server's SET DEADLOCK_PRIORITY HIGH not受到尊重?