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

时间:2011-12-05 18:52:59

标签: sql-server deadlock

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

  

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

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

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

4 个答案:

答案 0 :(得分:104)

  

Q1:执行事务所花费的时间是否会使关联进程更有可能被标记为死锁受害者。

没有。 SELECT是受害者,因为它只读取数据,因此事务与a lower cost相关联,因此被选为受害者:

  

默认情况下,数据库引擎选择作为死锁的受害者   会话运行回滚最便宜的交易。   或者,用户可以指定会话的优先级   使用SET DEADLOCK_PRIORITY语句的死锁情况。   DEADLOCK_PRIORITY可以设置为LOW,NORMAL或HIGH,或者可选   可以设置为范围(-10到10)内的任何整数值。

  

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

没有。有几个原因:

  

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

可能。死锁的原因几乎很可能是一个索引不佳的数据库.10分钟查询在这种狭窄的条件下是可以接受的,我在你的情况下100%确定可以接受。

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

答案 1 :(得分:11)

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

答案 2 :(得分:4)

这里的答案值得一试,但您还应该检查一下代码。特别请阅读Polyfun的答案: How to get rid of deadlock in a SQL Server 2005 and C# application?

它解释了并发问题,以及"如何使用(updlock)"在您的查询中可能会纠正您的死锁情况 - 具体取决于您的代码正在做什么。如果你的代码确实遵循这种模式,那么在诉诸脏读之前,这可能是一个更好的修复方法。

答案 3 :(得分:0)

尽管@ Remus Rusanu已经是一个很好的答案,以防万一人们期望对 SQL Server的死锁原因和跟踪策略有更深入的了解,但我还是建议您阅读< strong> Brad McGehee 的How to Track Down Deadlocks Using SQL Server 2005 Profiler