簡體   English   中英

使用自引用外鍵的死鎖

[英]Deadlock Using self-referential foreign key

使用 SQL 服務器 2005:我有一個具有自引用外鍵的表。

當此表上的更新和插入同時發生但僅在以下情況下發生時,會發生死鎖:

  • 更新發生在第 1 次
  • 更新是針對插入語句的外鍵引用的記錄

在更新期間,在主鍵上創建一個 X 鎖,主鍵是表的聚集索引。 我已經嘗試了幾件事來嘗試防止這種情況發生,例如:

  • 我嘗試過更改事務隔離級別
  • 提供表格提示,即 WITH(nolock)
  • 我嘗試在表的主鍵上創建一個非聚集索引,以便可以使用它來代替聚集索引。

外鍵需要在那里,所以刪除它不是一種選擇。 關於如何防止阻止插入的鎖或允許插入圍繞鎖工作的任何建議都會非常有幫助。

謝謝。

您是否嘗試過通過 BEGIN TRANSACTION 和 COMMIT 分隔 UPDATE 和 INSERT 事務。 這樣你就可以遠離僵局。

類似的東西;

BEGIN TRANSACTION insert
  <INSERT SQL>
  COMMIT TRANSACTION insert
  BEGIN TRANSACTION update
     <UPDATE SQL>
  COMMIT TRANSACTION update
END

當發現一條記錄符合UPDATE條件時,將在其上放置一個X鎖(或其頁面等,具體取決於引擎選擇的鎖定粒度)。

這可以防止將S鎖放在需要檢索其值的受影響資源上。

由於向子表中插入值需要對照父表進行檢查,因此INSERT語句必須等到UPDATE事務提交或回滾。

如果您將PRIMARY KEY非集群,則UPDATE不應影響它(除非您正在更新PRIMARY KEY本身,在正常情況下您不應該這樣做),因此INSERT將成功。

以下命令對我有用:

交易一:

CREATE TABLE parent (id INT NOT NULL PRIMARY KEY NONCLUSTERED, value INT NOT NULL, parentId INT REFERENCES parent)

INSERT
INTO    parent
VALUES  (1, 1, NULL)

BEGIN TRANSACTION
UPDATE  parent
SET     value = 2
WHERE   id = 1

交易2:

INSERT
INTO    parent
VALUES  (2, 1, 1)

請提供 DDL 和您的UPDATE / INSERT語句我無法重現。

CREATE TABLE T
(
id int identity(1,1) primary key,
refid int references T(id),
filler char(10)
)

INSERT INTO T (refid)
select number 
FROM master..spt_values where number between 1 and 2248

連接 1

BEGIN TRAN
UPDATE T SET filler = 'A' WHERE id=500  

連接 2

BEGIN TRAN
INSERT INTO T (refid) VALUES (500) /*Blocked - No deadlock*/

我最近遇到了同樣的問題。 正如這篇文章中提到的,我的解決方案是簡單地在自引用列(而不是 pk)上添加一個索引。 之后,僵局就徹底消失了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM