3

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

  1. Insert sp在 X 表中插入数据。
  2. Delete sp删除 X 表中的数据。

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

更新

Read/Write deadlock,我认为由于以下语句而出错。

  • 在插入语句中,它获取 id(聚集索引),然后是非聚集索引。
  • 在 delete 语句中,它在 id 之前获取非聚集索引。

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

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

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

谢谢,

4

5 回答 5

4

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

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

于 2009-07-24T04:52:10.677 回答
0

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

如果您正在删除和插入,那么这会影响聚集索引,并且表上的每个非聚集索引也需要插入/删除。所以死锁肯定是很有可能发生的。我将首先查看您的聚集索引是什么 - 例如,尝试为您的聚集索引设置一个代理键。

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

于 2009-07-25T13:14:57.077 回答
0

存储过程是否修改了任何内容,或者只是进行读取?如果修改某些内容,是否有关于更新的 where 子句足够细化?如果您可以尝试以较小的批次更新行,SQL Server 死锁的可能性较小,因为它只会锁定少量索引,而不是整个索引。

如果可能的话,你可以在这里发布死锁的代码吗?如果存储过程太长,您可以在其中发布违规语句(如果您知道它们是哪些)?

于 2009-07-24T04:13:58.337 回答
0

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

于 2009-07-24T04:30:50.410 回答
0

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

正如 Remus 所发布的,在索引级别也会发生同样的情况。他链接的文章提供了很好的解释,但不幸的是,没有人想知道解决方案,因为每种情况都没有一个最佳解决方案。

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

于 2009-07-24T04:34:11.137 回答