进程成为僵局受害者的原因

Ell*_*ott 94 sql-server deadlock

我有一个选择的过程需要很长时间才能完成,大约需要5到10分钟.
我目前没有使用NOLOCK作为MS SQL数据库引擎的提示.
与此同时,我们有另一个进程在进行更新并插入到同一个数据库和相同的表中.
第一个过程已经开始,最近过早地结束了一条消息

SQLEXCEPTION:事务在锁资源上与另一个进程死锁,并被选为死锁牺牲品.

第一个进程在相同条件但在数据库较小的其他站点上运行,因此所讨论的select语句需要更短的时间(大约30秒左右).在这些其他站点中,我没有在这些其他站点中获得死锁消息.我也没有在最初遇到问题的网站上收到此消息,但是,我认为,随着数据库的增长,我相信我必须超过一些门槛.这是我的问题:

  1. 执行事务所花费的时间是否会使关联进程更有可能被标记为死锁牺牲品.
  2. 如果我用NOLOCK提示执行select,这会解决问题吗?
  3. 我怀疑在select语句中作为WHERE子句的一部分检查的datetime字段导致慢查找时间.我可以根据此字段创建索引吗?这是可取的吗?

Rem*_*anu 114

Q1:执行事务所花费的时间是否会使关联进程更有可能被标记为死锁牺牲品.

不会.SELECT是受害者,因为它只读取数据,因此交易的成本较低,因此被选为受害者:

默认情况下,数据库引擎选择运行事务的会话作为死锁牺牲品,该事务的回滚成本最低.或者,用户可以使用该SET DEADLOCK_PRIORITY语句指定处于死锁情况的会话的优先级.DEADLOCK_PRIORITY可以设置为LOW,NORMAL或HIGH,也可以设置为范围(-10到10)内的任何整数值.

Q2.如果我用NOLOCK提示执行select,这会解决问题吗?

不.有几个原因:

Q3.我怀疑在select语句中作为WHERE子句的一部分检查的datetime字段导致慢查找时间.我可以根据此字段创建索引吗?这是可取的吗?

大概.僵局的原因是几乎很可能是一个索引不佳database.10分钟查询是在这样的条件下窄接受的,我是100%肯定你的情况是不能接受的.

99%的信心我声明你的死锁是由与更新冲突的大型表扫描引起的.首先捕获死锁图以分析原因.您很可能必须优化数据库的架构.在进行任何修改之前,请阅读本主题" 设计索引"和子文章.

  • 查询的长度对*选择死锁牺牲品*没有影响.它确实通过至少两个因素导致死锁有所不同:1)简单概率.查询越长,重组并发更新并陷入死锁的可能性就越大.2)较大的表可能使用完全不同的查询计划,一个易受僵局影响的计划. (4认同)

Ell*_*ott 12

以下是这个特定的死锁问题实际发生的原因以及它是如何实际解决的.这是一个相当活跃的数据库,每天发生130K交易.此数据库中表中的索引最初是聚类的.客户要求我们使索引非聚集.我们一说,僵局就开始了.当我们将索引重新建立为群集时,死锁就会停止.

  • 有人可以解释一下原因吗?(魔术解决方案不是很有帮助) (29认同)
  • 这家伙在他的帖子中解释了这一点:https://www.mssqltips.com/sqlservertip/2517/using-a-clustered-index-to-solve-a-sql-server-deadlock-issue/ (4认同)

Pet*_*ton 5

这里的答案值得一试,但是您也应该查看代码。具体请阅读Polyfun的答案: 如何摆脱SQL Server 2005和C#应用程序中的死锁?

它解释了并发性问题,以及查询中“ with(updlock)”的使用如何纠正您的死锁情况-确实取决于代码在做什么。如果您的代码确实遵循此模式,则在进行脏读等操作之前,这可能是一个更好的解决方法。