死锁 - 锁定列而没有数据

Flo*_*ian 5 sql sql-server database-deadlocks

我执行此存储过程时遇到死锁:

-- Delete transactions
delete from ADVICESEQUENCETRANSACTION
where ADVICESEQUENCETRANSACTION.id in (
  select TR.id from ADVICESEQUENCETRANSACTION TR
  inner join ACCOUNTDESCRIPTIONITEM IT on TR.ACCOUNTDESCRIPTIONITEMID = IT.id
  inner join ACCOUNTDESCRIPTION ACC on IT.ACCOUNTDESCRIPTIONID = ACC.id
  inner join RECOMMENDATIONDESCRIPTION RD on ACC.RECOMMENDATIONDESCRIPTIONID = RD.id
  inner join RECOMMENDATION REC on REC.id = RD.RECOMMENDATIONID
  inner join ADVICESEQUENCE ADV on ADV.id = REC.ADVICESEQUENCEID
  where adv.Id = @AdviceSequenceId AND (@RecommendationState is NULL OR @RecommendationState=REC.[State])
    );
Run Code Online (Sandbox Code Playgroud)

这是表的架构:

表格的架构

这是死锁图:

在此输入图像描述

你可以在这里看到死锁图的细节

因此,当我检索ressource节点的associatedobjid时,我确定它是主键和表AdviceSequenceTransaction的索引:

SELECT OBJECT_SCHEMA_NAME([object_id]), * ,
OBJECT_NAME([object_id]) 
FROM sys.partitions 
WHERE partition_id = 72057595553120256 OR partition_id = 72057595553316864;

SELECT name FROM sys.indexes WHERE object_id = 31339176 and (index_id = 1 or index_id = 4)
Run Code Online (Sandbox Code Playgroud)

PK_AdviceSequenceTransaction IX_ADVICESEQUENCEID_ADVICE

由于关键字ParentTransactionId和关键主键上的表AdviceSequenceTransaction存在关系,因此我在ParentTransactionId列上创建了一个索引.

我没有死锁了.但问题是我不知道为什么没有更多的死锁: - /

而且,在测试它的数据集上,ParentTransactionId中没有数据.全部都是NULL.

那么,即使在ParentTransactionId中没有数据(null),SQL Server是否可以访问主键?

另一件事是我想删除delete语句中的连接:

delete from ADVICESEQUENCETRANSACTION
where ADVICESEQUENCETRANSACTION.id in (
  select TR.id from ADVICESEQUENCETRANSACTION TR
  inner join ACCOUNTDESCRIPTIONITEM IT on TR.ACCOUNTDESCRIPTIONITEMID = IT.id
  inner join ACCOUNTDESCRIPTION ACC on IT.ACCOUNTDESCRIPTIONID = ACC.id
  inner join RECOMMENDATIONDESCRIPTION RD on ACC.RECOMMENDATIONDESCRIPTIONID = RD.id
  inner join RECOMMENDATION REC on REC.id = RD.RECOMMENDATIONID
  inner join ADVICESEQUENCE ADV on ADV.id = REC.ADVICESEQUENCEID
  where adv.Id = @AdviceSequenceId AND (@RecommendationState is NULL OR @RecommendationState=REC.[State])
    );
Run Code Online (Sandbox Code Playgroud)

进入:

delete from ADVICESEQUENCETRANSACTION
where ADVICESEQUENCETRANSACTION.id in (
  select TR.id from ADVICESEQUENCETRANSACTION TR
  inner join ACCOUNTDESCRIPTIONITEM IT on TR.ACCOUNTDESCRIPTIONITEMID = IT.id
  inner join ACCOUNTDESCRIPTION ACC on IT.ACCOUNTDESCRIPTIONID = ACC.id
  inner join RECOMMENDATIONDESCRIPTION RD on ACC.RECOMMENDATIONDESCRIPTIONID = RD.id
  inner join RECOMMENDATION REC on REC.id = RD.RECOMMENDATIONID
  where TR.AdviceSequenceId = @AdviceSequenceId AND (@RecommendationState is NULL OR @RecommendationState=REC.[State])
    );
Run Code Online (Sandbox Code Playgroud)

我删除了最后一次加入.但如果我这样做,我又陷入了僵局!在这里,我不知道为什么......

谢谢你的启发:)

Kam*_*ami 0

如果您不介意脏读,一种方法是对表 ADVICESEQUENCETRANSACTION TR 使用WITH (nolock)。