SQL阻塞Block是事務聯機系統OLTP的產物。因爲鎖致使的資源等待,事務執行時間過長,直接影響業務;瞭解阻塞,發現阻塞,已做爲DBA平常維護的重中之重。node
經過dmv能夠發現當前正在阻塞的語句,編寫存儲過程,使用agent做業定時執行,也能達到收集阻塞的效果;然而此方法存在必定的偏差。使用擴展事件記錄全部等待必定時間的阻塞,能完整的記錄全部發生阻塞的SQL。sql
經過如下腳本查看;默認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;
咱們能夠經過選擇blocked_process_report擴展事件,當任務被阻塞的時間超過 sp_configure 阻塞的進程閾值設置所指定的時間時,記錄阻塞信息。以下狀況圖所示。app
將數據寫入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
手動啓動腳本。oop
ALTER EVENT SESSION [ev_block_session] ON SERVER STATE = START
使用該系統函數,分析擴展事件文件;查出結果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)
新建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)
報警方式:統計每分鐘阻塞事務數,阻塞時長,經過必定規則並經過report service發送訂閱,報警以下code