【问题标题】:Deadlock during insert/update in parallel并行插入/更新期间的死锁
【发布时间】:2017-05-10 22:24:54
【问题描述】:

我是 MS SQL Server 的新手,我正在尝试通过增加出现计数器 (+1) 来更新记录,如果数据丢失或者我用计数器值零“0”新插入它。

此外,我的应用程序并行运行以处理数据数组 a[] 的每个元素。当并行处理数组时,SQL Server 会抛出相同的死锁。虽然我设置了事务隔离级别,但表上发生了相同的死锁。我的应用程序是用 Java/Camel/Hibernate 编写的。

存储过程:

IF(@recordCount = 0 OR @recordCount > 1 )
BEGIN
        IF(@chargeAbbreviation IS NOT NULL)
        BEGIN
            set transaction isolation level READ COMMITTED;
            begin transaction;

                    UPDATE  dbo.SLG_Charge_Abbreviation_Missing_Report WITH (UPDLOCK, HOLDLOCK)
                        SET     dbo.SLG_Charge_Abbreviation_Missing_Report.Occurrence_Count+=1,dbo.SLG_Charge_Abbreviation_Missing_Report.ModifiedAt=GETDATE()
                        WHERE   dbo.SLG_Charge_Abbreviation_Missing_Report.Jurisdiction_ID = @jurisdictionId AND
                                UPPER(dbo.SLG_Charge_Abbreviation_Missing_Report.Charge_Abbreviation) = @chargeAbbreviation AND 
                                (UPPER(dbo.SLG_Charge_Abbreviation_Missing_Report.Statute_Code) = @statuteCode OR (dbo.SLG_Charge_Abbreviation_Missing_Report.Statute_Code IS NULL AND @statuteCode IS NULL)) AND
                                dbo.SLG_Charge_Abbreviation_Missing_Report.Product_Category_id = @productCategoryId
                IF(@@ROWCOUNT = 0)
                BEGIN
                INSERT INTO dbo.SLG_Charge_Abbreviation_Missing_Report VALUES(@OriginalChargeAbbreviation,@jurisdictionId,@OriginalStatuteCode,@productCategoryId,GETDATE(),GETDATE(),1);
                END
            commit
        END
    SELECT TOP 0 * FROM dbo.SLG_Charge_Mapping

END

【问题讨论】:

  • 可以查看wait_type信息吗?您可以从 sys.dm_exec_requests 表中获取它。

标签: java sql-server hibernate stored-procedures apache-camel


【解决方案1】:

您似乎正在尝试使用某些版本的Sam Saffron's upsert method

要在使用holdlock/serializable 时利用Key-Range Locking,您需要有一个涵盖查询中列的索引。

如果您没有涵盖此查询的查询,您可以考虑创建一个这样的查询:

create unique nonclustered index ux_slg_Charge_Abbreviation_Missing_Report_jid_pcid_ca_sc
  on dbo.slg_Charge_Abbreviation_Missing_Report (
      Jurisdiction_id 
    , Product_Category_id
    , Charge_Abbreviation
    , Statute_Code
    );

我不认为这行:set transaction isolation level read committed; 在这种情况下对你有任何帮助。

set nocount on;
set xact_abort on;
if(@recordCount = 0 or @recordCount > 1 )
  begin;
    if @chargeAbbreviation is not null
      begin;
        begin tran;
            update camr with (updlock, serializable)
              set  camr.Occurrence_Count  = camr.Occurrence_Count + 1
                 , camr.ModifiedAt        = getdate()
              from dbo.slg_Charge_Abbreviation_Missing_Report as camr
            where camr.Jurisdiction_id            = @jurisdictionId 
              and camr.Product_Category_id        = @productCategoryId
              and upper(camr.Charge_Abbreviation) = @chargeAbbreviation 
              and (
                  upper(camr.Statute_Code)        = @statuteCode 
                    or (camr.Statute_Code is null and @statuteCode is null)
              ) 
        if @@rowcount = 0
          begin;
          insert into dbo.slg_Charge_Abbreviation_Missing_Report values
            (@OriginalChargeAbbreviation,@jurisdictionId
            ,@OriginalStatuteCode,@productCategoryId
            ,getdate(),getdate(),1);
          end;
        commit tran
      end;
    select top 0  from dbo.slg_Charge_Mapping;
end;

注意:holdlockserializable 相同。

与上述解决方案相关的链接:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2017-10-05
    • 2019-01-14
    • 2019-01-27
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    相关资源
    最近更新 更多