CTE查询以查找基于父spid和阻塞spid的所有死锁

时间:2014-09-24 18:28:47

标签: sql sql-server sql-server-2008

我已经在Table SPIDtable中捕获了spid,blockedByspid列 价值观是这样的 这里,死锁循环是116-> 243-> 248-> 116 这张表中有很多这样的死锁。

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

1 个答案:

答案 0 :(得分: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。)