连续两次执行delete+insert Into为什么会死锁??

时间:2021-01-15 01:11:41

internal bool AddPendingRloc(Entity.Fun.PendRlocRQ pendRloc, out Message message)
        {
            message = new Message();

            tbMOE_PendRloc db = IDABkgFolder.GetPendRloc(pendRloc.SourceSystem, pendRloc.SourceRef, pendRloc.OwnerTeam);
            tbMOE_PendRloc pr = new tbMOE_PendRloc()
            {
                UpdateBy = pendRloc.OwnerStaff,
                OwnerStaff = pendRloc.OwnerStaff,
                CreateBy = pendRloc.OwnerStaff,
                CreateOn = Now,
                DepartDate = pendRloc.DepartDate,
                NoOfTkt = pendRloc.NoOfYkt,
                Passengers = pendRloc.Passengers,
                SourceRef = pendRloc.SourceRef,
                SourceSystem = pendRloc.SourceSystem,
                UpdateOn = Now,
                OwnerTeam = pendRloc.OwnerTeam,
            };
            if (pr.Passengers.Length > 500)
            {
                pr.Passengers = pr.Passengers.Substring(0, 500);
            }
           // IDABkgFolder.UpdatePendRloc(pr);
            return IDABkgFolder.UpdatePendRloc(pr);
    }


public bool Update(tbMOE_PendRloc updateEntity)
        {
            Delete(updateEntity.SourceRef, updateEntity.OwnerTeam);
            return Add(updateEntity);
        }

public bool Delete(string pnr, string team)
        {
            FilterParams fp = new FilterParams();
            fp.AddParam(tbMOE_PendRloc.Fields.SourceRef, pnr, Enums.Relation.Equal, Enums.Expression.AND);
            fp.AddParam(tbMOE_PendRloc.Fields.OwnerTeam, team, Enums.Relation.Equal, Enums.Expression.AND);
            return base.Delete(fp);
        }

 public new bool Add(tbMOE_PendRloc entity)
        {
            return base.Add(entity);
        }

如果我把不打开注释,执行不会发生死锁,反之,就会。为什么呢
前面已经开启事务,而select也加了with(updlock)
求求大家帮帮忙了

14 个解决方案

#1


updlock 已经造成了执行语句的串行化了吧?

#2


引用 1 楼 fredrickhu 的回复:
updlock 已经造成了执行语句的串行化了吧?

就是啊,都串行化了,为什么还会死锁呢?

#3


不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。

而且.NET的事务是啥级别的我没研究过,但是,我知道,如果一个人在调试程序,断点停在.Net 事务里,抱歉,所有人对数据库的访问都等着去吧...

#4


引用 3 楼 spiritofdragon 的回复:
不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。

而且.NET的事务是啥级别的我没研究过,但是,我知道,如果一个人在调试程序,断点停在.Net 事务里,抱歉,所有人对数据库的访问都等着去吧...


第二句话,我深有体会
但是对于第一句不太明白。。

#5


引用 3 楼 spiritofdragon 的回复:
不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。

而且.NET的事务是啥级别的我没研究过,但是,我知道,如果一个人在调试程序,断点停在.Net 事务里,抱歉,所有人对数据库的访问都等着去吧...


事物的本质ACID之一就是对数据的锁定,
跟在哪里开事物和哪种数据库没有什么关系,
一样会对记录加锁,其他人对数据库的访问当然被阻塞,没有什么不妥的

只是说,正常情况下执行事务造成的阻塞(时间短,感觉不明显)没有断点停在事物里造成的影响那么明显而已

#6


至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的


#7


引用 6 楼 x_wy46 的回复:
至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的



恩恩,理解理解。
但还是希望大家帮忙解答一下我的问题呢 连续两次执行delete+insert Into为什么会死锁??

#8


引用 7 楼 u010167016 的回复:
Quote: 引用 6 楼 x_wy46 的回复:

至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的



恩恩,理解理解。
但还是希望大家帮忙解答一下我的问题呢 连续两次执行delete+insert Into为什么会死锁??


事务相关的代码段要执行完成,即便是报错,在异常捕获中也要执行rollback,
别开启事务后,中间有代码报错,你停下来不管了,
这样就不会出现你说的现象了

#9


引用 8 楼 x_wy46 的回复:
Quote: 引用 7 楼 u010167016 的回复:

Quote: 引用 6 楼 x_wy46 的回复:

