多个`ON DELETE CASCADE`外键导致的死锁

Deadlock caused by multiple `ON DELETE CASCADE` Foreign Keys

我遇到了由 ON DELETE CASCADE FK 链引起的死锁问题。 情况如下:

Table CON DELETE CASCADE FK 到 B.

Table BON DELETE CASCADE FK 到 A.

收到一个或多个请求,导致 SQL 语句 DELETE FROM A where A.id = @0 AND A.userId = @1

然而,由于级联的FK,为每个DELETE语句生成了一个庞大的执行计划,一些操作员请求X/IX锁定B/C.

当多个删除语句同时尝试执行此操作时,会发生死锁。

有没有一种方法可以解决这个问题而无需重写一大堆删除方法(DB 使用了几个这样的 FK,不知道它会变成这样)到 SP 并手动删除相关表?

感谢任何帮助。

你的问题是 child table 上的外键没有索引 ,所以每个 DELETE parent table 需要扫描整个 child table 以确保没有 FK 一致性问题。这似乎是造成死锁的原因。

给每个添加索引 child:

CREATE NONCLUSTERED INDEX IX_Parent ON Child (ParentID);

CREATE CLUSTERED INDEX IX_Parent ON Child (ParentID, SomeOtherCol);

所有主键和外键都有一个索引(以这些列作为前导键列)是必不可少的

如果您缺少外键索引,那么您将在 UPDATEDELETE 上针对 parent table 的主键遇到锁定问题。如果您缺少主键上的索引,那么您将在 INSERTUPDATE 上遇到针对 child table.

的锁定问题

我注意到你的大多数 table 甚至没有聚簇索引,只是堆 table,另一个坏主意。

您可以添加其他列作为键的一部分或作为 INCLUDE,但 PK 或 FK 必须是索引中的前导列

this fiddle可以看到索引的效果。