Sql server SQL Server意外死锁

Sql server SQL Server意外死锁,sql-server,azure,Sql Server,Azure,我想大多数死锁都是意外的,但即使查看死锁图,我仍然发现死锁是意外的 Azure SQL Server 这张桌子很简单。主键(Id)上的聚集索引,没有其他索引 所有更新都位于由主键标识的单行上 多台服务器可能同时更新表(但通常只有两台) 死锁图图像: 这一个在页面锁上死锁。后来我添加了(rowlock)提示,但仍然会出现死锁,只是在行而不是页面上。我使用这个例子是因为它是我发现的最简单的图形 看起来查询是并行运行的(Exchange事件),不同的并行处理器彼此死锁,但我真的不希望在如此简单的

我想大多数死锁都是意外的,但即使查看死锁图,我仍然发现死锁是意外的

  • Azure SQL Server
  • 这张桌子很简单。主键(Id)上的聚集索引,没有其他索引
  • 所有更新都位于由主键标识的单行上
  • 多台服务器可能同时更新表(但通常只有两台)
死锁图图像:

这一个在页面锁上死锁。后来我添加了(rowlock)提示,但仍然会出现死锁,只是在行而不是页面上。我使用这个例子是因为它是我发现的最简单的图形

看起来查询是并行运行的(Exchange事件),不同的并行处理器彼此死锁,但我真的不希望在如此简单的事情上发生这种情况

死锁图XML:

<deadlock>
  <victim-list>
    <victimProcess id="process228fd04e108" />
  </victim-list>
  <process-list>
    <process id="process228fd04e108" taskpriority="0" logused="0" waitresource="PAGE: 5:1:2288 " waittime="9103" ownerId="2582803" transactionname="UPDATE" lasttranstarted="2020-06-12T12:53:02.807" XDES="0x22776384df0" lockMode="U" schedulerid="2" kpid="45296" status="suspended" spid="123" sbid="0" ecid="1" priority="0" trancount="0" lastbatchstarted="2020-06-12T12:53:02.807" lastbatchcompleted="2020-06-12T12:53:02.803" lastattention="1900-01-01T00:00:00.803" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC5B6ACC6" hostpid="16672" isolationlevel="read committed (2)" xactid="2582803" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x16e67a1e6613ccaa" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="308" sqlhandle="0x02000000035f942bf8a99f27adc04a1730c088079e14a1a90000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
    <process id="process228fd04fc28" taskpriority="0" logused="328" waitresource="PAGE: 5:1:2288 " waittime="6999" ownerId="2582770" transactionname="UPDATE" lasttranstarted="2020-06-12T12:53:02.573" XDES="0x22908ef4960" lockMode="U" schedulerid="2" kpid="54024" status="suspended" spid="122" sbid="0" ecid="2" priority="0" trancount="0" lastbatchstarted="2020-06-12T12:53:02.573" lastbatchcompleted="2020-06-12T12:53:02.570" lastattention="1900-01-01T00:00:00.570" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC5B6ACC6" hostpid="14476" isolationlevel="read committed (2)" xactid="2582770" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x16e67a1e6613ccaa" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="308" sqlhandle="0x02000000035f942bf8a99f27adc04a1730c088079e14a1a90000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
    <process id="process228f451d088" taskpriority="0" logused="10000" waittime="4139" schedulerid="2" kpid="43452" status="suspended" spid="122" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2020-06-12T12:53:02.573" lastbatchcompleted="2020-06-12T12:53:02.570" lastattention="1900-01-01T00:00:00.570" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC5B6ACC6" hostpid="14476" loginname="superuser" isolationlevel="read committed (2)" xactid="2582770" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x16e67a1e6613ccaa" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="308" sqlhandle="0x02000000035f942bf8a99f27adc04a1730c088079e14a1a90000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
  </process-list>
  <resource-list>
    <pagelock fileid="1" pageid="2288" dbid="5" subresource="FULL" objectname="9332623d-7c4f-4da3-b054-9be315e6f0a4.dbo.KeyValue" id="lock228c3bed800" mode="U" associatedObjectId="72057594043826176">
      <owner-list>
        <owner id="process228f451d088" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process228fd04e108" mode="U" requestType="wait" />
      </waiter-list>
    </pagelock>
    <pagelock fileid="1" pageid="2288" dbid="5" subresource="FULL" objectname="9332623d-7c4f-4da3-b054-9be315e6f0a4.dbo.KeyValue" id="lock228c3bed800" mode="U" associatedObjectId="72057594043826176">
      <owner-list>
        <owner id="process228fd04e108" mode="U" requestType="wait" />
      </owner-list>
      <waiter-list>
        <waiter id="process228fd04fc28" mode="U" requestType="wait" />
      </waiter-list>
    </pagelock>
    <exchangeEvent id="Pipe2277614e600" WaitType="e_waitPipeGetRow" waiterType="Coordinator" nodeId="2" tid="0" ownerActivity="sentData" waiterActivity="needMoreData" merging="false" spilling="false" waitingToClose="false">
      <owner-list>
        <owner id="process228fd04fc28" />
      </owner-list>
      <waiter-list>
        <waiter id="process228f451d088" />
      </waiter-list>
    </exchangeEvent>
  </resource-list>