至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的



恩恩,理解理解。
但还是希望大家帮忙解答一下我的问题呢 连续两次执行delete+insert Into为什么会死锁??


事务相关的代码段要执行完成,即便是报错,在异常捕获中也要执行rollback,
别开启事务后,中间有代码报错,你停下来不管了,
这样就不会出现你说的现象了

是有固定的数据的,每次都会执行Update,也不会报异常,但就是连续执行就会出现死锁了。

#10


连续两次执行delete+insert Into为什么会死锁??
没人。结贴了。。

#11


打开跟踪标志1204,自动记录死锁的详细信息到SQL日志中,以便分析死锁原因..

#12


引用 11 楼 ap0405140 的回复:
打开跟踪标志1204,自动记录死锁的详细信息到SQL日志中,以便分析死锁原因..

好的好的

#13


抓个死锁图看看吧

#14


 internal bool AddPendingRloc(Entity.Fun.PendRlocRQ pendRloc, out Message message)
        {
            message = new Message();

            tbMOE_PendRloc db = IDABkgFolder.GetPendRloc(pendRloc.SourceSystem, pendRloc.SourceRef, pendRloc.OwnerTeam);

            tbMOE_PendRloc pr = new tbMOE_PendRloc()
            {
                UpdateBy = pendRloc.OwnerStaff,
                OwnerStaff = pendRloc.OwnerStaff,
                CreateBy = pendRloc.OwnerStaff,
                CreateOn = Now,
                DepartDate = pendRloc.DepartDate,
                NoOfTkt = pendRloc.NoOfYkt,
                Passengers = pendRloc.Passengers,
                SourceRef = pendRloc.SourceRef,
                SourceSystem = pendRloc.SourceSystem,
                UpdateOn = Now,
                OwnerTeam = pendRloc.OwnerTeam,
            };
            if (pr.Passengers.Length > 500)
            {
                pr.Passengers = pr.Passengers.Substring(0, 500);
            }
            
            if (db != null)
            {
                if (pr.NoOfTkt == 0)
                {
                    IDABkgFolder.DeletePendLoc(db.SourceRef, db.OwnerTeam);
                    return true;
                }
                else
                {
                    pr.CreateBy = db.CreateBy;
                    pr.CreateOn = db.CreateOn;
                   return IDABkgFolder.UpdatePendRloc(pr);
                }
            }
            else
            {
                return IDABkgFolder.AddPendRloc(pr);
            }
        }
  
这是原本的代码。
好吧,我来为自己做下总结。以下只是个人水平的总结,也为自己做下解决问题的记录。欢迎大家的批评与错误指出,也欢迎交流。
首先来看回问题代码的流程是:
1.开启事务
2.首先是GetPendRloc
3.然后根据pendRloc参数得到一个新的pr
大家可以看到如果执行UpdatePendRloc操作,其实也是先执行Delete然后再执行Insert操作( 连续两次执行delete+insert Into为什么会死锁??不要问我为什么要这样操作)
4.根据判断执行不同操作。

先放上一张锁类型的图 连续两次执行delete+insert Into为什么会死锁??
可以看到,U锁与U锁和X锁都是冲突的

所以回到问题上,相对于本问题来说,如果把注释的代码打开,其实与上面的GetPendRloc(加了updlock)差不多(本人觉得 连续两次执行delete+insert Into为什么会死锁??)

本人做过测试,如果执行原本代码,GetPendRloc(加的是NoLock),也没有注释的那段代码,是不会出现死锁的。

本问题里,增加的记录与删除的记录在数据库里是一模一样的
所以我自己总结了以下两句话
1.每一条记录在插入的时候已经记录了相对于该表的特定行号。
2.如果增加新的记录和删除旧的记录是完全一模一样的(包括索引),是不会产生死锁的。

declare @i int
set @i=50

while @i>0
begin

begin tran 
waitfor delay '00:00:0.1'
select * from moe_test.dbo.MOE_PendRloc with(nolock) where SourceSystem='AIR' and SourceRef='7FEMRO' and OwnerTeam='SHD'
waitfor delay '00:00:0.1'
delete  moe_test.dbo.MOE_PendRloc where SourceSystem='AIR' and SourceRef='7FEMRO' and OwnerTeam='SHD'
waitfor delay '00:00:0.1'
insert into moe_test.dbo.MOE_PendRloc select * from moe.dbo.MOE_PendRloc where SourceSystem='AIR' and SourceRef='7FEMRO' and OwnerTeam='SHD' 

