데드락 감지는 다양한 형태로 감지할 수 있다.
가. SQL Errorlog
나. 경고 시스템을 이용한 데드락 감시
다. SQL Server 프로파일러를 이용한 데드락 정보 추적.
이번에는 경고 시스템을 이용한 데드락 감시 방법에 대한 설명을 하겠다.
작업할 내용 : 데드락 발생시 DBA라는 DB에 데드락 정보를 기록(SQL2008 이후 버젼에서만 사용 가능)
1. 데드락 감지를 위한 추적 플레그 확성화 체크
T1204: 교착 상태에 있는 잠금의 유형과 리소스 및 현재 영향을 받은 명령을 반환.
T1222: 교착 상태에 있는 잠금의 유형과 리소스 및 현재 영향을 받은 명령을 XSD 스키마에 맞지않는 XML형식으로 반환.
DBCC TRACEON (1222, 1204, -1); go
2. 데드락 정보 경고 발생으로 알람 기능
가. Object 생성
------------------------------------------------------------------------------ -- TABLE ------------------------------------------------------------------------------ CREATE TABLE [dbo].[TblAlert]( [mIdx] [int] IDENTITY(1,1) NOT NULL, [mRegDate] [datetime] NOT NULL, [mType] [tinyint] NOT NULL, [DeadLocks] [xml] NULL, CONSTRAINT [PK_TblAlert] PRIMARY KEY CLUSTERED ( [mIdx] DESC ) ) GO ALTER TABLE [dbo].[TblAlert] ADD CONSTRAINT [DF_TblAlert_mRegDate] DEFAULT (getdate()) FOR [mRegDate] GO ALTER TABLE [dbo].[TblAlert] ADD CONSTRAINT [DF_TblAlert_mType] DEFAULT ((0)) FOR [mType] GO -------------------------------------------------------------------------------------- -- PROCEDURE, FUNCTION -------------------------------------------------------------------------------------- GO CREATE PROCEDURE [dbo].[Usp_Ins_DeadLockCount] AS DECLARE @DeadLocks XML; SET @DeadLocks = ( SELECT x.y.value('(@name)[1]', 'varchar(50)') [deadlock-list/deadlock/@eventname], x.y.value('(@timestamp)[1]', 'datetime') [deadlock-list/deadlock/@timestamp], CAST(x.y.value('data(.//data/value)[1]','VARCHAR(MAX)') AS XML).value('deadlock[1]/victim-list[1]/victimProcess[1]/@id[1]','VARCHAR(15)') [deadlock-list/deadlock/@victim], CAST(x.y.value('data(.//data/value)[1]','VARCHAR(MAX)') AS XML).query('deadlock/process-list/*') [deadlock-list/deadlock/process-list], CAST(x.y.value('data(.//data/value)[1]','VARCHAR(MAX)') AS XML).query('deadlock/resource-list/*') [deadlock-list/deadlock/resource-list] FROM ( SELECT CAST([target_data] as XML) [target_data] FROM sys.dm_xe_session_targets st INNER JOIN sys.dm_xe_sessions s ON s.[address] = st.[event_session_address] WHERE s.[name] = 'system_health' ) [deadlock] CROSS APPLY [target_data].nodes('/RingBufferTarget/event') AS x(y) WHERE x.y.query('.').exist('/event[@name="xml_deadlock_report"]') = 1 FOR XML PATH(''),ROOT('root') ) INSERT INTO [dbo].[TblAlert] (mType, DeadLocks) SELECT 1, x.y.query('.') [deadlocks] FROM @DeadLocks.nodes('/root/deadlock-list') AS x(y); GO CREATE FUNCTION [dbo].[UNF_DEADLOCK_VIEW] ( @deadlock XML ) RETURNS TABLE AS RETURN ( SELECT [PagelockObject] = @deadlock.value('/deadlock-list[1]/deadlock[1]/resource-list[1]/pagelock[1]/@objectname', 'varchar(200)'), [DeadlockObject] = @deadlock.value('/deadlock-list[1]/deadlock[1]/resource-list[1]/objectlock[1]/@objectname', 'varchar(200)'), [KeylockObject] = Keylock.Process.value('@objectname', 'varchar(200)'), [Index] = Keylock.Process.value('@indexname', 'varchar(200)'), [IndexLockMode] = Keylock.Process.value('@mode', 'varchar(5)'), [Victim] = case when Deadlock.Process.value('@id', 'varchar(50)') = @deadlock.value('/deadlock-list[1]/deadlock[1]/@victim', 'varchar(50)') then 1 else 0 end, [Procedure] = Deadlock.Process.value('executionStack[1]/frame[1]/@procname[1]', 'varchar(200)'), [LockMode] = Deadlock.Process.value('@lockMode', 'char(1)'), [Code] = Deadlock.Process.value('executionStack[1]/frame[1]', 'varchar(1000)'), [ClientApp] = Deadlock.Process.value('@clientapp', 'varchar(100)'), [HostName] = Deadlock.Process.value('@hostname', 'varchar(20)'), [LoginName] = Deadlock.Process.value('@loginname', 'varchar(20)'), [TransactionTime] = Deadlock.Process.value('@lasttranstarted', 'datetime'), [InputBuffer] = Deadlock.Process.value('inputbuf[1]', 'varchar(1000)') from @deadlock.nodes('/deadlock-list/deadlock/process-list/process') as Deadlock(Process) LEFT JOIN @deadlock.nodes('/deadlock-list/deadlock/resource-list/keylock') as Keylock(Process) ON Keylock.Process.value('owner-list[1]/owner[1]/@id', 'varchar(50)') = Deadlock.Process.value('@id', 'varchar(50)') ); GO -------------------------------------------------------------------------------------- -- 경고 및 JOB 추가 -------------------------------------------------------------------------------------- USE [msdb] GO EXEC sp_add_job @job_name = '[경고] 데드락발생' EXEC sp_add_jobstep @job_name = '[경고] 데드락발생' , @step_id = 1 , @step_name = '데드락발생' , @subsystem = 'TSQL' , @command = 'EXEC dbo.Usp_Ins_DeadLockCount' , @database_name = 'DBA' EXEC sp_add_jobserver @job_name = '[경고] 데드락발생' , @server_name = N'(local)' GO EXEC sp_add_alert @name = '[경고] 데드락발생경고' , @message_id = 0 , @severity = 0 , @enabled = 1 , @delay_between_responses = 0 , @include_event_description_in = 0 , @category_name = N'[Uncategorized]' , @performance_condition = N'SQLServer:Locks|Number of Deadlocks/sec|_Total|>|0' , @job_name = '[경고] 데드락발생' GO
나. 데드락 발생
USE DBA GO Create table dbo.Cat ( Thing1 int not null ); Create table dbo.Hat ( Thing2 int not null ); insert into dbo.Cat values(1); insert into dbo.Hat values(1); go -- sesssion 1 BEGIN TRANSACTION UPDATE dbo.Hat SET Thing2 = 1 -- session 2 BEGIN TRANSACTION UPDATE dbo.Cat SET Thing1 = 1 -- sesssion 1 UPDATE dbo.Cat SET Thing1 = 1 -- session 2 UPDATE dbo.Hat SET Thing2 = 1
다. 데드락 정보 확인
SELECT * FROM dbo.TblAlert T1 CROSS APPLY dbo.UNF_DEADLOCK_VIEW( T1.DeadLocks ) T2
'SQL Server 2008' 카테고리의 다른 글
SQL Server 2008, 2008 R2 진단 쿼리 (0) | 2012.02.24 |
---|---|
DML 변경 내용 추적하기 (0) | 2011.08.09 |
BACKUP LOG WITH TRUNCATE_ONLY - SQL2008에서 더이상 사용할 수 없는 기능 (1) | 2011.05.12 |
Myths and misconceptions: 60-page PDF of blog posts (0) | 2010.11.03 |
server collation과 database collation을 한번에 바꾸기 (0) | 2010.11.01 |