SQL Server中的死锁简单更新操作

时间:2018-03-28 11:11:09

标签: sql-server sql-server-2012

我有一个像这样的SQL命令:

UPDATE tableName 
SET ColA = @ColA, ColB = @ColB, ColC = @ColC
WHERE ID = @ID

在自己的事务中作为唯一命令执行。这些事务中的多个是从多个程序线程中同时执行的(可能是针对不同的ID),并且在某些未知的情况下,我会遇到死锁:

  

错误:事务(进程ID 372)在锁定时死锁与另一个进程通信缓冲资源并被选为死锁牺牲品。重新运行交易   声明:UPDATE tableName SET ColA = @ ColA,ColB = @ ColB,ColC = @ColC WHERE ID = @ID

查询在大约50种不同的安装/环境上运行,这些死锁只发生在几台选定的机器上。

我在MSDN上发现了这个can be caused by a missing index的帖子,但是ID列是主键。我是否必须在该列上添加另一个索引,如果是,那么哪种类型的索引可以使用?

编辑:这是从管理中检索到的xml_deadlock_report的内容 - >扩展事件 - > System_Health - > package0.event_file:

<deadlock>
 <victim-list>
  <victimProcess id="process3b6651c38" />
 </victim-list>
 <process-list>
  <process id="process3b6651c38" taskpriority="0" logused="0" waitresource="PAGE: 45:1:12951 " waittime="3873" ownerId="35041102" transactionname="UPDATE" lasttranstarted="2018-03-28T09:34:11.700" XDES="0x3bf35dd40" lockMode="U" schedulerid="2" kpid="6972" status="suspended" spid="306" sbid="0" ecid="3" priority="0" trancount="0" lastbatchstarted="2018-03-28T09:34:11.700" lastbatchcompleted="2018-03-28T09:34:11.700" lastattention="1900-01-01T00:00:00.700" clientapp=".Net SqlClient Data Provider" hostname="WSERVER01" hostpid="1984" isolationlevel="read committed (2)" xactid="35041102" currentdb="45" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame procname="adhoc" line="1" stmtstart="66" sqlhandle="0x02000000b14fad3a90dbdc90c36b1078cbce60ffaeefea220000000000000000000000000000000000000000">
UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID    </frame>
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
(@ID nvarchar(152),@ColA int, @ColB int, ColC varchar(30))UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID   </inputbuf>
  </process>
  <process id="process3b2d22188" taskpriority="0" logused="0" waitresource="PAGE: 45:1:42575 " waittime="3874" ownerId="35041102" transactionname="UPDATE" lasttranstarted="2018-03-28T09:34:11.700" XDES="0x27dd93c50" lockMode="U" schedulerid="4" kpid="7572" status="suspended" spid="306" sbid="0" ecid="2" priority="0" trancount="0" lastbatchstarted="2018-03-28T09:34:11.700" lastbatchcompleted="2018-03-28T09:34:11.700" lastattention="1900-01-01T00:00:00.700" clientapp=".Net SqlClient Data Provider" hostname="WSERVER01" hostpid="1984" isolationlevel="read committed (2)" xactid="35041102" currentdb="45" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame procname="adhoc" line="1" stmtstart="66" sqlhandle="0x02000000b14fad3a90dbdc90c36b1078cbce60ffaeefea220000000000000000000000000000000000000000">
UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID    </frame>
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
(@ID nvarchar(152),@ColA int, @ColB int, ColC varchar(30))UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID   </inputbuf>
  </process>
  <process id="process3b2d250c8" taskpriority="0" logused="10000" waittime="3611" schedulerid="3" kpid="1496" status="suspended" spid="317" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-03-28T09:34:11.673" lastbatchcompleted="2018-03-28T09:34:11.673" lastattention="1900-01-01T00:00:00.673" clientapp=".Net SqlClient Data Provider" hostname="WSERVER01" hostpid="1984" loginname="dbUser" isolationlevel="read committed (2)" xactid="35041090" currentdb="45" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame procname="adhoc" line="1" stmtstart="66" sqlhandle="0x02000000b14fad3a90dbdc90c36b1078cbce60ffaeefea220000000000000000000000000000000000000000">
UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID    </frame>
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
(@ID nvarchar(152),@ColA int, @ColB int, ColC varchar(30))UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID   </inputbuf>
  </process>
  <process id="process3b2d24cf8" taskpriority="0" logused="19872" waitresource="PAGE: 45:1:42575 " waittime="3782" ownerId="35041090" transactionname="UPDATE" lasttranstarted="2018-03-28T09:34:11.673" XDES="0x3bf361d40" lockMode="U" schedulerid="3" kpid="2600" status="suspended" spid="317" sbid="0" ecid="4" priority="0" trancount="0" lastbatchstarted="2018-03-28T09:34:11.673" lastbatchcompleted="2018-03-28T09:34:11.673" lastattention="1900-01-01T00:00:00.673" clientapp=".Net SqlClient Data Provider" hostname="WSERVER01" hostpid="1984" isolationlevel="read committed (2)" xactid="35041090" currentdb="45" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame procname="adhoc" line="1" stmtstart="66" sqlhandle="0x02000000b14fad3a90dbdc90c36b1078cbce60ffaeefea220000000000000000000000000000000000000000">
UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID    </frame>
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
(@ID nvarchar(152),@ColA int, @ColB int, ColC varchar(30))UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID   </inputbuf>
  </process>
  <process id="process3b6657498" taskpriority="0" logused="19872" waitresource="PAGE: 45:1:12951 " waittime="3780" ownerId="35041090" transactionname="UPDATE" lasttranstarted="2018-03-28T09:34:11.673" XDES="0x3acb75760" lockMode="U" schedulerid="1" kpid="2748" status="suspended" spid="317" sbid="0" ecid="2" priority="0" trancount="0" lastbatchstarted="2018-03-28T09:34:11.673" lastbatchcompleted="2018-03-28T09:34:11.673" lastattention="1900-01-01T00:00:00.673" clientapp=".Net SqlClient Data Provider" hostname="WSERVER01" hostpid="1984" isolationlevel="read committed (2)" xactid="35041090" currentdb="45" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame procname="adhoc" line="1" stmtstart="66" sqlhandle="0x02000000b14fad3a90dbdc90c36b1078cbce60ffaeefea220000000000000000000000000000000000000000">
UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID    </frame>
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
(@ID nvarchar(152),@ColA int, @ColB int, ColC varchar(30))UPDATE tableName SET ColA=@ColA, ColB=@ColB, ColC=@ColC WHERE ID=@ID   </inputbuf>
  </process>
 </process-list>
 <resource-list>
  <pagelock fileid="1" pageid="12951" dbid="45" subresource="FULL" objectname="dbName.dbo.tableName" id="lock266e05c00" mode="U" associatedObjectId="72057594041663488">
   <owner-list>
    <owner id="process3b2d250c8" mode="U" />
   </owner-list>
   <waiter-list>
    <waiter id="process3b6651c38" mode="U" requestType="wait" />
   </waiter-list>
  </pagelock>
  <pagelock fileid="1" pageid="42575" dbid="45" subresource="FULL" objectname="dbName.dbo.tableName" id="lock2668a9280" mode="U" associatedObjectId="72057594041663488">
   <owner-list>
    <owner id="process3b6657498" mode="U" />
   </owner-list>
   <waiter-list>
    <waiter id="process3b2d22188" mode="U" requestType="wait" />
   </waiter-list>
  </pagelock>
  <exchangeEvent id="Pipe32a7fe700" WaitType="e_waitPipeGetRow" nodeId="2">
   <owner-list>
    <owner id="process3b6657498" />
    <owner id="process3b2d24cf8" />
   </owner-list>
   <waiter-list>
    <waiter id="process3b2d250c8" />
   </waiter-list>
  </exchangeEvent>
  <pagelock fileid="1" pageid="42575" dbid="45" subresource="FULL" objectname="dbName.dbo.tableName" id="lock2668a9280" mode="U" associatedObjectId="72057594041663488">
   <owner-list>
    <owner id="process3b2d22188" mode="U" requestType="wait" />
   </owner-list>
   <waiter-list>
    <waiter id="process3b2d24cf8" mode="U" requestType="wait" />
   </waiter-list>
  </pagelock>
  <pagelock fileid="1" pageid="12951" dbid="45" subresource="FULL" objectname="dbName.dbo.tableName" id="lock266e05c00" mode="U" associatedObjectId="72057594041663488">
   <owner-list>
    <owner id="process3b6651c38" mode="U" requestType="wait" />
   </owner-list>
   <waiter-list>
    <waiter id="process3b6657498" mode="U" requestType="wait" />
   </waiter-list>
  </pagelock>
 </resource-list>
</deadlock>

我可以从中读到什么?

1 个答案:

答案 0 :(得分:2)

听起来好像正在进行锁升级 - 即使您只更新了1行,SQL也会悲观地锁定页面甚至表格。

值得尝试的一个选项是在更新时使用WITH ROWLOCK提示。 理论上,这将仅在效果行上应用锁定。