commit tran
set @i=@i-1
end

我开了3个会话用以上的SQL来测试,没死锁

然后改成
select  with(UpdLock)

测试就锁发生死锁了
spid   dbid   ObjId       IndId  Type Resource                         Mode     Status
------ ------ ----------- ------ ---- -------------------------------- -------- ------
57     51     0           0      DB                                    S        GRANT
57     80     0           0      DB                                    S        GRANT
57     51     1076198884  0      PAG  1:16568                          IU       GRANT
57     51     1076198884  0      PAG  1:49337                          IU       GRANT
57     51     1076198884  0      RID  1:16568:11                       U        WAIT
57     51     1076198884  0      PAG  1:72482                          IU       GRANT
57     51     1076198884  0      PAG  1:6642                           IU       GRANT
57     51     1076198884  0      PAG  1:6649                           IU       GRANT
57     51     1076198884  0      PAG  1:6651                           IU       GRANT
57     51     1076198884  0      PAG  1:6650                           IU       GRANT
57     51     1076198884  0      PAG  1:56307                          IU       GRANT
57     51     1076198884  0      PAG  1:15939                          IU       GRANT
57     51     1076198884  0      PAG  1:15938                          IU       GRANT
57     51     1076198884  0      PAG  1:15937                          IU       GRANT
57     51     1076198884  0      PAG  1:15936                          IU       GRANT
57     51     1076198884  0      PAG  1:15940                          IU       GRANT
57     51     1076198884  0      PAG  1:15931                          IU       GRANT
57     51     1076198884  0      PAG  1:15930                          IU       GRANT
57     51     1076198884  0      PAG  1:15928                          IU       GRANT
57     51     1076198884  0      PAG  1:15935                          IU       GRANT
57     51     1076198884  0      PAG  1:15933                          IU       GRANT
57     51     1076198884  0      PAG  1:15932                          IU       GRANT
57     51     1076198884  0      TAB                                   IX       GRANT
57     51     1076198884  0      PAG  1:48823                          IU       GRANT

68     80     0           0      DB                                    S        GRANT
68     51     0           0      DB                                    S        GRANT
68     51     1076198884  0      PAG  1:49337                          IU       GRANT
68     51     1076198884  0      PAG  1:16568                          IU       GRANT
68     51     1076198884  0      RID  1:16568:11                       U        GRANT
68     51     1076198884  0      PAG  1:72482                          IU       GRANT
68     51     1076198884  0      PAG  1:56307                          IU       GRANT
68     51     1076198884  0      PAG  1:6650                           IU       GRANT
68     51     1076198884  0      PAG  1:6651                           IU       GRANT
68     51     1076198884  0      PAG  1:6649                           IU       GRANT
68     51     1076198884  0      PAG  1:15937                          IU       GRANT
68     51     1076198884  0      PAG  1:15938                          IU       GRANT
68     51     1076198884  0      PAG  1:6642                           IU       GRANT
68     51     1076198884  0      PAG  1:15939                          IU       GRANT
68     51     1076198884  0      PAG  1:15932                          IU       GRANT
68     51     1076198884  0      PAG  1:15933                          IU       GRANT
68     51     1076198884  0      PAG  1:15935                          IU       GRANT
68     51     1076198884  0      PAG  1:15928                          IU       GRANT
68     51     1076198884  0      PAG  1:15930                          IU       GRANT
68     51     1076198884  0      PAG  1:15931                          IU       GRANT
68     51     1076198884  0      PAG  1:15940                          IU       GRANT
68     51     1076198884  0      PAG  1:15936                          IU       GRANT
68     51     1076198884  0      PAG  1:48823                          IU       GRANT
68     51     1076198884  0      TAB                                   IX       GRANT

74     51     0           0      DB                                    S        GRANT
74     80     0           0      DB                                    S        GRANT
74     51     1076198884  0      PAG  1:16568                          IU       GRANT
74     51     1076198884  0      PAG  1:72482                          IU       GRANT
74     51     1076198884  0      RID  1:16568:11                       U        WAIT
74     51     1076198884  0      PAG  1:49337                          IU       GRANT
74     51     1076198884  0      PAG  1:56307                          IU       GRANT
74     51     1076198884  0      TAB                                   IX       GRANT
74     51     1076198884  0      PAG  1:48823                          IU       GRANT

