我有一个像这样的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>
我可以从中读到什么?
答案 0 :(得分:2)
听起来好像正在进行锁升级 - 即使您只更新了1行,SQL也会悲观地锁定页面甚至表格。
值得尝试的一个选项是在更新时使用WITH ROWLOCK提示。 理论上,这将仅在效果行上应用锁定。