SQL Server 2000死锁

时间:2009-06-01 22:45:48

标签: sql-server sql-server-2000 deadlock

我们在生产SQL Server 2000数据库中遇到了一些非常烦人的死锁情况。

主要设置如下:

  • SQL Server 2000企业版。
  • 服务器使用ATL OLE数据库以C ++编码。
  • 正在通过存储过程访问所有数据库对象。
  • 所有UPDATE / INSERT存储过程将其内部操作包装在BEGIN TRANS ... COMMIT TRANS块中。

我在互联网上的几篇文章之后收集了SQL Profiler的一些初始跟踪,例如this one忽略它指的是SQL Server 2005工具,相同的原则适用)。 从跟踪中看,它似乎是两个UPDATE查询之间的死锁。

我们采取了一些措施可能会减少问题发生的可能性:

  • SELECT WITH(NOLOCK)。我们已经更改了存储过程中的所有SELECT查询以使用WITH(NOLOCK)。我们理解脏读的含义,但被查询的数据并不重要,因为我们进行了大量的自动刷新,在正常情况下,UI将具有正确的值。
  • READ UNCOMMITTED 。我们已将服务器代码上的事务隔离级别更改为READ UNCOMMITED。
  • 减少交易范围。我们减少了交易的持续时间,以最大限度地减少发生数据库死锁的可能性。

我们也质疑我们在大多数存储过程中都有一个事务(BEGIN TRANS ... COMMIT TRANS块)。在这种情况下,我的猜测是事务隔离级别是SERIALIZABLE,对吧?那么,如果我们在源代码中指定了一个调用存储过程的事务隔离级别,那么应用哪个?

这是一个处理密集型应用程序,我们正在为数据库进行大量读取(更高百分比)和一些写入。

如果这是一个SQL Server 2005数据库,我可以使用Geoff Dalgas answer on an deadlock issue concerning Stack Overflow ,如果这甚至适用于我遇到的问题。但是,目前升级到SQL Server 2005并不是一个可行的选择。

由于这些初步尝试失败,我的问题是:你会如何离开这里?你会采取什么步骤来减少甚至避免发生死锁,或者我应该使用哪些命令/工具更好地揭露问题?

4 个答案:

答案 0 :(得分:1)

一些评论:

  1. 存储过程中显式指定的隔离级别会覆盖调用者的隔离级别。

  2. 如果sp_getapplock在2000上可用,我会使用它:

    http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/06/30/855.aspx

  3. 在许多情况下,可序列化的隔离级别会增加陷入僵局的可能性。

  4. 2000年的一个很好的资源:

    http://www.code-magazine.com/article.aspx?quickid=0309101&page=1

  5. Bart Duncan的一些建议也许适用:

    http://blogs.msdn.com/bartd/archive/2006/09/09/747119.aspx

答案 1 :(得分:0)

除了Alex的回答:

  • 注视代码以查看是否以相同的顺序访问表。我们最近做了这个,然后将代码重新排序给父母然后孩子。系统已经发展,代码和功能更复杂,用户更多:我们只是开始陷入僵局。

- 查看交易是否可以缩短(例如,稍后开始,提前完成,减少处理)

  • 确定您不想失败的代码,并在其他代码中使用SET DEADLOCK PRIORITY LOW 我们已经使用了这个(SQL 2005在这里有更多选项)来确保某些代码永远不会死锁并牺牲其他代码。

  • 如果你在事务开始时有SELECT准备一些东西,可以考虑使用HOLDLOCK(可能是UPDLOCK)来保持锁定持续时间。我们偶尔会使用它,所以请停止其他进程在此表上写入。

答案 2 :(得分:0)

我的猜测是你遇到了死锁:

  1. 因为您的DML(可能更新)语句正在升级到表锁,或
  2. 不同的存储过程在事务中访问相同的表,但顺序不同。
  3. 为了解决这个问题,我首先检查存储过程,并确保修改语句具有所需的索引。

    注意:这适用于目标表和源表(尽管NOLOCK,UPDATE的源表也会获得锁定。检查用户存储过程扫描的查询计划。与批量或批量操作不同,大多数用户查询和放大器; DML可以处理表行的一个小子集,因此不应该锁定整个表。

    然后,我会检查存储过程,以确保存储过程中的所有数据访问都以一致的顺序完成(Parent - > Child通常是首选)。

答案 3 :(得分:0)

我的设置方案中出现死锁的原因是在所有索引之后。我们使用(默认生成)non clustered索引作为表的主键。更改为clustered索引可解决问题。