2014-08-27 63 views
5

循環可以自鎖嗎?循環可以自鎖嗎?

昨晚測試隊打開了一個奇怪的勾號。 該應用程序有一個網格,用戶可以檢查事件推遲 測試者選擇了兩個事件(IDS:1和5),推遲雙方卻一個沒有拿到狀態更新

我知道[事件]做表必須進行更新和一個新的記錄在[IncidentDetail表 我查詢都與插入喜歡這個:

Id IncidentKindCode TransportEntryId CreateDate    IncidentStatus CloseDate 
-- ---------------- ---------------- ---------------------- -------------- --------- 
1 11301   52    2014-08-26 19:23:21.47 1    NULL 
5 11301   56    2014-08-26 20:06:17.94 0    NULL 

Id IncidentId InsertDate    DetailKind Reason IncidentUser PostponeDate 
-- ----------- ---------------------- ---------- --------- ------------ ----------------------- 
9 1   2014-08-26 20:28:37.37 1   TEST TEST 8   2014-08-27 00:00:00.000 
10 5   2014-08-26 20:28:37.37 1   TEST TEST 8   2014-08-27 00:00:00.000 

測試人員抱怨是有效的,因爲這兩個[事件] [IncidentStatus]值必須在這個零。點。 挖掘後,我捕獲了應用程序發送到服務器的確切查詢(感謝探查器)。

declare @p1 int 
set @p1=2 
exec sp_prepexec @p1 output,N'@IDINCIDENT varchar(max) ,@REASON varchar(max) ,@USERCODE varchar(max) ,@POSTPONEDATE varchar(max) ',N' 
DECLARE @ARRAY VARCHAR(8000), @DELIMITADOR VARCHAR(100), @SELECTEDID VARCHAR(8000); 

SELECT @ARRAY = @IDINCIDENT 
SELECT @DELIMITADOR = '';'' 

IF LEN(@ARRAY) > 0 SET @ARRAY = @ARRAY + @DELIMITADOR 

WHILE LEN(@ARRAY) > 0 
BEGIN 

    SELECT @SELECTEDID = LTRIM(SUBSTRING(@ARRAY, 1, 
    CHARINDEX(@DELIMITADOR, @ARRAY) - 1)) 

    BEGIN 
     UPDATE [dbo].Incident SET INCIDENTSTATUS = 1 WHERE ID = @SELECTEDID 
     INSERT [dbo].IncidentDetail (INCIDENTID, DETAILKIND, REASON, INCIDENTUSER, POSTPONEDATE) 
         VALUES (@SELECTEDID, 1, @REASON, @USERCODE, @POSTPONEDATE); 
    END 

    SELECT @ARRAY = SUBSTRING(@ARRAY, 
    CHARINDEX(@DELIMITADOR, @ARRAY) + 1, LEN(@ARRAY)) 
END 
',@IDINCIDENT='1;5',@REASON='querty',@USERCODE='1',@POSTPONEDATE='2014-08-28 00:00:00' 
select @p1 

沒有觸發器,沒有其他更新沒有未決事務。 據我所知,即使第一次循環迭代阻止第二次循環到更新失敗的位置,也必須引發異常,並且所有事務都要回滾。

似乎ilogical在插入工作時更新可能失敗。 所有列都有標準類型(Int,Varchar(100),DateTime等),我也測試了隱式轉換問題。

這個問題只發生過一次,即使使用備份也無法複製,但如果我無法找到它發生的原因,恐怕會再次發生。

+0

SQL Server中的錯誤有時會中止批處理,有時它們不會。交易和連接也一樣。 (是的,這很討厭。);所以你的更新可能會失敗,插入可能會通過。也許你的應用程序正在拋出錯誤。 – usr 2014-08-27 21:04:28

+0

不,事務本身不能阻塞或死鎖。 – usr 2014-08-27 21:04:47

+0

內部查詢死鎖可以並確實發生。我在生產代碼中自己遇到了它們: http://blogs.msdn.com/b/bartd/archive/2008/09/24/today-s-annoyingly-unwieldy-term-intra-query-parallel-thread -deadlocks.aspx – Jace 2014-08-28 02:11:34

回答

3

我不明白你究竟想要做什麼。我根據我的理解給你一個方法。您可以檢查是否更新條目,如果更新,則插入IncidentDetail。

UPDATE [dbo].Incident SET INCIDENTSTATUS = 1 WHERE ID = @SELECTEDID 

If Exists( Select 1 
      From [dbo].Incident As I 
      Where I.ID = @SELECTEDID 
        And I.INCIDENTSTATUS = 1 
     ) 
Begin 
    INSERT [dbo].IncidentDetail (INCIDENTID, DETAILKIND, REASON, INCIDENTUSER, POSTPONEDATE) 
         VALUES (@SELECTEDID, 1, @REASON, @USERCODE, @POSTPONEDATE); 
End 
+0

幾天後,我們發現問題是由另一位同事刪除了一行引起的,我們盲目地認爲這不是問題。此外,我還發現很多參考文獻說,循環無法鎖定自己(問題從一開始就很愚蠢,我不想關閉它)。我不想刪除它作爲參考,因爲很多人訪問過它。還病態upvote你的答案,因爲它可以有用的人 – jean 2014-09-24 18:11:26