可以看到有两个U锁确实是处于wait的状态。
select with(Updlock)      select with(Updlock)     select with(Updlock)
                  |                                          |                                       |
             Delete                              Delete                              Delete
                  |                                          |                                       |
              Insert                                 Insert                              Insert
套上死锁理论:例如A B互抢
A        B
|          |
B        A
可以发现是有可能发生死锁的。
以上只是本人目前水平的结论。有错的地方希望有心人指出。
还有,本人想更深入的了解Insert 语句的机制,例如包括Insert前和后发生了一些什么操作,或者所加的锁,或者其它等。
有关于这方面的资料可以共享下吗?求赐教 连续两次执行delete+insert Into为什么会死锁??

#1


updlock 已经造成了执行语句的串行化了吧?

#2


引用 1 楼 fredrickhu 的回复:
updlock 已经造成了执行语句的串行化了吧?

就是啊,都串行化了,为什么还会死锁呢?

#3


不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。

而且.NET的事务是啥级别的我没研究过,但是,我知道,如果一个人在调试程序,断点停在.Net 事务里,抱歉,所有人对数据库的访问都等着去吧...

#4


引用 3 楼 spiritofdragon 的回复:
不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。

而且.NET的事务是啥级别的我没研究过,但是,我知道,如果一个人在调试程序,断点停在.Net 事务里,抱歉,所有人对数据库的访问都等着去吧...


第二句话,我深有体会
但是对于第一句不太明白。。

#5


引用 3 楼 spiritofdragon 的回复:
不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。

而且.NET的事务是啥级别的我没研究过,但是,我知道,如果一个人在调试程序,断点停在.Net 事务里,抱歉,所有人对数据库的访问都等着去吧...


事物的本质ACID之一就是对数据的锁定,
跟在哪里开事物和哪种数据库没有什么关系,
一样会对记录加锁,其他人对数据库的访问当然被阻塞,没有什么不妥的

只是说,正常情况下执行事务造成的阻塞(时间短,感觉不明显)没有断点停在事物里造成的影响那么明显而已

#6


至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的


#7


引用 6 楼 x_wy46 的回复:
至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的



恩恩,理解理解。
但还是希望大家帮忙解答一下我的问题呢 连续两次执行delete+insert Into为什么会死锁??

#8


引用 7 楼 u010167016 的回复:
Quote: 引用 6 楼 x_wy46 的回复:

至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的



恩恩,理解理解。
但还是希望大家帮忙解答一下我的问题呢 连续两次执行delete+insert Into为什么会死锁??


事务相关的代码段要执行完成,即便是报错,在异常捕获中也要执行rollback,
别开启事务后,中间有代码报错,你停下来不管了,
这样就不会出现你说的现象了

#9


引用 8 楼 x_wy46 的回复:
Quote: 引用 7 楼 u010167016 的回复:

Quote: 引用 6 楼 x_wy46 的回复:

至于三楼说的“不建议用.NET 事务,你既然开了事务,执行一次后,是不是等于没有 commit ,再执行第二次,是不是就是在等待第一次执行的commint。然而,你的程序里执行第一次时,代码有没有.NET事务的提交。”

.NET事物,跟数据库sql级别事物,没啥本质区别吧,类似操作,换做在数据库中执行,不也是一样的么?




create table t
(
id int,
name varchar(20)
)

insert into t values (1,'AAA')

--执行如下代码,注意不提交
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--新开一个查询窗口执行同样的代码
begin tran
delete from t where id =1
insert into t values (1,'BBB')

--第二个窗口的执行肯定被阻塞,这跟什么形式的事物没什么关系的



恩恩,理解理解。
但还是希望大家帮忙解答一下我的问题呢 连续两次执行delete+insert Into为什么会死锁??


事务相关的代码段要执行完成,即便是报错,在异常捕获中也要执行rollback,
别开启事务后,中间有代码报错,你停下来不管了,
这样就不会出现你说的现象了

是有固定的数据的,每次都会执行Update,也不会报异常,但就是连续执行就会出现死锁了。

#10


连续两次执行delete+insert Into为什么会死锁??
没人。结贴了。。

#11


打开跟踪标志1204,自动记录死锁的详细信息到SQL日志中,以便分析死锁原因..

#12


引用 11 楼 ap0405140 的回复:
打开跟踪标志1204,自动记录死锁的详细信息到SQL日志中,以便分析死锁原因..

