【问题标题】:How to refactor this deadlock issue?如何重构这个死锁问题?
【发布时间】:2015-03-31 03:10:15
【问题描述】:

我在短时间内多次遇到死锁问题synchronizing 一张表。同步是指执行以下操作:

  1. 将要同步的数据插入到临时表中
  2. 更新目标表中的现有记录
  3. 将新记录插入到目标表中
  4. 删除某些条件下不在同步表中的记录 情况
  5. 删除临时表

对于INSERTDELETE 语句,我使用了类似于:

INSERT INTO destination_table (fk1, fk2, val1)
FROM #tmp
LEFT JOIN destination_table dt ON dt.fk1 = #tmp.fk1
   AND dt.fk2 = #temp.fk2
WHERE dt.pk IS NULL;

死锁图报告destination_table 的主键处于排他锁下。我假设上述查询导致表或页锁而不是行锁。我该如何确认?

我可以使用INEXISTEXCEPT 命令重写上述查询。是否有其他重构代码的方法?使用这些命令中的任何一个进行重构会避免死锁问题吗?哪一个是最好的?我假设EXCEPT

【问题讨论】:

  • 这一切都是在一个事务中完成的吗?您使用的是什么事务隔离级别?是否有其他活动使用目标表?

标签: sql-server tsql sql-server-2005 deadlock


【解决方案1】:

在正常情况下,我可以很好地执行场景。下面给出的是我创建的测试脚本。你在尝试别的吗?

drop table #destination_table
drop table #tmp

Declare @x int=0

create table #tmp(fk1 int, fk2 int, val int)

set @x=2

while (@x<1000)
begin
    insert into #tmp
    select @x,@x,100
    set @x=@x+3
end

create table #destination_table(fk1 int, fk2 int, val int)
while (@x<1000)
begin
    insert into #destination_table
    select @x,@x,100
    set @x=@x+1
end



INSERT INTO #destination_table (fk1, fk2, val)
select t.*
FROM #tmp t
LEFT JOIN #destination_table dt ON dt.fk1 = t.fk1
     AND dt.fk2 = t.fk2
WHERE dt.fk1 IS NULL

【讨论】:

  • 由于您的测试仅使用从单个连接访问的本地临时表,因此产生死锁的可能性很小
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-28
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
相关资源
最近更新 更多