2016-12-26 114 views
1

我是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 
+0

你可以检查wait_type信息?你可以从sys.dm_exec_requests表中得到它。 –

回答

2

它看起来像你正在尝试使用的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; 

注:holdlock是一样的serializable