SQL Server 收集數據庫死鎖信息
背景
我們在數據庫出現阻塞及時郵件預警提醒中監控了數據庫的阻塞情況,為了更好的維護數據庫,特別是提升終端客戶用戶體驗,我們要盡量避免在數據庫中出現死鎖的情況。我們知道收集死鎖可以開啟跟蹤標誌如1204,然後在日誌中查看死鎖相關信息,或者使用Profiler去跟蹤死鎖,我們希望所有的死鎖信息收集到某表供我們後期優化分析使用,我們可以使用相對比較輕量的自帶擴展事件(system_health)來完成這個需求。測試環境
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) Feb 10 2012 19:39:15 Copyright (c) Microsoft Corporation實現過程
a.新建存放死鎖的表
IF DB_ID(‘azure_monitor‘) IS NULL BEGIN CREATE DATABASE azure_monitor ; END GO ALTER DATABASE azure_monitor SET RECOVERY SIMPLE; GO USE [azure_monitor]; --存放死鎖信息的庫名 GO IF OBJECT_ID(‘monitor_deadlock‘, ‘U‘) IS NOT NULL DROP TABLE dbo.monitor_deadlock; GO CREATE TABLE [dbo].[monitor_deadlock] ( [ServerName] [VARCHAR](50), [DataBaseName] [NVARCHAR](100) NULL , [DeadlockID] [BIGINT] NULL , [TransactionTime] [DATETIME] NULL , [DeadlockGraph] [XML] NULL , [DeadlockObjects] [NVARCHAR](MAX) NULL , [Victim] [INT] NOT NULL , [SPID] [INT] NULL , [ProcedureName] [VARCHAR](200) NULL , [LockMode] [CHAR](1) NULL , [Code] [VARCHAR](1000) NULL , [ClientApp] [NVARCHAR](245) NULL , [HostName] [VARCHAR](20) NULL , [LoginName] [VARCHAR](20) NULL , [InputBuffer] [VARCHAR](1000) NULL , [Capture_date] [DATETIME] NOT NULL , [capture_day] AS ( CONVERT([VARCHAR](12), [Capture_date], ( 112 )) ) , [comfirm_user] [NVARCHAR](50) NULL , [comfirm_flag] [INT] NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]; GO ALTER TABLE [dbo].[monitor_deadlock] ADD CONSTRAINT [DF__monitor_d__Captu__2CF2ADDF] DEFAULT (GETDATE()) FOR [Capture_date]; GO ALTER TABLE [dbo].[monitor_deadlock] ADD CONSTRAINT [DF__monitor_d__comfi__2DE6D218] DEFAULT ((1)) FOR [comfirm_flag]; GO
b.新建讀取死鎖的存儲過程
USE [azure_monitor]; --存放讀取死鎖信息的存儲過程的庫名 GO IF OBJECT_ID(‘monitor_P_deadlock‘, ‘P‘) IS NULL EXEC( ‘CREATE procedure dbo.monitor_P_deadlock AS ‘); GO /*============================================= -- Author: jil.wen -- Create date: 2017/04/11 -- Description: 監控數據庫上死鎖情況; -- demo : exec dbo.monitor_P_deadlock ============================================= */ ALTER PROCEDURE monitor_P_deadlock AS BEGIN -- DELETE FROM dbo.monitor_deadlock -- WHERE [capture_day] = CONVERT([VARCHAR](12), GETDATE(), ( 112 )) -- AND comfirm_flag = 1; DECLARE @SessionName sysname; DECLARE @Servername VARCHAR(50); SELECT @Servername = @@SERVERNAME; SELECT @SessionName = ‘system_health‘; /* SELECT Session_Name = s.name, s.blocked_event_fire_time, s.dropped_buffer_count, s.dropped_event_count, s.pending_buffers FROM sys.dm_xe_session_targets t INNER JOIN sys.dm_xe_sessions s ON s.address = t.event_session_address WHERE target_name = ‘event_file‘ --*/ IF OBJECT_ID(‘tempdb..#Events‘) IS NOT NULL BEGIN DROP TABLE #Events; END; DECLARE @Target_File NVARCHAR(1000) , @Target_Dir NVARCHAR(1000) , @Target_File_WildCard NVARCHAR(1000); SELECT @Target_File = CAST(t.target_data AS XML).value(‘EventFileTarget[1]/File[1][email protected]
c.在Agent新建job調用上述【monitor_P_deadlock】存儲過程
省略,詳情可以參考數據庫出現阻塞及時郵件預警提醒(下)
d.收集效果如下
註意事項
- 如需使用Agent代理發送預警郵件,就要註意Agent是否正常運行;
- 是否有調用上述腳本的數據庫用戶權限;
- 數據庫自帶擴展事件system_health是否正常運行;
SQL Server 收集數據庫死鎖信息