SQLServer2012基於擴展事件的阻塞監控

1、前言

SQL阻塞Block是事務聯機系統OLTP的產物。因爲鎖致使的資源等待,事務執行時間過長,直接影響業務;瞭解阻塞,發現阻塞,已做爲DBA平常維護的重中之重。node

經過dmv能夠發現當前正在阻塞的語句,編寫存儲過程,使用agent做業定時執行,也能達到收集阻塞的效果;然而此方法存在必定的偏差。使用擴展事件記錄全部等待必定時間的阻塞,能完整的記錄全部發生阻塞的SQL。sql

1.一、blocked process threshold (s)

經過如下腳本查看;默認blocked process收集不開啓。數據庫

exec sp_configure 'show advanced options',1;RECONFIGURE
exec sp_configure 'blocked process threshold (s)';

執行如下腳本,記錄全部阻塞超過10s的進程session

USE master;
EXEC sp_configure 'blocked process threshold (s)',10
RECONFIGURE WITH OVERRIDE;
1.二、blocked_process_report

咱們能夠經過選擇blocked_process_report擴展事件,當任務被阻塞的時間超過 sp_configure 阻塞的進程閾值設置所指定的時間時,記錄阻塞信息。以下狀況圖所示。app

clip_image002

2、新建擴展事件

2.一、新建擴展事件ev_block_session

將數據寫入N'd:\xe_sessions\servername_ev_block_session.xel',最大文件2M,能夠循環40個文件,超過40個文件將自動刪除。函數

CREATE EVENT SESSION [ev_block_session] ON SERVER
ADD EVENT sqlserver.blocked_process_report(
ACTION(sqlserver.query_hash,sqlserver.query_plan_hash))
ADD TARGET package0.event_file(SET filename=N'd:\xe_sessions\servername_ev_block_session.xel',max_file_size=(2),max_rollover_files=(40))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
2.二、默認不啓動該事件

手動啓動腳本。oop

ALTER EVENT SESSION [ev_block_session] ON SERVER STATE = START

3、分析阻塞文件

3.一、sys.Fn_xe_file_target_read_file

使用該系統函數,分析擴展事件文件;查出結果XML格式。sqlserver

SELECT CONVERT(XML,event_data) AS data
sys.Fn_xe_file_target_read_file(N'd:\xe_sessions\servername_ev_block_session.xel',NULL,NULL,NULL)
3.二、分析

新建xe_block表,將分析結果保存在在該表中。具體信息以下腳本所示;每阻塞10s時間,就會再次被記錄;能夠經過查詢同一個transaction_id下最大monitorloop,來肯定當前阻塞時間。spa

;WITH d AS (
SELECT
dateadd(hh,8,data.value('(/event/@timestamp)[1]','datetime')) timestamp,--時間戳
data.value('(/event/data[@name="duration"]/value)[1]','bigint')/1000/1000 duration_us,--阻塞時長
data.value('(/event/data[@name="database_name"]/value)[1]','nvarchar(128)') database_name,--阻塞數據庫
data.value('(/event/data[@name="transaction_id"]/value)[1]','bigint') transaction_id,--阻塞事務id
data.value('(//blocked-process-report/@monitorLoop)[1]','bigint') monitorLoop,--監控自增id
data.query('//blocked-process-report') block,--阻塞內容
data
FROM #event_data a
)
INSERT INTO xe_block(
timestamp--時間戳
,duration_us--阻塞時長
,database_name--阻塞數據庫
,transaction_id--阻塞事務數
,monitorLoop--監控增加id
,blocked_spid--被阻塞spid
,blocked_trancount--被阻塞事務
,blocked_waitresource--被阻塞等待資源
,blocked_lockmode--被阻塞等待鎖
,blocked_hostname--被阻塞主機
,blocked_loginname--被阻塞用戶
,blocked_clientapp--被阻塞客戶端
,blocked_sql--被阻塞腳本
,blocking_spid--阻塞spid
,blocking_trancount--阻塞事務數
,blocking_status--阻塞狀態
,blocking_waitresource--阻塞等待資源
,blocking_lockmode--阻塞鎖
,blocking_hostname--阻塞主機
,blocking_loginname--阻塞用戶
,blocking_clientapp--阻塞客戶端
,blocking_sql--阻塞腳本
,data
)
SELECT
d.timestamp,
d.duration_us,
d.database_name,
d.transaction_id,
d.monitorLoop,
ed.c.value('@spid','int') blocked_spid,
ed.c.value('@trancount','int') blocked_trancount,
ed.c.value('@waitresource','varchar(64)') blocked_waitresource,
ed.c.value('@lockMode','varchar(32)') blocked_lockmode,
ed.c.value('@hostname','varchar(64)') blocked_hostname,
ed.c.value('@loginname','varchar(64)') blocked_loginname,
ed.c.value('@clientapp','varchar(256)') blocked_clientapp,
ed.c.query('.').value('(/process/inputbuf)[1]','varchar(max)') blocked_sql,
ing.c.value('@spid','int') blocking_spid,
ing.c.value('@trancount','int') blocking_trancount,
ing.c.value('@status','varchar(32)') blocking_status,
ing.c.value('@waitresource','varchar(64)') blocking_waitresource,
ing.c.value('@lockMode','varchar(32)') blocking_lockmode,
ing.c.value('@hostname','varchar(64)') blocking_hostname,
ing.c.value('@loginname','varchar(64)') blocking_loginname,
ing.c.value('@clientapp','varchar(256)') blocking_clientapp,
ing.c.query('.').value('(/process/inputbuf)[1]','varchar(max)') blocking_sql,
data
FROM d
CROSS APPLY d.block.nodes('//blocked-process/process') ed(c)
CROSS APPLY d.block.nodes('//blocking-process/process') ing(c)

4、監控報警

報警方式:統計每分鐘阻塞事務數,阻塞時長,經過必定規則並經過report service發送訂閱,報警以下code

相關文章
相關標籤/搜索