如何解决非聚集索引上的插入/删除死锁?

时间:2009-07-24 04:08:55

标签: sql-server deadlock

我遇到了死锁问题,我发现它是由两个不同线程调用的存储过程引起的(2个称为Web服务)。

  1. 插入在X表中插入数据的sp
  2. 删除删除X
  3. 中的数据的

    此外,我得到的结果告诉我在X表的非唯一和非聚集索引中发生的死锁。你有什么想法解决这个问题吗?

    更新

    Read/Write deadlock开始,由于以下陈述,我认为这是错误的。

    • 在insert语句中,它获取id(聚簇索引),然后获得非聚集索引。
    • 在删除语句中,它在id之前获得非聚集索引。

    所以,我需要为删除语句选择id,如下面的语句。

    SELECT id FROM X WITH(NOLOCK) WHERE [condition]
    

    PS。两个存储过程都在事务中调用。

    谢谢,

5 个答案:

答案 0 :(得分:4)

我们必须看到某种代码......你提到了一个交易;它的隔离级别是什么?要尝试的一件事是将(UPDLOCK)提示添加到用于查找行的任何查询(或检查存在);所以你将从一开始就取出写锁(而不是读锁)。

当有争议时,这应该导致(非常短暂的)阻塞而不是死锁。

答案 1 :(得分:0)

存储过程是否会修改任何内容,或者只是执行读取操作?如果修改某些东西,那么更新的条款是否足够粒度?如果您可以尝试以较小批量更新行,则SQL Server不太可能发生死锁,因为它只会锁定少量索引,而不是整个索引。

如果有可能,你可以在这里发布死锁的代码吗?如果存储过程太长,你可以在其中发布有问题的陈述(如果你知道它们是哪个)?

答案 2 :(得分:0)

没有死锁信息更多的是猜测而不是正确答案......可能是类似于read-write deadlock的索引访问顺序问题。

答案 3 :(得分:0)

可能是选择查询是实际问题,特别是如果它们在两个存储过程中是相同的表,但是以不同的顺序。重要的是要记住,从表中读取将创建(共享)锁。您可能希望阅读lock types

同样的情况可能发生在指数级别,正如Remus发布的那样。他联系的The article提供了一个很好的解释,但遗憾的是没有人能够解决这个问题,因为每个案例都没有一个最佳解决方案。

我自己并不是这个领域的专家,但是使用lock hints,您可以确保相同的资源以相同的顺序锁定,从而防止死锁。您可能需要测试人员提供更多信息才能有效地解决这个问题。

答案 4 :(得分:0)

让应用程序恢复正常运行的快速方法是检测死锁错误(1205)并重新运行事务。代码可以在联机丛书的“TRY ... CATCH”部分找到。

如果要删除和插入,那么这会影响聚簇索引,并且表上的每个非聚集索引也需要插入/删除。因此,发生死锁肯定是非常可能的。我将从查看聚簇索引的内容开始 - 例如,尝试使用聚簇索引的代理键。

不幸的是,如果没有更多信息,几乎不可能完全解决你的死锁问题。

罗布