SQL Server - 聚集索引死锁

4
我有一个表A,它的主键上有一个聚集索引,第二列(act_id)上有一个非聚集索引(指向表B的外键)。两个更新语句会导致死锁,如下图所示:死锁1。这个死锁似乎不是书签查找死锁,因为它在同一个索引和同一个objid上。在非聚集索引中包含主键并没有带来任何成功。我理解objid不是记录id,而是索引中的范围。导致死锁的查询(例如update a set act_id = 1 where act_id = 2),具有以下执行计划:执行计划。有时候同样的死锁也会发生在只有一个聚集索引的另一张表上:另一张表上相同的死锁。有人有什么想法可以避免这种死锁吗?

你的交易里有多个语句吗?你能发一下整个事务的SQL吗? - usr
2个回答

2
两个查询似乎都在更新聚集索引的B-Tree的同一部分。对于这种并发问题,有多种解决方案。一种是获取更快的硬件。另一种是不要有可以更改的主键。
我首先会问你:您是否从2个单独的查询中更新了主键?您是否有自然键?您的主/外键上是否设置了级联更新?您的其他阻止查询是什么?
包括主键在非聚集索引中并没有带来任何成功,因为主键始终存在于所有非聚集索引中,否则如何进行书签查找?

他正在更改一个非主键列。通常,U锁可以防止简单的单行更新产生许多死锁情况。例如,使用主键并发更新同一行永远不会死锁。关于通过非主键列进行更新,我不确定是否也是如此。 - usr
这两个查询是相同类型的(update A set act_id where act_id = XX),可能会有多行记录属于同一个act_id。 - Littlefield

1
感谢您的回答。我画了一张图片,以使其更加清晰:enter image description here 我们有一些任务,每个任务有一个动作。每个动作可以有多个参数。
我们的应用程序由几个部署组成。每个部署都可以上传这些任务。
在示例中,我有三个部署。2个插件和一个基础模块。
2个插件正在等待直到基础模块准备好,然后两个模块都会在自己的事务中调用基础模块中的.upload()。在某一点上,如果任务有更改,则将更新任务。因此,如果两个插件中都有任务更改,则会产生死锁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接