</deadlock>
编辑的实际查询计划:

另一个死锁图,这是添加rowlock提示后的死锁图:

第三幅图:

第三个图形的XML:

<deadlock>
  <victim-list>
    <victimProcess id="process28b6db54108" />
  </victim-list>
  <process-list>
    <process id="process28b6db54108" taskpriority="0" logused="396" waitresource="KEY: 5:72057594043826176 (36d9edc841fc)" waittime="7137" ownerId="1491320" transactionname="UPDATE" lasttranstarted="2020-06-15T09:55:29.570" XDES="0x28b698c9280" lockMode="U" schedulerid="2" kpid="34896" status="suspended" spid="113" sbid="0" ecid="3" priority="0" trancount="0" lastbatchstarted="2020-06-15T09:55:29.570" lastbatchcompleted="2020-06-15T09:55:29.563" lastattention="1900-01-01T00:00:00.563" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC5B6ACC6" hostpid="26324" isolationlevel="read committed (2)" xactid="1491320" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x01068720fbb54c87" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="338" sqlhandle="0x02000000916f1f032e9e459183cba2f8f5cf5fabfffb31b40000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue WITH (rowlock) SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
    <process id="process28b6db544e8" taskpriority="0" logused="796" waitresource="KEY: 5:72057594043826176 (f8db9e67957b)" waittime="14507" ownerId="1491488" transactionname="UPDATE" lasttranstarted="2020-06-15T09:55:31.380" XDES="0x28b698dedf0" lockMode="U" schedulerid="2" kpid="74440" status="suspended" spid="129" sbid="0" ecid="2" priority="0" trancount="0" lastbatchstarted="2020-06-15T09:55:31.380" lastbatchcompleted="2020-06-15T09:55:31.377" lastattention="1900-01-01T00:00:00.377" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC552A9B5" hostpid="4176" isolationlevel="read committed (2)" xactid="1491488" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x01068720fbb54c87" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="338" sqlhandle="0x02000000916f1f032e9e459183cba2f8f5cf5fabfffb31b40000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue WITH (rowlock) SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
    <process id="process28c66eff848" taskpriority="0" logused="796" waitresource="KEY: 5:72057594043826176 (5f732a583b1e)" waittime="7820" ownerId="1491488" transactionname="UPDATE" lasttranstarted="2020-06-15T09:55:31.380" XDES="0x28b69a2fba0" lockMode="U" schedulerid="1" kpid="67308" status="suspended" spid="129" sbid="0" ecid="1" priority="0" trancount="0" lastbatchstarted="2020-06-15T09:55:31.380" lastbatchcompleted="2020-06-15T09:55:31.377" lastattention="1900-01-01T00:00:00.377" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC552A9B5" hostpid="4176" isolationlevel="read committed (2)" xactid="1491488" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x01068720fbb54c87" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="338" sqlhandle="0x02000000916f1f032e9e459183cba2f8f5cf5fabfffb31b40000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue WITH (rowlock) SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
    <process id="process28cf7edd468" taskpriority="0" logused="10000" waittime="4232" schedulerid="1" kpid="50744" status="suspended" spid="129" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2020-06-15T09:55:31.380" lastbatchcompleted="2020-06-15T09:55:31.377" lastattention="1900-01-01T00:00:00.377" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC552A9B5" hostpid="4176" loginname="superuser" isolationlevel="read committed (2)" xactid="1491488" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x01068720fbb54c87" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="338" sqlhandle="0x02000000916f1f032e9e459183cba2f8f5cf5fabfffb31b40000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue WITH (rowlock) SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
    <process id="process28cf7edc8c8" taskpriority="0" logused="10000" waittime="4864" schedulerid="1" kpid="59208" status="suspended" spid="113" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2020-06-15T09:55:29.570" lastbatchcompleted="2020-06-15T09:55:29.563" lastattention="1900-01-01T00:00:00.563" clientapp="Core Microsoft SqlClient Data Provider" hostname="RD501AC5B6ACC6" hostpid="26324" loginname="superuser" isolationlevel="read committed (2)" xactid="1491320" currentdb="5" currentdbname="fp-pinfo-prod-db" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0x01068720fbb54c87" queryplanhash="0xd91db86605a474c5" line="1" stmtstart="150" stmtend="338" sqlhandle="0x02000000916f1f032e9e459183cba2f8f5cf5fabfffb31b40000000000000000000000000000000000000000">
