Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 了解特定类型的死锁_Sql Server_Deadlock_Sql Server 2016 - Fatal编程技术网

Sql server 了解特定类型的死锁

Sql server 了解特定类型的死锁,sql-server,deadlock,sql-server-2016,Sql Server,Deadlock,Sql Server 2016,我试图理解一种特定类型的死锁是如何产生的 我有一个非常简单的死锁图,有两个资源和两个进程。一个运行SELECT,另一个运行UPDATE语句。我知道在某些情况下,这可能会导致死锁,但我不明白在这种特定场景中它是如何发生的 受害者的查询: 选择id\u粒子、id\u事件、dt\u创建、dt\u rcvd、tlx\u no、from\u routename、re、deleted 从msg_列表 去哪里_routename=@P0 和((dt_answ为NULL,b_complete=0,id_even

我试图理解一种特定类型的死锁是如何产生的

我有一个非常简单的死锁图,有两个资源和两个进程。一个运行
SELECT
,另一个运行
UPDATE
语句。我知道在某些情况下,这可能会导致死锁,但我不明白在这种特定场景中它是如何发生的

受害者的查询:

选择id\u粒子、id\u事件、dt\u创建、dt\u rcvd、tlx\u no、from\u routename、re、deleted
从msg_列表
去哪里_routename=@P0
和((dt_answ为NULL,b_complete=0,id_event=6)或(id_event=10,deleted=0)
或者(从_id_post=9705,删除=0))
由dt_创建的ASC订购
获胜者的查询:

更新消息列表
设置
ID_事件=7,
状态='已回答',
这句话的意思是:{ts'2017-02-1205:34:14'
其中ID_PARTICLE=46211816
完整的死锁图:


选择id_粒子,id_事件,dt_创建,dt_rcvd,tlx_no,from_routename,re,deleted from msg_列表,其中to_routename=@P0和((dt_answ为NULL,b_complete=0,id_事件=6)或(id_事件=10,deleted=0)或(from_id_post=9705,deleted=0))按dt_创建为
Proc[数据库Id=2对象Id=-1260316328]
不为人知
不为人知
不为人知
更新msg_列表集合ID_事件=7,状态为“已应答”,DT_ANSW={ts'2017-02-12 05:34:14'其中ID_粒子=46211816
及其图形表示:

下面是运行这两个查询时生成的查询计划:

受害者:

获胜者:

受害者使用的
ncci\u rcvd\u列表
索引是一个非聚集覆盖索引,包含一个键列和多个包含列。其中一个包含列由获胜者更新。键列不更新

mgs_list
表有大约500000条记录。由
SELECT
查询返回的结果集通常只有几行,比如十几行左右(尽管有时可能会大到几千行)

有人能解释一下这种情况是如何导致僵局的吗


这是从一个经常发生这种情况的生产系统中捕获的。我通过将事务隔离级别更改为读取提交的快照解决了这一问题,这不再是一个问题,但我想了解那里发生了什么,然后再看看是否有不同的解决方案。

第155679页归
IX模式下处理319282ACA8
(更新),S模式下处理30AA42D468(选择)需要。第396658页由S模式下的选择所有,IX模式下更新需要

问题是两个查询都缺少索引。更新使用了一个索引,但没有覆盖,因此需要在聚集索引中查找RID。SELECT是一个扫描(由页面级别的S锁提供…)。这保证了并发情况下的死锁

这是将表误用为队列的另一个示例。读取。将状态与事件分开。仅对事件进行排队和出列


另外,“牺牲品”将始终是回滚工作量较少的事务,在读操作与写操作中,这将始终是读操作。此外,我怀疑您发布的选择执行计划实际上是死锁的。

您能否将执行计划粘贴为xml和Share?顺便问一句,该表上是否有更新触发器?是的,确实存在一个该表上的简单更新触发器。它更新另一个数据库中统计表中的记录。否则读取链接的文档…除非该文档中包含该文档,您能解释为什么您认为select是一个扫描,而计划是“false”吗?select语句毕竟有一个覆盖索引,这就是我每次得到的计划我手动运行该查询。@RemusRusanu:您是如何识别的,数据库上有一个更新触发器table@TheGameiswar从执行堆栈帧。
为什么您认为select是扫描
页面级别的锁定通常是由扫描引起的。但是,正确的情况可能在
ncci\u rcv\u列表上
(我看不到资源上的
indexname
,但我认为页面锁不会发布所有者索引名,只发布对象)。如果是
ncci\u rcv\u列表
,它必须涵盖更新后更新的
dt\u answ
,解释ncci上的死锁。