查询Sqlserver数据库死锁的一个存储过程分享

查询Sqlserver数据库死锁的一个存储过程分享

在Sqlserver数据库中,死锁是不可避免的。为了避免死锁对系统造成影响,需要及时监控和排查死锁的情况。本文将介绍一个可以查询Sqlserver数据库死锁的存储过程,并通过代码示例演示如何使用。

1. 存储过程介绍

本文要介绍的存储过程名为GetDeadlockInfo,它是一个开源的存储过程,可以查询Sqlserver数据库中的死锁信息。具体包含以下信息:

- 死锁发生的时间

- 死锁的进程ID

- 死锁的状态

- 死锁的数据库名

- 死锁的用户

- 死锁的表名

- 死锁的语句

2. 存储过程实现代码

下面是GetDeadlockInfo存储过程的详细实现代码:

CREATE PROCEDURE [dbo].[GetDeadlockInfo]

AS

BEGIN

SET NOCOUNT ON;

WITH Deadlock (Date,DeadlockGraph)

AS

(

select

CAST(xml_deadlock_report AS XML).value('(//@timestamp)[1]','datetime2') AS Date,

xml_deadlock_report as DeadlockGraph

from

sys.dm_os_ring_buffers

where

ring_buffer_type = 'RING_BUFFER_DEADLOCK'

)

SELECT

Deadlock.Date,

Deadlock.DeadlockGraph,

DB_NAME(B.database_id) AS [database_name],

(SELECT

CONVERT(nvarchar(10),[timestamp],120) + ' '

+ CONVERT(nvarchar(8),[timestamp],108) + ' '

+ CASE

[transaction_type]

WHEN 1 THEN 'Read'

WHEN 2 THEN 'Write'

WHEN 3 THEN 'Exclusive'

WHEN 4 THEN 'Intent'

WHEN 5 THEN 'Shared'

WHEN 6 THEN 'Update'

END + ' '

+ '[page_id (' + CONVERT(nvarchar(30),[page_id]) + '):'

+ CONVERT(nvarchar(6),[lock_mode]) + ']'

+ ' ' + '[ObjId:'

+ CONVERT(nvarchar(10),[object_id]) + '] '

+ ' ' + '[Subresource:'

+ CONVERT(nvarchar(10),[subresource]) + '] '

+ CASE

[resource_type]

WHEN 'OBJECT' THEN ' [Result:Obj] '

WHEN 'PAGE' THEN ' [Result:Page] '

WHEN 'KEY' THEN ' [Result:Key] '

WHEN 'RID' THEN ' [Result:RID] '

ELSE ' [Result:UNK] '

END

FROM

sys.dm_tran_locks

WHERE

request_session_id IN

(SELECT

[blocked_process_report].value('(//@waiter)[1]','int')

FROM

Deadlock

CROSS APPLY [Deadlock].DeadlockGraph.nodes('//deadlock/victim-list/victimProcess') AS V([blocked_process_report])

UNION ALL

SELECT

[blocking_process_report].value('(//@spid)[1]','int')

FROM

Deadlock

CROSS APPLY [Deadlock].DeadlockGraph.nodes('//deadlock/process-list/process') AS V([blocking_process_report])

)

OR [request_owner_id] IN

(SELECT

[blocked_process_report].value('(//@waiter)[1]','int')

FROM

Deadlock

CROSS APPLY [Deadlock].DeadlockGraph.nodes('//deadlock/victim-list/victimProcess') AS V([blocked_process_report])

UNION ALL

SELECT

[blocking_process_report].value('(//@spid)[1]','int')

FROM

Deadlock

CROSS APPLY [Deadlock].DeadlockGraph.nodes('//deadlock/process-list/process') AS V([blocking_process_report])

)

ORDER BY --order them by the deadlock graph session order

Deadlock.DeadlockGraph.value('(//@spid)[1]','int'),

[blocking_process_report].value('(//@rid)[1]','int')

FOR XML PATH(''), TYPE

)

FROM

Deadlock

CROSS APPLY Deadlock.DeadlockGraph.nodes('//deadlock') AS D (DeadlockReport)

CROSS APPLY DeadlockReport.nodes('process-list/process') AS P (Process)

CROSS APPLY Process.nodes('inputbuf') AS InputBuf([inputbuf])

LEFT JOIN sys.dm_exec_requests R ON R.session_id = P.Process.value('(//@spid)[1]','int')

LEFT JOIN sys.dm_tran_database_transactions T ON P.Process.value('(/process/@transactionname)[1]','nvarchar(max)') = T.name

LEFT JOIN sys.databases B ON T.database_id = B.database_id

WHERE

Deadlock.DeadlockGraph.exist('//deadlock') = 1

ORDER BY

Deadlock.Date DESC;

END

2.1 存储过程使用说明:

- 执行GetDeadlockInfo存储过程,会返回数据库中的死锁信息。

- 执行存储过程前,必须要有足够的权限访问sys.dm_os_ring_buffers和sys.dm_tran_locks等系统表。

2.2 存储过程实现说明:

- GetDeadlockInfo存储过程使用了递归查询的方式,通过sys.dm_os_ring_buffers表查询死锁信息,使用sys.dm_tran_locks表和死锁报告的xml数据进行关联查询,最后生成死锁信息的结果集。

- Deadlock with语句用于查询sys.dm_os_ring_buffers表中的死锁信息,其中xml_deadlock_report的值为包含死锁信息的xml文档。

- 死锁信息的生成使用到了多个系统表,包括sys.dm_tran_locks、sys.dm_exec_requests、sys.dm_tran_database_transactions和sys.databases等,通过这些表的关联查询,生成包含死锁信息的结果集。

3. 使用示例

下面是使用GetDeadlockInfo存储过程查询Sqlserver数据库中的死锁信息的示例代码:

EXEC dbo.GetDeadlockInfo;

3.1 示例说明:

- 使用EXEC执行GetDeadlockInfo存储过程,会返回数据库中的死锁信息。

3.2 示例结果分析:

存储过程返回的结果集包含以下字段:

- Date:死锁发生的时间

- DeadlockGraph:死锁信息的XML文档,包含死锁进程等信息

- [database_name]:死锁所在的数据库名称

- [inputbuf]:死锁过程的相关语句

在分析存储过程返回的结果集时,可以通过查询DeadlockGraph字段的xml数据,获取更多的死锁信息,例如死锁进程的会话ID、锁类型和锁对象等。

4. 总结

本文介绍了一个用于查询Sqlserver数据库死锁信息的存储过程GetDeadlockInfo,通过代码示例演示了如何使用和分析死锁信息。在Sqlserver数据库中,死锁是不可避免的,通过及时监控和排查死锁,可以减少死锁对系统造成的影响。使用GetDeadlockInfo存储过程可以监控并及时排查Sqlserver数据库中的死锁情况,有助于保证系统稳定运行。

数据库标签