2011-03-25 45 views
1

我正在爲併發用戶插入我的表上發生死鎖。我正在發射的sp是相對簡單的插入和更新SQL 2008中的死鎖

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 

任何人都可以幫助我,謝謝。

+0

'Processed_Response'與'Candidate_Instance'有外鍵關係嗎?這些表上有哪些索引?如果'Processed_Response.Client_ID'上沒有索引,則應該添加一個。 – 2011-03-25 14:08:07

+0

這真的是代碼嗎?因爲在你顯示的代碼中,'@ Candidate_Instance_ID'永遠不會被初始化。 – 2011-03-25 15:54:42

+0

@Damien OP提到這是一個sp - 我認爲這是一個參數 – 2011-03-25 16:12:45

回答

0

它需要兩位代碼才能死鎖,所以這個代碼是否自己死鎖?不知道表結構和索引用法很難診斷。是你的更新 - 選擇(update pr...)表掃描並鎖定整個表?等

毫無疑問,我會把BEGIN TRANS移動到INSERT INTO Processed_Response之前,你不需要把所有的局部變量的東西放在事務中。儘可能縮短交易時間。

設置了SQL Server Profiler並獲得了一個死鎖圖形跟蹤,你會看到兩個相互碰撞的SQL,並從那裏開始。