SQL Server擴展事件system_health會話總結

system_health會話概念node

 

咱們知道擴展事件(Extended Events)是從SQL Server 2008開始引入的。system_health會話是SQL Server默認包含的擴展事件會話。該會話在SQL Server數據庫引擎啓動時自動啓動,而且運行時不會對性能形成任何明顯影響。該會話收集的系統數據可用於幫助對數據庫引擎的性能問題進行故障排除。sql

 

該會話收集的信息包括:(下面來自官方文檔使用 system_health 會話數據庫

 

 

 

·         發生嚴重性 >=20 的錯誤的任何會話的 sql_text session_id 安全

·          服務器

·         發生內存相關錯誤的任何會話的 sql_text session_id 這些錯誤包括 17803701802864586518657 8902session

·          app

·         任何沒法完成的計劃程序問題的記錄。 這些問題在 SQL Server 錯誤日誌中顯示爲錯誤 17883工具

·          post

·         檢測到的任何死鎖,包括死鎖圖形。性能

·          

·         等待閂鎖(或其餘相關資源)時間 > 15 秒的任何會話的 callstacksql_text session_id

·          

·         等待鎖(或其餘相關資源)時間 > 30 秒的任何會話的 callstacksql_text session_id

·          

·         爲得到搶先等待(或其餘相關資源)而等待時間很長的任何會話的 callstacksql_text session_id 持續時間因等待類型而異。 在搶先等待中, SQL Server 等待的是外部 API 調用。

·          

·         CLR 分配失敗和虛擬分配失敗的調用堆棧和 session_id

·          

·         有關內存代理、計劃程序監視、內存節點 OOM、安全性和鏈接的環形緩衝區事件。

·          

·         來自 sp_server_diagnostics 的系統組件結果。

·          

·         scheduler_monitor_system_health_ring_buffer_recorded 收集的實例運行情況。

·          

·         CLR 分配失敗。

·          

·         使用 connectivity_ring_buffer_recorded 時的鏈接錯誤。

·          

·         使用 security_error_ring_buffer_recorded 時的安全錯誤。

 

 

其實咱們用system_health會話最多的地方,就是查看、分析死鎖信息。這也是爲何這篇文章要總結的緣由。由於死鎖是DBA常常遇到的問題之一,而system_health會話是捕獲、分析死鎖最佳工具,沒有之一。

 

 

 

system_health會話配置

 

若是要確認system_health會話是否在啓動時是否啓動會話,可使用下面腳本:

 

startup_state0 (OFF) 服務器啓動時不啓動會話。

               1 (ON)  服務器啓動時啓動事件會話。

 

SELECT 
    es.name, 
    esf.name, 
    esf.value,
    es.startup_state
FROM  
    sys.server_event_session_fields AS esf
JOIN 
    sys.server_event_sessions AS es
ON 
    esf.event_session_id=es.event_session_id
WHERE  es.name='system_health'

 

 

 

SQL Server 2008下碰到一個很奇怪的事情(只是一個特例,不是全部SQL Server 2008都有這種現象),system_health會話的create_time竟然大於當前的getdate(). 彷佛是個bug來着。

 

 

SELECT  s.name ,
        se.event_name,
        s.create_time
FROM    sys.dm_xe_sessions s
        INNER JOIN sys.dm_xe_session_events se ON ( s.address = se.event_session_address )
                                                  AND ( event_name = 'xml_deadlock_report' )
WHERE   name = 'system_health';

 

clip_image001

 

 

查看system_health會話的一些設置信息。以下腳本所示:

 

 

clip_image002

 

 

默認狀況下,system_health會話使用環形緩衝區目標(ring buffer target)和事件文件目標(event file target存儲數據。事件文件目標配置爲最大大小爲 5 MB,文件保留策略爲4個文件,在SQL Server 2008 SQL Server 2008R2下,默認使用環形緩衝區目標(ring buffer target), 而SQL Server 2012或以上版本默認使事件文件目標(event file target)存儲數據。以下腳本所示,你可使用下面腳本查看system_health會話的而設置。

 

SELECT 
    es.name, 
    esf.name, 
    esf.value 
FROM  
    sys.server_event_session_fields AS esf
JOIN 
    sys.server_event_sessions AS es
ON 
    esf.event_session_id=es.event_session_id
WHERE es.startup_state=1
    AND (esf.name= 'filename' 
        OR esf.name ='max_file_size' 
        OR esf.name='max_rollover_files')
 
 
SELECT 
    es.name, 
    esf.name, 
    esf.value 
FROM  
    sys.server_event_session_fields AS esf
JOIN 
    sys.server_event_sessions AS es
ON 
    esf.event_session_id=es.event_session_id
WHERE es.startup_state=1 AND es.name='system_health'
    AND (esf.name= 'filename' 
        OR esf.name ='max_file_size' 
        OR esf.name='max_rollover_files')

 

clip_image003

 

 

修改system_health會話的的文件大小,以及文件保留個數。

 

ALTER EVENT SESSION [system_health] 
ON SERVER STATE = STOP
GO
ALTER EVENT SESSION [system_health] 
ON SERVER DROP TARGET package0.event_file 
ALTER EVENT SESSION [system_health] 
ON SERVER ADD TARGET package0.event_file 
    (SET FILENAME=N'system_health.xel',--name of the session
    max_file_size=(24), --size of each file in MB
    max_rollover_files=(50)) --how many files you want to keep
GO
ALTER EVENT SESSION [system_health] 
ON SERVER STATE = START
GO

 

 

 

其實你也能夠定製本身的擴展事件捕獲死鎖。這裏不作展開介紹。 在SQL Server 2008下面,因爲system_health會話將事件保存在ring buffer target中,因爲ring buffer target的大小限制以及sys.dm_xe_session_targets這個DMVtarget_data列只能輸出大約4MBXML數據,這樣有可能致使你看不到當前的死鎖信息(Missing Events)或者有些舊事件被清除了。從而致使你沒法查看某些時間段的死鎖信息。因此有時候會定製一些擴展事件。

 

 

 

system_health會話分析死鎖

 

若是system_health會話使用ring buffer target保存事件數據的話,那麼你須要知道下面這些內容:

 

ring buffer target將事件數據保存到內存中,事件數據以XML格式存儲。一旦事件數據把分配的內存Buffers 用盡,那麼最老的事件數據將被清除。

 

ring buffer target簡單地把數據存儲到內存中,這種target模式採用兩種模式來管理事件:

 

第一種模式是嚴格地先進先出(first-in first-out FIFO),也就是說,當分配的內存被target耗盡時,從內存中移除建立時間最先的事件。

 

第二種模式是per-event 先進先出模式,也就是說,每一種類型的事件都持有一個計數。在這種模式下,當分配的內存被target耗盡時,每一個類型中建立時間最先的事件從內存中被移除。

 

The ring buffer target briefly holds event data in memory. This target can manage events in one of two modes.

 

·         The first mode is strict first-in first-out (FIFO), where the oldest event is discarded when all the memory allocated to the target is used. In this mode (the default), the occurrence_number option is set to 0.

 

·         The second mode is per-event FIFO, where a specified number of events of each type is kept. In this mode, the oldest events of each type are discarded when all the memory allocated to the target is used. You can configure the occurrence_number option to specify the number of events of each type to keep.

 

 

 

咱們可使用下面腳原本查看ring buffer target中的死鎖信息。

 

 

SELECT 
    DeadlockGraph
,   [DbId] = DeadlockGraph.value ( '(/deadlock/resource-list//@dbid)[1]', 'int' )
,   [DbName] = DB_NAME ( DeadlockGraph.value ( '(/deadlock/resource-list//@dbid)[1]', 'int' ) ) 
,   [LastTranStarted] = DeadlockGraph.value ( '(/deadlock/process-list/process/@lasttranstarted)[1]', 'datetime' )
FROM
(
   SELECT 
      CAST ( event_data.value ( '(event/data/value)[1]', 'varchar(max)' ) AS XML ) AS DeadlockGraph
   FROM    
   ( 
      SELECT    
         XEvent.query('.') AS event_data
      FROM      
         ( -- Cast the target_data to XML 
            SELECT    
               CAST( st.target_data AS XML ) AS TargetData
            FROM
               sys.dm_xe_session_targets st
            JOIN 
               sys.dm_xe_sessions s
            ON 
               s.[address] = st.event_session_address
            WHERE     
               name = 'system_health'
               AND target_name = 'ring_buffer'
         ) AS Data  
      CROSS APPLY      -- Split out the Event Nodes
         TargetData.nodes ( 'RingBufferTarget/event[@name="xml_deadlock_report"]' ) AS XEventData ( XEvent )
   ) AS tab ( event_data )
) AS A
ORDER BY [LastTranStarted];

 

 

 

注意:在SQL Server 2008中,system_health會話信息保存在ring buffer target中,會出現一些死鎖信息不能及時查到的狀況(後續能夠查看),這個是由於一些限制緣故。摘抄「Why I hate the ring_buffer target in Extended Events」的解釋以下,詳情參考這篇文章。

 

This is by far the most common problem I have to explain about the ring_buffer target by email.  Generally the question is phrased along the lines of:

        「Hey Jonathan,I got the code below from one of your articles on SQL Server central and it is not working. The problem I have is that when I run the code, it doesn’t show any deadlock graphs even though I know one just occurred in the application. It seems like I only see older deadlocks in the system_health session, but never the most recent one.  I’ve turned on Trace 1222 and get the information that way, so why doesn’t this work.」

The reality of the situation is that the events are actually there, you just can’t see them because of a limitation of the sys.dm_xe_session_targets DMV.  The target_data column of this DMV can only output roughly 4MB of XML data. The information about the 4MB formated XML limitation of the DMV was explained by Bob Ward on the CSS SQL Server Engineers blog post You may not see the data you expect in Extended Event Ring Buffer Targets…. back in 2009.  To demonstrate the effect of this limitation, lets look at the number of events contained in the ring_buffer target for the system_health event session on a SQL Server 2012 SP1+CU7 server that I have permission to share the information from using the following query.

 

 

若是system_health會話使用事件文件保存數據的話,可使用下面腳本查詢死鎖信息:

 

 

DECLARE @path  NVARCHAR(260);
 
SELECT 
    TOP  1 @path=[path]
FROM
    SYS.dm_os_server_diagnostics_log_configurations
 
 
SET @path=@path +'system_health*.xel'
 
SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(),CURRENT_TIMESTAMP), T.execution_time_utc) AS event_time,
       T.dead_lock_xml
FROM
(
SELECT CONVERT(xml, event_data).query('/event/data/value/child::*') AS dead_lock_xml,
       CONVERT(xml, event_data).value('(event[@name="xml_deadlock_report"]/@timestamp)[1]','datetime') as execution_time_utc
        
FROM sys.fn_xe_file_target_read_file(@path, null, null, null)
WHERE object_name like 'xml_deadlock_report'
) T
ORDER BY 1 DESC
GO

 

 

注意:這個腳本可能不能知足全部的情形,例如,你將擴展事件的文件沒有放置在默認位置。放置在其餘地方....等等。

 

 

 

參考資料:

 

 

https://www.sqlskills.com/blogs/jonathan/why-i-hate-the-ring_buffer-target-in-extended-events/

https://docs.microsoft.com/zh-cn/sql/relational-databases/extended-events/use-the-system-health-session?view=sql-server-2017

相關文章
相關標籤/搜索