了解特定类型的死锁
我想了解特定类型的死锁是如何发生的。了解特定类型的死锁
我有一个非常简单的死锁图与两个资源和两个进程。一个是运行SELECT
另一个UPDATE
声明。我知道有些情况会导致死锁,但我不明白在这种情况下会发生什么。
被害人查询:
SELECT id_particle, id_event, dt_created, dt_rcvd, tlx_no, from_routename, re, deleted
FROM msg_list
WHERE to_routename = @P0
AND ((dt_answ IS NULL AND b_complete = 0 AND id_event=6) OR (id_event = 10 AND deleted = 0)
OR (from_id_post = 9705 AND deleted = 0))
ORDER BY dt_created ASC
冠军奖金查询:
UPDATE msg_list
SET
ID_EVENT=7,
STATUS='Answered',
DT_ANSW={ts '2017-02-12 05:34:14'
WHERE ID_PARTICLE = 46211816
完整的僵局图:
<deadlock-list>
<deadlock victim="process30aa42d468">
<process-list>
<process id="process30aa42d468" taskpriority="0" logused="0" waitresource="PAGE: 6:1:155679 " waittime="921" ownerId="427175775" transactionname="SELECT" lasttranstarted="2017-02-12T05:34:48.293" XDES="0x3126fbba40" lockMode="S" schedulerid="4" kpid="10648" status="suspended" spid="184" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2017-02-12T05:34:48.293" lastbatchcompleted="2017-02-12T05:34:48.280" lastattention="1900-01-01T00:00:00.280" clientapp="jTDS" hostname="LNS" hostpid="123" loginname="MsgStore" isolationlevel="read committed (2)" xactid="427175775" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="tempdb.dbo.#jtds000003_____________________________________________________________________________________________________________0042FD9D" line="1" stmtstart="92" stmtend="668" sqlhandle="0x030002005819e1b4efce580018a7000001000000000000000000000000000000000000000000000000000000">
SELECT id_particle, id_event, dt_created, dt_rcvd, tlx_no, from_routename, re, deleted FROM msg_list WHERE to_routename = @P0 AND ((dt_answ IS NULL AND b_complete = 0 AND id_event=6) OR (id_event = 10 AND deleted = 0) OR (from_id_post = 9705 AND deleted = 0)) ORDER BY dt_created AS </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 2 Object Id = -1260316328] </inputbuf>
</process>
<process id="process319282aca8" taskpriority="0" logused="21256" waitresource="PAGE: 6:1:396658 " waittime="869" ownerId="427175573" transactionname="implicit_transaction" lasttranstarted="2017-02-12T05:34:48.210" XDES="0x30c2dbc408" lockMode="IX" schedulerid="4" kpid="11980" status="suspended" spid="99" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-02-12T05:34:48.430" lastbatchcompleted="2017-02-12T05:34:48.427" lastattention="2017-02-12T03:34:28.130" clientapp="NotesMover" hostname="LNS" hostpid="8828" loginname="Notesmover" isolationlevel="read committed (2)" xactid="427175573" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="364" stmtend="812" sqlhandle="0x020000006d523b316d15563a50b97ce8d56da3cf6d8fc4450000000000000000000000000000000000000000">
unknown </frame>
<frame procname="adhoc" line="1" stmtend="554" sqlhandle="0x02000000d8b78713c51b1588947edf24f2d7b69031f4f1d60000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
UPDATE msg_list SET ID_EVENT=7, STATUS='Answered', DT_ANSW={ts '2017-02-12 05:34:14'WHERE ID_PARTICLE = 46211816
</inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="155679" dbid="6" subresource="FULL" objectname="MsgStore.dbo.msg_list" id="lock31683f2400" mode="IX" associatedObjectId="72057594523811840">
<owner-list>
<owner id="process319282aca8" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process30aa42d468" mode="S" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="396658" dbid="6" subresource="FULL" objectname="MsgStore.dbo.msg_list" id="lock2f80c2e300" mode="S" associatedObjectId="72057594523811840">
<owner-list>
<owner id="process30aa42d468" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="process319282aca8" mode="IX" requestType="wait"/>
</waiter-list>
</pagelock>
</resource-list>
</deadlock>
</deadlock-list>
和它们的图形表示:
这里是正在运行这两个查询时生成的查询计划:
的受害者:
优胜者:
由受害者使用的ncci_rcvd_list
指数是一个非聚集覆盖索引与单个键柱和几个包含的列。其中一列包括专栏由获胜者更新。关键列未更新。
mgs_list
表有大约500,000条记录。 SELECT
查询返回的结果集通常只有几十行左右(尽管偶尔它可能会更大,可能是几千)。
有人可以解释这种情况如何导致僵局吗?
这是从生产系统捕获的,这种情况发生频率很高。我已经通过将事务隔离级别更改为读取已提交的快照来解决此问题,这不再是问题,但我想了解发生的事情,然后查看是否存在不同的解决方案。
页面155679在IX模式下由process319282aca8
(UPDATE)拥有,并且在S模式下由process30aa42d468
(SELECT)提供。 S在S模式下由SELECT拥有,并且在IX模式下由UPDATE使用。
问题是两个查询都缺少索引。 UPDATE使用索引但没有覆盖,因此需要将RID查找到聚集索引。 SELECT是一个扫描(如页面级锁S给出的...)。这可以保证并发下的死锁。
这是滥用表格作为队列的另一个例子。阅读Using tables as Queues。将你的状态与你的事件分开。仅入队和出队事件。
PS。 '受害者'将始终是回滚较少的事务,并且在读取或写入时,这总是读取。另外,我怀疑你发布的SELECT执行计划是实际死锁的计划。
顺便说一句,您是否有该表上的任何UPDATE触发器? –
是的,该表上确实有一个简单的更新触发器。它更新另一个数据库中统计表中的记录。否则,阅读链接的文档...除非它包含在该文档中,你能解释为什么你认为该选择是扫描并且计划是'假'?毕竟,select语句有一个覆盖索引,这是我每次手动运行该查询时得到的计划。 – IamNaN
@RemusRusanu:您是如何识别的,在执行堆栈框架中存在表格 – TheGameiswar
您可以将执行计划粘贴为xml并共享 – TheGameiswar