【问题标题】:In T-SQL, is it possible for update statements to a parent table and a child table to deadlock?在T-SQL中,父表和子表的更新语句是否可能死锁?
【发布时间】:2012-03-31 02:59:15
【问题描述】:

如果 SQL Server 2008r2 数据库同时接收到子表和父表(由外键约束相关)的更新语句,更新语句是否会造成死锁情况?

基于 cmets 的注意事项:这种情况下更新的字段不是关键字段,它们只是计数器字段。

谢谢。

【问题讨论】:

  • 没有。死锁需要共享依赖。
  • 是的,我相信如果外键约束引用的值本身被更新修改是可能的。他们是吗?为了清楚起见,我建议为您的问题场景共享表架构。
  • @bnieland 我认为 PK FK 关系是共享依赖关系。
  • 我已经看到了死锁,其中一个查询是 select,并且涉及到 FK。两次更新似乎很容易实现。
  • @Blam,您当然是对的,但主键的更改非常罕见,尤其是使用合成键时。

标签: sql-server sql-server-2008 tsql


【解决方案1】:

是的,你可以。这是证据:

--setup
use tempdb;
create table Parent (
    ParentID int not null, 
    constraint PK_Parent primary key clustered (ParentId)
);
insert into Parent values (1), (2), (3);
create table Child (
    ChildId int identity, 
    constraint PK_Child primary key clustered (ChildId),
    ParentId int, 
    constraint FK_Child_Parent foreign key (ParentId) 
        references Parent (ParentId)
);
insert into Child (ParentId) values (2), (2), (3);

--in window 1
use tempdb;
begin tran;
update Child set ParentId = 1 where ParentId = 3;


--in window 2
use tempdb;
begin tran;
update Parent set ParentId = 4 where ParentId = 1;

--back in window 1
update Child set ParentId = 4 where ParentId = 2;

我对此进行了测试,并且能够产生死锁。

【讨论】:

  • 问题陈述中没有这样的排除。抛开实用主义不谈,这可能会发生。
  • 是的——只是不太常见
  • 不错的答案。如果您要更新不是主键的字段,会发生这种情况吗?
  • 使用单个语句的 begin tran 的目的是什么? +1
  • @Blam:没有显式事务,这是创建死锁的竞争条件。本质上,我必须在窗口二中提交语句,以使窗口一中的第一条语句完成而第二条语句未启动。我没那么好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-02
  • 2018-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多