并发创建或选择语句失败并出现死锁错误

时间:2018-02-09 17:06:55

标签: sql-server tsql transactions deadlock

当前运行以下SQL语句(可能同时运行30或40次)并且给我们发生死锁错误但我们不确定哪些语句相互干扰。除了PK和Fk到ThingTypes表之外,Things表上没有索引。我们还想知道是否向ThingTypeId和HourId添加索引将有助于解决问题。最后,我们也可以安全地假设{@ somethingTypeID和@hourID}对于所有并发查询都是唯一的,而if仅在以后重新运行时才会存在。

  

事务(进程ID 237)在锁资源上与另一个进程发生死锁,并被选为死锁牺牲品。重新运行交易

代码:

IF NOT EXISTS(select top(1) id from [eddsdbo].[Things] (UPDLOCK) 
              where [ThingTypeID] = @thingTypeID and [HourID] = @hourID)
BEGIN
    INSERT INTO [eddsdbo].[Things]
            ([ThingTypeID]
            ,[HourID])
        VALUES
            (@thingTypeID
            ,@hourID)

    SELECT m.*, mt.SampleType 
    FROM [eddsdbo].[Things] as m
    inner join [eddsdbo].[ThingTypes] as mt on mt.Id = m.ThingTypeID
    WHERE m.ID = @@IDENTITY
END
ELSE
BEGIN
    SELECT m.*, mt.SampleType 
    FROM [eddsdbo].[Things] as m
    inner join [eddsdbo].[ThingTypes] as mt on mt.Id = m.ThingTypeID
    where [ThingTypeID] = @thingTypeID and [HourID] = @hourID
END

我们一直在追讨这个问题,所以感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

不确定这会解决它 但是你真的需要WHERE m.ID = @@IDENTITY

吗?
IF NOT EXISTS(select top(1) id from [eddsdbo].[Things] (UPDLOCK) 
              where [ThingTypeID] = @thingTypeID and [HourID] = @hourID)
BEGIN
    INSERT INTO [eddsdbo].[Things]
               ([ThingTypeID], [HourID])
        VALUES (@thingTypeID,  @hourID)
END

SELECT m.*, mt.SampleType 
FROM [eddsdbo].[Things] as m
inner join [eddsdbo].[ThingTypes] as mt 
  on mt.Id = m.ThingTypeID
 and [ThingTypeID] = @thingTypeID 
 and [HourID] = @hourID

单一陈述是交易
我认为这会减少开销

DECLARE @t AS TABLE (id int identity primary key, thingTypeID  int, hourID  int);
declare @thingTypeID int = 1, @hourID int = 2;

insert into @t (thingTypeID, hourID)  
values (@thingTypeID, @hourID);
select * 
from @T 
where thingTypeID = @thingTypeID and hourID = @hourID;

insert into @t (thingTypeID, hourID)
       select @thingTypeID, @hourID 
       where not exists (select 1 from @t where thingTypeID = @thingTypeID and hourID = @hourID);
select * 
from @T 
where thingTypeID = @thingTypeID and hourID = @hourID;

set @thingTypeID = 1;
set @hourID = 3;
insert into @t (thingTypeID, hourID)
       select @thingTypeID, @hourID  
       where not exists (select 1 from @t where thingTypeID = @thingTypeID and hourID = @hourID);
select * 
from @T 
where thingTypeID = @thingTypeID and hourID = @hourID;

select * 
from @T 
order by id;