好的好的

#13


抓个死锁图看看吧

#14


 internal bool AddPendingRloc(Entity.Fun.PendRlocRQ pendRloc, out Message message)
        {
            message = new Message();

            tbMOE_PendRloc db = IDABkgFolder.GetPendRloc(pendRloc.SourceSystem, pendRloc.SourceRef, pendRloc.OwnerTeam);

            tbMOE_PendRloc pr = new tbMOE_PendRloc()
            {
                UpdateBy = pendRloc.OwnerStaff,
                OwnerStaff = pendRloc.OwnerStaff,
                CreateBy = pendRloc.OwnerStaff,
                CreateOn = Now,
                DepartDate = pendRloc.DepartDate,
                NoOfTkt = pendRloc.NoOfYkt,
                Passengers = pendRloc.Passengers,
                SourceRef = pendRloc.SourceRef,
                SourceSystem = pendRloc.SourceSystem,
                UpdateOn = Now,
                OwnerTeam = pendRloc.OwnerTeam,
            };
            if (pr.Passengers.Length > 500)
            {
                pr.Passengers = pr.Passengers.Substring(0, 500);
            }
            
            if (db != null)
            {
                if (pr.NoOfTkt == 0)
                {
                    IDABkgFolder.DeletePendLoc(db.SourceRef, db.OwnerTeam);
                    return true;
                }
                else
                {
                    pr.CreateBy = db.CreateBy;
                    pr.CreateOn = db.CreateOn;
                   return IDABkgFolder.UpdatePendRloc(pr);
                }
            }
            else
            {
                return IDABkgFolder.AddPendRloc(pr);
            }
        }
  
这是原本的代码。
好吧,我来为自己做下总结。以下只是个人水平的总结,也为自己做下解决问题的记录。欢迎大家的批评与错误指出,也欢迎交流。
首先来看回问题代码的流程是:
1.开启事务
2.首先是GetPendRloc
3.然后根据pendRloc参数得到一个新的pr
大家可以看到如果执行UpdatePendRloc操作,其实也是先执行Delete然后再执行Insert操作( 连续两次执行delete+insert Into为什么会死锁??不要问我为什么要这样操作)
4.根据判断执行不同操作。

先放上一张锁类型的图 连续两次执行delete+insert Into为什么会死锁??
可以看到,U锁与U锁和X锁都是冲突的

所以回到问题上,相对于本问题来说,如果把注释的代码打开,其实与上面的GetPendRloc(加了updlock)差不多(本人觉得 连续两次执行delete+insert Into为什么会死锁??)

本人做过测试,如果执行原本代码,GetPendRloc(加的是NoLock),也没有注释的那段代码,是不会出现死锁的。

本问题里,增加的记录与删除的记录在数据库里是一模一样的
所以我自己总结了以下两句话
1.每一条记录在插入的时候已经记录了相对于该表的特定行号。
2.如果增加新的记录和删除旧的记录是完全一模一样的(包括索引),是不会产生死锁的。

declare @i int
set @i=50

while @i>0
begin

begin tran 
waitfor delay '00:00:0.1'
select * from moe_test.dbo.MOE_PendRloc with(nolock) where SourceSystem='AIR' and SourceRef='7FEMRO' and OwnerTeam='SHD'
waitfor delay '00:00:0.1'
delete  moe_test.dbo.MOE_PendRloc where SourceSystem='AIR' and SourceRef='7FEMRO' and OwnerTeam='SHD'
waitfor delay '00:00:0.1'
insert into moe_test.dbo.MOE_PendRloc select * from moe.dbo.MOE_PendRloc where SourceSystem='AIR' and SourceRef='7FEMRO' and OwnerTeam='SHD' 

commit tran
set @i=@i-1
end

我开了3个会话用以上的SQL来测试,没死锁

然后改成
select  with(UpdLock)

