使用擴展事件記錄 SQL 執行歷史

http://tommwq.tech/blog/%e4%bd%bf%e7%94%a8%e6%89%a9%e5%b1%95%e4%ba%8b%e4%bb%b6%e8%ae%b0%e5%bd%95-sql-%e6%89%a7%e8%a1%8c%e5%8e%86%e5%8f%b2/

 

擴展事件(XEvent)是 SQL Server 從 2008 版本開始提供的一種記錄系統運行事件的機制。使用擴展事件可以瞭解 SQL Server 的內部執行情況,其中就包括了執行過哪些 SQL 語句。要記錄和查看 SQL 語句執行歷史,需要執行 4 個步驟:創建擴展事件會話;啓動擴展事件會話;讀取 xel 文件;關閉擴展事件會話。

 

1 創建擴展事件會話

 

IF EXISTS (SELECT * FROM sys.server_event_sessions WHERE name='test_event_session')
    DROP EVENT SESSION test_event_session ON SERVER;
GO

CREATE EVENT SESSION test_event_session
ON SERVER
ADD EVENT sqlserver.sql_statement_completed 
(
        ACTION (sqlserver.sql_text)
)
ADD TARGET package0.event_file
(
        SET filename=N'Z:\test_event_session.xel'
) 
WITH 
(
        MAX_MEMORY=16MB,
        MAX_EVENT_SIZE=16MB,
        MAX_DISPATCH_LATENCY=1 SECONDS
);
GO

 

使用語句 CREATE EVENT SESSION 可以創建擴展事件會話。要使用擴展事件記錄 SQL 執行歷史,首先必須創建擴展事件會話。這裏我們選擇 test_event_session 作爲會話名,並將 sqlserver.sql_statement_completed 事件添加到會話中。sql_statement_completed 是事件名,表示“Transact-SQL 語句已完成時發生。”事件。sqlserver 是包名,事件是從屬於某個包的。後面我們會進一步介紹包、事件等概念。擴展事件中定義了很多事件類型,這些事件可以通過下面的 SQL 語句查詢:Listing 1: 查詢 SQL Server 支持的擴展事件

 

SELECT packages.name,packages.description,objects.name,objects.description 
FROM sys.dm_xe_objects objects
LEFT JOIN sys.dm_xe_packages packages ON packages.guid=objects.package_guid
WHERE object_type='event'
ORDER BY packages.name,objects.name

 

這裏我們只關注 SQL 執行歷史記錄,因此只需要添加 sql_statement_completed 事件。

 

當事件發生後,事件被髮送給目標(target),目標是保存事件信息的地方。這裏我們使用 event_file,表示將事件信息保存到文件中。要注意的時,參數 filename 必須以“.xel”結尾。每個目標支持不同的參數,這些參數可以通過下面的 SQL 查詢:Listing 2: 查詢目標參數

 

SELECT object_name,name,type_name,column_value,description FROM sys.dm_xe_object_columns WHERE column_type='customizable'

 

2 啓動擴展事件會話

 

擴展事件會話創建後,我們還需要啓動會話,讓 SQL Server 開始記錄事件。 #+caption 啓動擴展事件會話

 

ALTER EVENT SESSION  test_event_session ON SERVER STATE=START

 

會話啓動之後,我們可以從下面個視圖中查詢會話的信息。Listing 3: 查詢會話信息

 

SELECT * FROM sys.server_event_sessions;
GO

SELECT * FROM sys.dm_xe_sessions;
GO

 

3 讀取 xel 文件

 

啓動會話後,SQL Server 會將事件信息保存到 xel 文件中。SQL Server 不會向我們設置的 filename 文件中寫入數據,實際的文件名是在 filename 中添加序號和時間戳得到的。這麼做是爲了進行文件輪轉。在我的服務器(SQL Server 2014 SP2)上,默認情況下 SQL Server 爲每個事件會話保留最多 5GB 事件數據。這是可以配置的,方法參考上一節。

 

由於實際文件名不是 filename 參數值,我們需要查詢文件名。Listing 4: 查看會話 xel 文件實際名稱

 

SELECT
    n.value('(File/@name)[1]', 'nvarchar(max)') AS xel_filename
FROM
(
    SELECT CAST(targets.target_data AS XML) AS target_data
    FROM sys.dm_xe_session_targets AS targets
    JOIN sys.dm_xe_sessions AS xe_sessions ON xe_sessions.address=targets.event_session_address
    JOIN sys.server_event_sessions se_sessions ON se_sessions.name=xe_sessions.name
    WHERE xe_sessions.name='test_event_session'
) td
CROSS APPLY td.target_data.nodes('EventFileTarget') AS q(n)

 

得到 xel 實際文件名之後,我們可以查詢其中記錄的時間信息。這裏我們只關心 SQL 執行歷史。Listing 5: 從 xel 文件查詢事件信息

 

SELECT
    n.value('(@timestamp)[1]', 'datetime2') AS [utc_timestamp],
    n.value('(data[@name="statement"]/value)[1]', 'nvarchar(max)') AS statement
FROM 
(
    SELECT CAST(event_data AS XML) AS event_data
    FROM sys.fn_xe_file_target_read_file('Z:\test_event_session_0_132871334271260000.xel', null, null, null)
) ed
CROSS APPLY ed.event_data.nodes('event') AS q(n)

 

4 停止會話

 

查詢完畢後不要忘了停止會話,以免產生性能損耗。Listing 6: 停止會話

 

ALTER EVENT SESSION test_event_session ON SERVER STATE=STOP

 

會話停止以後,對 SQL Server 沒有任何性能影響。當然如果不再需要使用這個會話,最好在會話停止後刪除會話。Listing 7: 刪除會話

 

DROP EVENT SESSION test_event_session ON SERVER;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章