2014-09-24 33 views
0

我已經捕獲spid,blockedByspid列中的一個表SPIDtable 這個值有點像這樣 這裏的死鎖週期是116-> 243-> 248- > 116 這個表中有很多這樣的死鎖。CTE查詢找到所有基於父spid和被阻塞的spid的死鎖

spid blockedBy 
116 208 
116 243 
243 248 
248 116 

我已經寫CTE查詢打印出所有這樣的循環

這是找到了一些週期,但它是後最大100遞歸停止,有沒有更好的方法

;WITH cte(spid, blockedBy, isCycle) 
    as 
    (
    select spid, blockedBy , 0 FROM SPIDTable 
    where blockedby <>0 
    union all 
    select S.spid , S.blockedBy, (case when CTE.blockedBy = S.spid then 1 else 0 end) as cycle from CTE 
    inner join SPIDtable S 
    on S.blockedBy = CTE.spid  
) 
    select * from CTE where isCycle =1 
+0

查看跟蹤標誌1204和1222,以便在SQL Server檢測到它們時記錄全面的死鎖信息。 – Laurence 2014-09-24 18:36:19

回答

2

通過定義,死鎖圖將至少有一次循環。因此,如果你只是在blocker.spid = blocked.blockedBy上運行你的查詢,你將永遠迭代,除非你有一個終止子句。以下是我想出了:

with SPIDTable as (
    select * from (values 
     (116, 208), 
     (116, 243), 
     (243, 248), 
     (248, 116) 
    ) as x(spid, blockedBy) 
) 
, cte as (
    select spid 
     , blockedBy 
     , 0 as isCycle, spid as [starter] 
     , cast(spid as nvarchar(max)) as [chain] 
     , 1 as [level] 
    FROM SPIDTable 
    where blockedby <> 0 

    union all 

    select S.spid , S.blockedBy 
    , case when CTE.starter = S.spid then 1 else 0 end as cycle 
    , cte.starter as [starter] 
    , cte.chain + '/' + cast(s.spid as nvarchar(max)) as [chain] 
    , cte.[level] + 1 as [level] 
    from CTE 
    inner join SPIDtable S 
     on S.blockedBy = CTE.spid 
    where s.spid <> cte.starter 
) 
select * from CTE 
order by [level] 

注意,在這個例子中,所有的「3級」的行表示相同的週期(即116→248→243→116)。但是在所有情況下,具有最高級別的行將是完整的死鎖週期(最後一個(省略)spid將只是鏈中的第一個spid)。

+0

這看起來很有希望,並給我想要的結果。 – radar 2014-09-24 19:43:54

+0

不錯的一個。本·圖爾 – artm 2014-09-25 08:19:19