依赖多个更新语句中的死锁

时间:2019-02-12 09:48:46

标签: sql-server tsql transactions

在SP中,三个表在单个事务中被更新。这些更新相互依赖。但是在此更新过程中间歇性发生死锁。它不是一贯地发生,而是断断续续地发生。

正在调用WCF服务,该服务将调用SP。 SP的输入是XML。通过OPENXML方法对XML进行解析,并将其值用于更新表。

@Table是一个表变量,由OPENXML在应用SP的输入XML时填充。输入的XML仅包含一个ID。

<A>
  <Value>XYZ</Value>
  <ID>1</ID>
</A>

BEGIN TRAN
--update Table1  
Update Table1
Set ColumnA = A.value
JOIN @Table A
ON Table1.ID = A.ID

--update Table2    
Update Table2
Set ColumnA = Table1.ColumnA
JOIN Table1
ON Table1.ID = Table2.ID

--update Table3
Update Table3
Set ColumnA = Table1.ColumnA
JOIN Table1
ON Table1.ID = Table3.ID

COMMIT TRAN

在表1中,ID列是主键。 在表2中的“ ID”列中,没有可用的索引。

有时在更新Table2时会发生死锁。

收到错误消息“事务(进程ID为100)在另一个资源上已在锁资源上死锁,并且已被选择为死锁受害者。重新运行事务。”

需要解决此间歇性死锁问题的建议。

1 个答案:

答案 0 :(得分:0)

死锁通常是由于查询的数据多于查询所需要的。查询和索引调整可帮助确保仅查询和锁定查询所需的数据,从而减少并发会话的阻塞和死锁的可能性。

由于您的查询在没有其他条件的情况下加入了ID,因此该列上的索引可以帮助避免UPDATEDELETE语句接触其他行。从您的评论中可以看出,table2 ID列上没有索引,因此执行了聚集索引扫描。扫描不仅导致性能欠佳,而且在并发会话竞争同一行时可能导致阻塞和死锁。

ID上添加非聚集索引将计划从完整聚集索引扫描更改为非聚集索引查找。如果不能消除,这应该减少甚至消除死锁,并且也可以大大提高性能。我想说性能和并发性是齐头并进的,这对于数据修改语句而言尤其重要。