我遇到了由 FK 鏈引起的死鎖問題ON DELETE CASCADE。情況如下:
表C有ON DELETE CASCADEFK 到B.
表B有ON DELETE CASCADEFK 到A.
一個或多個請求進來,導致 SQL Statement(s) DELETE FROM A where A.id = @0 AND A.userId = @1。
然而,由于級聯的 FK,為每個DELETE陳述句生成了一個龐大的執行計劃,一些操作員請求X/IX鎖定B/ C。
當多個洗掉陳述句嘗試同時執行此操作時,會發生死鎖。
有沒有辦法解決這個問題,而無需將一大堆洗掉方法(DB 使用幾個這樣的 FK,不知道它可能會出現這種情況)重寫為手動洗掉相關表的 SP?
任何幫助表示贊賞。
uj5u.com熱心網友回復:
您的問題是子表上的外鍵沒有索引,因此DELETE父表上的每個都需要掃描整個子表以確保沒有 FK 一致性問題。這似乎是導致死鎖的原因。
將索引添加到每個孩子:
CREATE NONCLUSTERED INDEX IX_Parent ON Child (ParentID);
要么
CREATE CLUSTERED INDEX IX_Parent ON Child (ParentID, SomeOtherCol);
所有主鍵和外鍵都必須有一個索引(這些列作為前導鍵列)。
如果您缺少外鍵上的索引,那么您將在父表的主鍵上遇到鎖定UPDATE問題DELETE。如果您缺少主鍵上的索引,那么您將遇到子表上的INSERT鎖定問題。UPDATE
我注意到您的大多數表甚至沒有聚集索引,只是堆表,這是另一個壞主意。
您可以添加其他列作為鍵的一部分或作為 INCLUDE,但 PK 或 FK必須是索引中的前導列。
你可以在這個 fiddle中看到索引的效果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/447368.html
