SQL Server一個特殊的阻塞案例分析2

最近發現一個很是奇怪的阻塞問題,以下截圖所示(來自監控工具DPA),會話583被會話1036阻塞,並且阻塞發生在tempdb,被阻塞的SQL以下截圖所示,會話等待類型爲LCK_M_Shtml

 

 

clip_image001

 

 

 

 

clip_image002

 

由於DPA工具很差截取所有信息,使用下面SQL語句獲取了阻塞會話的詳細信息以下,來自Microsoft SQL Server Management Studio - Transact-SQL IntelliSense的的SQL被阻塞了sql

 

SELECT  s.session_id ,
        r.status ,
        r.blocking_session_id 'Blk by' ,
        r.wait_type ,
        wait_resource ,
        r.wait_time / ( 1000 * 60 ) 'Wait M' ,
        r.cpu_time ,
        r.logical_reads ,
        r.reads ,
        r.writes ,
        r.total_elapsed_time / ( 1000 * 60 ) 'Elaps M' ,
        SUBSTRING(st.text, ( r.statement_start_offset / 2 ) + 1,
                  ( ( CASE r.statement_end_offset
                        WHEN -1 THEN DATALENGTH(st.text)
                        ELSE r.statement_end_offset
                      END - r.statement_start_offset ) / 2 ) + 1) AS statement_text ,
        COALESCE(QUOTENAME(DB_NAME(st.dbid)) + N'.'
                 + QUOTENAME(OBJECT_SCHEMA_NAME(st.objectid, st.dbid)) + N'.'
                 + QUOTENAME(OBJECT_NAME(st.objectid, st.dbid)), '') AS command_text ,
        r.command ,
        s.login_name ,
        s.host_name ,
        s.program_name ,
        s.last_request_end_time ,
        s.login_time ,
        r.open_transaction_count
FROM    sys.dm_exec_sessions AS s
        JOIN sys.dm_exec_requests AS r ON r.session_id = s.session_id
        CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE r.session_id =583
ORDER BY r.cpu_time DESC;

 

clip_image001[4]

 

 

而會話1036處於睡眠(sleeping)狀態,有一個Open的事務。經過wait_resource的值KEY: 2:1125899909070848 (79c68d10aa42)咱們定位到是一個系統表sysschobj.它是sys.triggers這個系統視圖的基表。以下所示:session

 

 

clip_image004

 

 

 

clip_image005

 

 

SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE VIEW sys.triggers AS
    SELECT o.name,
        object_id = o.id,
        parent_class = o.pclass,
        parent_class_desc = pc.name,
        parent_id = o.pid,
        type = o.type,
        type_desc = n.name,
        create_date = o.created,
        modify_date = o.modified,
        is_ms_shipped = sysconv(bit, o.status & 1),         -- OBJALL_MSSHIPPED
        is_disabled = sysconv(bit, o.status & 256),         -- OBJTRG_DISABLED
        is_not_for_replication = sysconv(bit, o.status & 512), -- OBJTRG_NOTFORREPL
        is_instead_of_trigger = sysconv(bit, o.status & 1024)     -- OBJTRG_INSTEADOF
    FROM sys.sysschobjs o
    LEFT JOIN sys.syspalnames n ON n.class = 'OBTY' AND n.value = o.type
    LEFT JOIN sys.syspalvalues pc ON pc.class = 'UNCL' AND pc.value = o.pclass
    WHERE o.type IN ('TA','TR') AND o.pclass <> 100
        AND has_access('TR', o.id, o.pid, o.nsclass) = 1
 
GO

 

 

 

使用下面腳本能夠查到對應的鎖信息(其實,正確的作法應該是加上條件過濾spid),從而能夠判斷,會話1036可能由於事務中,間接涉及對基表sysschobj的DML操做(有多是衍生的系統視圖),而因爲事務沒有提交也沒有釋放,致使在基表上的鎖沒有釋放,從而致使出現這樣一個阻塞。我的也很好奇是什麼樣的SQL會致使這樣一個阻塞出現,不過這種阻塞源頭是Sleeping狀態的會話,已經沒法定位阻塞源頭SQL,只能經過Profile去跟蹤捕獲。可是這種阻塞出現時機和場景不清楚,很難一會兒捕獲到。app

 

 
USE tempdb
GO
SELECT  request_session_id AS spid ,
        DB_NAME(resource_database_id) AS dbname ,
        CASE WHEN resource_type = 'OBJECT'
             THEN OBJECT_NAME(resource_associated_entity_id)
             WHEN resource_associated_entity_id = 0 THEN 'n/a'
             ELSE OBJECT_NAME(p.object_id)
        END AS entity_name ,
        index_id ,
        resource_type AS resource ,
        resource_description AS description ,
        request_mode AS mode ,
        request_status AS status
FROM    sys.dm_tran_locks t
LEFT JOIN sys.partitions p
ON      p.partition_id = t.resource_associated_entity_id
WHERE   resource_database_id = DB_ID()

 

 

clip_image006

 

 

今天早上有發現一樣的阻塞,猜想是SQL裏面有建立臨時表或對臨時表作DDL或DML操做的跡象。不過依然沒有找到源頭SQL,只能靜候下次機會。找出罪魁禍首。不過讓我頭痛的是,對於這種特殊阻塞狀況,即便是使用Profile跟蹤也是至關麻煩,由於不知道它什麼時間點出現、出如今那個會話。工具

 

SELECT  tl.resource_type AS [Resource Type] ,
        DB_NAME(tl.resource_database_id) AS [DB Name] ,
        CASE tl.resource_type
          WHEN 'OBJECT'
          THEN OBJECT_NAME(tl.resource_associated_entity_id,
                           tl.resource_database_id)
          WHEN 'DATABASE' THEN 'DB'
          ELSE CASE WHEN tl.resource_database_id = DB_ID()
                    THEN ( SELECT   OBJECT_NAME(object_id,
                                                tl.resource_database_id)
                           FROM     sys.partitions
                           WHERE    hobt_id = tl.resource_associated_entity_id
                         )
                    ELSE '(Run under DB context)'
               END
        END AS [Object] ,
        tl.resource_description AS [Resource] ,
        tl.request_session_id AS [Session] ,
        tl.request_mode AS [Mode] ,
        tl.request_status AS [Status] ,
        wt.wait_duration_ms AS [Wait (ms)] ,
        qi.sql ,
        qi.query_plan
FROM    sys.dm_tran_locks tl WITH ( NOLOCK )
LEFT OUTER JOIN sys.dm_os_waiting_tasks wt WITH ( NOLOCK )
ON      tl.lock_owner_address = wt.resource_address
        AND tl.request_status = 'WAIT'
OUTER APPLY ( SELECT    SUBSTRING(s.text,
                                  ( er.statement_start_offset / 2 ) + 1,
                                  ( ( CASE er.statement_end_offset
                                        WHEN -1 THEN DATALENGTH(s.text)
                                        ELSE er.statement_end_offset
                                      END - er.statement_start_offset ) / 2 )
                                  + 1) AS sql ,
                        qp.query_plan
              FROM      sys.dm_exec_requests er WITH ( NOLOCK )
              CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) s
              OUTER APPLY sys.dm_exec_query_plan(er.plan_handle) qp
              WHERE     tl.request_session_id = er.session_id
            ) qi
WHERE   tl.request_session_id =134

 

 

clip_image007

 

連接資料

一個特殊的SQL Server阻塞案例分析spa

SQL Server一個特殊的阻塞案例分析23d

相關文章
相關標籤/搜索