使用SQL Server 2005:我有一个具有自引用外键的表。
更新&此表上的插入同时发生,但仅限于以下条件:
在更新期间,在主键上创建X锁,该主键是表的聚簇索引。我尝试了几种方法来防止这种情况发生,例如:
外键需要存在,因此删除它不是一种选择。关于如何阻止锁定停止插入或允许插入物在锁定周围工作的任何建议都会非常有用。
感谢。
答案 0 :(得分:0)
您是否尝试通过BEGIN TRANSACTION和COMMIT分离UPDATE和INSERT事务。这样你就可以远离死锁。
类似的东西;
BEGIN TRANSACTION insert
<INSERT SQL>
COMMIT TRANSACTION insert
BEGIN TRANSACTION update
<UPDATE SQL>
COMMIT TRANSACTION update
END
答案 1 :(得分:0)
如果发现某条记录符合UPDATE
的条件,则会在其上放置X
锁定(或其页面等,具体取决于引擎选择的锁定粒度)。
这可以防止S
锁定在受影响的资源上,这是检索其值所必需的。
由于将值插入子表需要针对父表进行检查,因此INSERT
语句必须等到UPDATE
事务提交或回滚。
如果您使PRIMARY KEY
非群集,UPDATE
不应该影响它(除非您正在更新PRIMARY KEY
本身,在正常情况下您不应该这样做),所以{ {1}}会成功。
以下命令对我有用:
交易1:
INSERT
交易2:
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 :(得分:0)
请提供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
BEGIN TRAN
UPDATE T SET filler = 'A' WHERE id=500
BEGIN TRAN
INSERT INTO T (refid) VALUES (500) /*Blocked - No deadlock*/
答案 3 :(得分:0)
我最近碰到了同样的问题。正如this post中提到的,我的解决方案是在自引用列(而不是pk)上添加索引。在那之后,死锁完全消失了。