SQL 2008中关于插入和更新的死锁

时间:2011-03-25 12:19:11

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

我在并发用户的插件上遇到死锁。我开火的sp相对简单

SET NOCOUNT ON;

begin try
    begin tran

    DECLARE @idoc INT
    declare @ProcessedResponse table (
      candidateInstanceID  int,
      assessmetID          int,
      sectionID            int,
      itemID               int,
      clientID             int,
      displayTypeID        int,
      respondedAt          datetime,
      responseTime         float,
      marksObtained        float,
      processedresponseXML xml,
      resultDescription    varchar(255),
      reportedIssue        bit )

    -- insert into @PartialResponse 
    EXEC sp_xml_preparedocument
      @idoc OUTPUT,
      @Processed_Responses

    insert into @ProcessedResponse
    SELECT *
    FROM   OPENXML(@idoc, '/Processed_Responses/Processed_Response', 1)
              WITH (Candidate_Instance_ID int,
                    Assessment_ID         int,
                    Section_ID            int,
                    Item_ID               int,
                    Client_ID             int,
                    Display_Type_ID       int,
                    Responded_At          datetime,
                    Response_Time         float,
                    Marks_Obtained        float,
                    Processed_XML         text,
                    Result_Description    text,
                    Reported_Issue        bit)

    INSERT INTO Processed_Response
                (Candidate_Instance_ID,
                 Assessment_ID,
                 Section_ID,
                 Client_ID,
                 Item_ID,
                 Display_Type_ID,
                 Responded_At,
                 Response_Time,
                 Marks_Obtained,
                 Processed_XML,
                 Result_Description,
                 Reported_Issue)
    SELECT pr.candidateInstanceID,
           pr.assessmetID,
           pr.sectionID,
           pr.clientID,
           pr.itemID,
           pr.displayTypeID,
           cast(pr.respondedAt as datetime),
           pr.responseTime,
           case pr.marksObtained
             when 0 then null
             else pr.marksObtained
           end,
           CAST(pr.processedresponseXML AS XML),
           pr.resultDescription,
           pr.reportedIssue
    FROM   @ProcessedResponse pr

    update pr
    set    pr.Client_ID = a.Assessment_Owner
    from   Processed_Response pr
           join Assessment a
             on pr.Assessment_ID = a.Assessment_Id
    where  pr.Candidate_Instance_ID = @Candidate_Instance_ID

    update Candidate_Instance
    set    Instance_Status = 'Completed',
           Instance_End_Time = GETDATE()
    where  Candidate_Instance_Id = @Candidate_Instance_ID

    commit tran
end try

begin catch
    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT @ErrorMessage = ERROR_MESSAGE(),
           @ErrorSeverity = ERROR_SEVERITY(),
           @ErrorState = ERROR_STATE();

    rollback tran

    -- Use RAISERROR inside the CATCH block to return error
    -- information about the original error that caused
    -- execution to jump to the CATCH block.
    RAISERROR (@ErrorMessage,-- Message text.
               @ErrorSeverity,-- Severity.
               @ErrorState -- State.
    );
end catch  

任何人都可以帮助我谢谢。

1 个答案:

答案 0 :(得分:0)

它需要两位代码才能死锁,所以同样的代码死锁本身也是如此?如果不知道表结构和索引用法,很难诊断出来。是你的update-select(update pr...)表扫描并锁定整个表?等

毫无疑问,我会将BEGIN TRANS移到INSERT INTO Processed_Response之前,您不需要将所有局部变量填充到事务中。保持您的交易尽可能短。

设置SQL Server Profiler并得到一个死锁图跟踪,你会看到两个相互碰撞的SQL,并从那里开始。