测试就锁发生死锁了
spid   dbid   ObjId       IndId  Type Resource                         Mode     Status
------ ------ ----------- ------ ---- -------------------------------- -------- ------
57     51     0           0      DB                                    S        GRANT
57     80     0           0      DB                                    S        GRANT
57     51     1076198884  0      PAG  1:16568                          IU       GRANT
57     51     1076198884  0      PAG  1:49337                          IU       GRANT
57     51     1076198884  0      RID  1:16568:11                       U        WAIT
57     51     1076198884  0      PAG  1:72482                          IU       GRANT
57     51     1076198884  0      PAG  1:6642                           IU       GRANT
57     51     1076198884  0      PAG  1:6649                           IU       GRANT
57     51     1076198884  0      PAG  1:6651                           IU       GRANT
57     51     1076198884  0      PAG  1:6650                           IU       GRANT
57     51     1076198884  0      PAG  1:56307                          IU       GRANT
57     51     1076198884  0      PAG  1:15939                          IU       GRANT
57     51     1076198884  0      PAG  1:15938                          IU       GRANT
57     51     1076198884  0      PAG  1:15937                          IU       GRANT
57     51     1076198884  0      PAG  1:15936                          IU       GRANT
57     51     1076198884  0      PAG  1:15940                          IU       GRANT
57     51     1076198884  0      PAG  1:15931                          IU       GRANT
57     51     1076198884  0      PAG  1:15930                          IU       GRANT
57     51     1076198884  0      PAG  1:15928                          IU       GRANT
57     51     1076198884  0      PAG  1:15935                          IU       GRANT
57     51     1076198884  0      PAG  1:15933                          IU       GRANT
57     51     1076198884  0      PAG  1:15932                          IU       GRANT
57     51     1076198884  0      TAB                                   IX       GRANT
57     51     1076198884  0      PAG  1:48823                          IU       GRANT

68     80     0           0      DB                                    S        GRANT
68     51     0           0      DB                                    S        GRANT
68     51     1076198884  0      PAG  1:49337                          IU       GRANT
68     51     1076198884  0      PAG  1:16568                          IU       GRANT
68     51     1076198884  0      RID  1:16568:11                       U        GRANT
68     51     1076198884  0      PAG  1:72482                          IU       GRANT
68     51     1076198884  0      PAG  1:56307                          IU       GRANT
68     51     1076198884  0      PAG  1:6650                           IU       GRANT
68     51     1076198884  0      PAG  1:6651                           IU       GRANT
68     51     1076198884  0      PAG  1:6649                           IU       GRANT
68     51     1076198884  0      PAG  1:15937                          IU       GRANT
68     51     1076198884  0      PAG  1:15938                          IU       GRANT
68     51     1076198884  0      PAG  1:6642                           IU       GRANT
68     51     1076198884  0      PAG  1:15939                          IU       GRANT
68     51     1076198884  0      PAG  1:15932                          IU       GRANT
68     51     1076198884  0      PAG  1:15933                          IU       GRANT
68     51     1076198884  0      PAG  1:15935                          IU       GRANT
68     51     1076198884  0      PAG  1:15928                          IU       GRANT
68     51     1076198884  0      PAG  1:15930                          IU       GRANT
68     51     1076198884  0      PAG  1:15931                          IU       GRANT
68     51     1076198884  0      PAG  1:15940                          IU       GRANT
68     51     1076198884  0      PAG  1:15936                          IU       GRANT
68     51     1076198884  0      PAG  1:48823                          IU       GRANT
68     51     1076198884  0      TAB                                   IX       GRANT

74     51     0           0      DB                                    S        GRANT
74     80     0           0      DB                                    S        GRANT
74     51     1076198884  0      PAG  1:16568                          IU       GRANT
74     51     1076198884  0      PAG  1:72482                          IU       GRANT
74     51     1076198884  0      RID  1:16568:11                       U        WAIT
74     51     1076198884  0      PAG  1:49337                          IU       GRANT
74     51     1076198884  0      PAG  1:56307                          IU       GRANT
74     51     1076198884  0      TAB                                   IX       GRANT
74     51     1076198884  0      PAG  1:48823                          IU       GRANT

可以看到有两个U锁确实是处于wait的状态。
select with(Updlock)      select with(Updlock)     select with(Updlock)
                  |                                          |                                       |
             Delete                              Delete                              Delete
                  |                                          |                                       |
              Insert                                 Insert                              Insert
套上死锁理论:例如A B互抢
A        B
|          |
B        A
可以发现是有可能发生死锁的。
以上只是本人目前水平的结论。有错的地方希望有心人指出。
还有,本人想更深入的了解Insert 语句的机制,例如包括Insert前和后发生了一些什么操作,或者所加的锁,或者其它等。
有关于这方面的资料可以共享下吗?求赐教 连续两次执行delete+insert Into为什么会死锁??