unknown    </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))UPDATE KeyValue WITH (rowlock) SET Value = @p0, TimestampUtc = @p1, Origin = @p2 WHERE Id = @p3   </inputbuf>
    </process>
  </process-list>
  <resource-list>
    <keylock hobtid="72057594043826176" dbid="5" objectname="050344b0-8326-468d-9337-48fedc86da64.dbo.KeyValue" indexname="PK_KeyValue" id="lock28c65e13800" mode="U" associatedObjectId="72057594043826176">
      <owner-list>
        <owner id="process28cf7edd468" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process28b6db54108" mode="U" requestType="wait" />
      </waiter-list>
    </keylock>
    <keylock hobtid="72057594043826176" dbid="5" objectname="050344b0-8326-468d-9337-48fedc86da64.dbo.KeyValue" indexname="PK_KeyValue" id="lock28c68183800" mode="X" associatedObjectId="72057594043826176">
      <owner-list>
        <owner id="process28cf7edc8c8" mode="X" />
        <owner id="process28cf7edc8c8" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process28b6db544e8" mode="U" requestType="wait" />
      </waiter-list>
    </keylock>
    <keylock hobtid="72057594043826176" dbid="5" objectname="050344b0-8326-468d-9337-48fedc86da64.dbo.KeyValue" indexname="PK_KeyValue" id="lock28c683a5700" mode="U" associatedObjectId="72057594043826176">
      <owner-list>
        <owner id="process28cf7edc8c8" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process28c66eff848" mode="U" requestType="wait" />
      </waiter-list>
    </keylock>
    <exchangeEvent id="Pipe28b69a26680" WaitType="e_waitPipeGetRow" waiterType="Coordinator" nodeId="2" tid="0" ownerActivity="sentData" waiterActivity="needMoreData" merging="false" spilling="false" waitingToClose="false">
      <owner-list>
        <owner id="process28b6db544e8" />
        <owner id="process28c66eff848" />
      </owner-list>
      <waiter-list>
        <waiter id="process28cf7edd468" />
      </waiter-list>
    </exchangeEvent>
    <exchangeEvent id="Pipe28b699e0680" WaitType="e_waitPipeGetRow" waiterType="Coordinator" nodeId="2" tid="0" ownerActivity="sentData" waiterActivity="needMoreData" merging="false" spilling="false" waitingToClose="false">
      <owner-list>
        <owner id="process28b6db54108" />
      </owner-list>
      <waiter-list>
        <waiter id="process28cf7edc8c8" />
      </waiter-list>
    </exchangeEvent>
  </resource-list>
</deadlock>

