【问题标题】:Concurrent create or select statement failing with deadlock error并发创建或选择语句因死锁错误而失败
【发布时间】:2018-02-09 17:06:54
【问题描述】:

当前运行以下 SQL 语句的位置(可能同时运行 30 或 40 次)并给我们带来死锁错误,但我们不确定哪些语句相互干扰。除了 PK 和 Fk 到 ThingTypes 表之外,Things 表上没有索引。我们还想知道向 ThingTypeId 和 HourId 添加索引是否有助于解决问题。最后,我们还可以安全地假设 {@thingTypeID 和 @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

我们一直在追查这个问题一段时间,因此感谢您提供任何帮助。

【问题讨论】:

  • 旁白:Scope_Identity() 几乎总是比@@Identity 更好的选择。您还可以使用 OUTPUT 子句从行中获取任何数据(注意复数。),例如新插入行的标识列值。 OUTPUT 可以与 INSERTUPDATEDELETEMERGE 一起使用,并且在 @ 的情况下提供对 beforeafter 值的访问987654332@。一个非常值得放在口袋里的工具。

标签: sql-server tsql transactions deadlock


【解决方案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;

【讨论】:

    猜你喜欢
    • 2017-06-14
    • 1970-01-01
    • 2022-07-07
    • 2021-07-16
    • 2010-12-03
    • 2023-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多