不为人知
不为人知
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))使用(rowlock)SET Value=@p0,TimestampUtc=@p1,Origin=@p2其中Id=@p3更新KeyValue
不为人知
不为人知
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))使用(rowlock)SET Value=@p0,TimestampUtc=@p1,Origin=@p2其中Id=@p3更新KeyValue
不为人知
不为人知
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))使用(rowlock)SET Value=@p0,TimestampUtc=@p1,Origin=@p2其中Id=@p3更新KeyValue
不为人知
不为人知
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))使用(rowlock)SET Value=@p0,TimestampUtc=@p1,Origin=@p2其中Id=@p3更新KeyValue
不为人知
不为人知
(@p0 nvarchar(4000),@p1 datetime2(7),@p2 nvarchar(4000),@p3 nvarchar(4000))使用(rowlock)SET Value=@p0,TimestampUtc=@p1,Origin=@p2其中Id=@p3更新KeyValue

找到了它。简单的错误。您的PK是
varchar(900)
。您的更新发送一个类型为
nvarchar(4000)
的参数
nvarchar
的值高于
varchar
,因此必须将
varchar
值转换为
nvarchar
进行比较。因此,一个微不足道的聚集索引搜索变成了一次扫描。扫描的额外成本导致了并行查询计划以及死锁的可能性

要解决此问题,只需在.NET中使用正确的参数类型或在查询中强制转换即可。乙二醇

UPDATE KeyValue SET Value = @p0, TimestampUtc = @p1, Origin = @p2 
WHERE Id = cast(@p3 as varchar(900))

这将消除并行计划和死锁,并使此查询变得越来越便宜。

找到了它。简单的错误。您的PK是
varchar(900)
。您的更新发送一个类型为
nvarchar(4000)
的参数
nvarchar
的值高于
varchar
,因此必须将
varchar
值转换为
nvarchar
进行比较。因此,一个微不足道的聚集索引搜索变成了一次扫描。扫描的额外成本导致了并行查询计划以及死锁的可能性

要解决此问题,只需在.NET中使用正确的参数类型或在查询中强制转换即可。乙二醇

UPDATE KeyValue SET Value = @p0, TimestampUtc = @p1, Origin = @p2 
WHERE Id = cast(@p3 as varchar(900))


这将消除并行计划和死锁,并使此查询变得越来越便宜。

能否将表和索引DDL添加到问题中?并验证没有触发器或索引视图。以及查询计划(如果可以获得)。在这样一个简单的查询中看到exchangeEvent是很奇怪的。DDL添加到了问题中。添加了更新的执行计划。我们的任何表上都没有触发器或视图,因此这是一个负数。添加了另一个带有XML的图。能否将表和索引DDL添加到问题中?并验证没有触发器或索引视图。以及查询计划(如果可以获得)。在这样一个简单的查询中看到exchangeEvent是很奇怪的。DDL添加到了问题中。添加了更新的执行计划。我们的任何表上都没有触发器或视图,所以这是否定的。添加了另一个带有XML的图。你比我更了解它,尽管表达式是否可搜索取决于排序规则。对,但我相信参数表达式将使用列的排序规则,除非显式指定不同的排序规则。根据此处的规则:@我的意思是,使用Windows列排序规则,如
Latin1\u General\u CI\u AS
,SQL Server可以强制索引查找,即使使用Unicode参数,也可以使用范围查找表达式,如
seek Keys[1]:Start:[tempdb].[dbo].[KeyValue].Id>标量运算符([Expr1005]),End:[tempdb].[dbo].[KeyValue].Id<标量运算符([Expr1006])
。这不会发生在像
SQL\u Latin1\u General\u CP1\u CI\u AS
这样的旧式SQL排序规则中。很好的发现!我已经有了这个:[Key,Column(TypeName=“varchar(900)”]public string Id{get;set;}-但在执行此操作时它被忽略了:const string Sql=“UPDATE KeyValue WITH(rowlock)set Value={0},TimestampUtc={1},Origin={2},其中Id={3}”;等待ctx.Database.ExecuteSqlRawAsync(Sql,值,_dateTimeService.UtcNow,Environment.MachineName,id);还有一件事仍然让我感到惊讶:为什么它在并行运行时会死锁?这真的是意料之中的事吗?你比我抢先一步,尽管这个表达式是否是sargable取决于coll