查询数据库死锁

本文介绍了一个用于查询SQL Server中锁定情况的存储过程sp_Locks。该存储过程通过不同的模式参数返回不同级别的锁定信息,包括阻塞会话、被阻塞会话及其对应的SQL语句等详细数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[sp_Locks]    Script Date: 11/28/2012 17:24:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


  
ALTER PROCEDURE [dbo].[sp_Locks]
(
@Mode int = 2
,@Wait_Duration_ms int = 1000 /* 1 seconds */
)

AS    
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;




--EXEC sp_Locks @Mode = 3, @Wait_Duration_ms = 1000




/* return the one result set */
IF @Mode = 1
BEGIN;
SELECT
    t.blocking_session_id AS blocking
   ,t.session_id AS blocked
   ,p2.[program_name] AS program_blocking
   ,p1.[program_name] AS program_blocked   
   ,DB_NAME(l.resource_database_id) AS [database]
   ,p2.[hostname] AS host_blocking
   ,p1.[hostname] AS host_blocked   
   ,t.wait_duration_ms
   ,l.request_mode
   ,l.resource_type
   ,t.wait_type  
   ,(SELECT SUBSTRING(st.text, (r.statement_start_offset/2) + 1, ((CASE r.statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE r.statement_end_offset END - r.statement_start_offset)/2) + 1) FROM sys.dm_exec_requests AS r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st WHERE r.session_id = l.request_session_id) AS statement_blocked
   ,CASE WHEN t.blocking_session_id > 0 THEN (SELECT st.text FROM sys.sysprocesses AS p CROSS APPLY sys.dm_exec_sql_text(p.sql_handle) AS st WHERE p.spid = t.blocking_session_id) ELSE NULL END AS statement_blocking  
   --,t.resource_description AS blocking_resource_description
   --,l.resource_associated_entity_id
FROM sys.dm_os_waiting_tasks AS t
INNER JOIN sys.dm_tran_locks AS l ON t.resource_address = l.lock_owner_address
INNER JOIN sys.sysprocesses p1 ON p1.spid = t.session_id
INNER JOIN sys.sysprocesses p2 ON p2.spid = t.blocking_session_id
WHERE t.session_id > 50
AND t.wait_duration_ms > @Wait_Duration_ms;
END;




/* return the first two result sets */
IF @Mode = 2
BEGIN;
SELECT 
spid
,[status]
,CONVERT(CHAR(3), blocked) AS blocked
,loginame 
,SUBSTRING([program_name] ,1,25) AS program
,SUBSTRING(DB_NAME(p.dbid),1,10) AS [database]
,SUBSTRING(hostname, 1, 12) AS host
,cmd
,waittype
,t.[text]
FROM sys.sysprocesses p
CROSS APPLY sys.dm_exec_sql_text (p.sql_handle) t
WHERE spid IN (SELECT blocked FROM sys.sysprocesses WHERE blocked <> 0) AND blocked = 0;




SELECT
    t.blocking_session_id AS blocking
   ,t.session_id AS blocked
   ,p2.[program_name] AS program_blocking
   ,p1.[program_name] AS program_blocked   
   ,DB_NAME(l.resource_database_id) AS [database]
   ,p2.[hostname] AS host_blocking
   ,p1.[hostname] AS host_blocked   
   ,t.wait_duration_ms
   ,l.request_mode
   ,l.resource_type
   ,t.wait_type  
   ,(SELECT SUBSTRING(st.text, (r.statement_start_offset/2) + 1, ((CASE r.statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE r.statement_end_offset END - r.statement_start_offset)/2) + 1) FROM sys.dm_exec_requests AS r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st WHERE r.session_id = l.request_session_id) AS statement_blocked
   ,CASE WHEN t.blocking_session_id > 0 THEN (SELECT st.text FROM sys.sysprocesses AS p CROSS APPLY sys.dm_exec_sql_text(p.sql_handle) AS st WHERE p.spid = t.blocking_session_id) ELSE NULL END AS statement_blocking  
FROM sys.dm_os_waiting_tasks AS t
INNER JOIN sys.dm_tran_locks AS l ON t.resource_address = l.lock_owner_address
INNER JOIN sys.sysprocesses p1 ON p1.spid = t.session_id
INNER JOIN sys.sysprocesses p2 ON p2.spid = t.blocking_session_id
WHERE t.session_id > 50
AND t.wait_duration_ms > @Wait_Duration_ms;
END;




/* return all three result sets */
IF @Mode = 3
BEGIN;
SELECT 
spid
,[status]
,CONVERT(CHAR(3), blocked) AS blocked
,loginame 
,SUBSTRING([program_name], 1, 25)AS program
,SUBSTRING(DB_NAME(p.dbid), 1, 10)AS [database]
,SUBSTRING(hostname, 1, 12)AS host
,cmd
,waittype
,t.[text]
FROM sys.sysprocesses p
CROSS APPLY sys.dm_exec_sql_text (p.sql_handle) t
WHERE spid IN (SELECT blocked FROM sys.sysprocesses WHERE blocked <> 0) AND blocked = 0;



SELECT
    t.blocking_session_id AS blocking
   ,t.session_id AS blocked
   ,SUBSTRING(p2.[program_name], 1, 25) AS program_blocking
   ,SUBSTRING(p1.[program_name], 1, 25) AS program_blocked   
   ,DB_NAME(l.resource_database_id) AS [database]
   ,p2.[hostname] AS host_blocking
   ,p1.[hostname] AS host_blocked   
   ,t.wait_duration_ms
   ,l.request_mode
   ,l.resource_type
   ,t.wait_type  
   ,(SELECT SUBSTRING(st.text, (r.statement_start_offset/2) + 1, ((CASE r.statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE r.statement_end_offset END - r.statement_start_offset)/2) + 1) FROM sys.dm_exec_requests AS r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st WHERE r.session_id = l.request_session_id) AS statement_blocked
   ,CASE WHEN t.blocking_session_id > 0 THEN (SELECT st.text FROM sys.sysprocesses AS p CROSS APPLY sys.dm_exec_sql_text(p.sql_handle) AS st WHERE p.spid = t.blocking_session_id) ELSE NULL END AS statement_blocking  
   --,t.resource_description AS blocking_resource_description
   --,l.resource_associated_entity_id
FROM sys.dm_os_waiting_tasks AS t
INNER JOIN sys.dm_tran_locks AS l ON t.resource_address = l.lock_owner_address
INNER JOIN sys.sysprocesses p1 ON p1.spid = t.session_id
INNER JOIN sys.sysprocesses p2 ON p2.spid = t.blocking_session_id
WHERE t.session_id > 50
AND t.wait_duration_ms > @Wait_Duration_ms;




SELECT DISTINCT
r.session_id AS spid
,r.percent_completeAS [percent]
,r.open_transaction_count AS open_trans
,r.[status]
,r.reads
,r.logical_reads
,r.writes
,s.cpu
,DB_NAME(r.database_id)AS [db_name]
,s.[hostname]
,s.[program_name] 
--,s.loginame 
--,s.login_time 
,r.start_time
--,r.wait_type
,r.wait_time 
,r.last_wait_type
,r.blocking_session_idAS blocking
,r.command 
,(SELECT SUBSTRING(text, statement_start_offset/2 + 1,(CASE WHEN statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX),text)) * 2 ELSE statement_end_offset END - statement_start_offset)/2) FROM sys.dm_exec_sql_text(r.sql_handle)) AS [statement]
,t.[text]
--,query_plan 
FROM sys.dm_exec_requests r
INNER JOIN sys.sysprocesses s ON s.spid = r.session_id
CROSS APPLY sys.dm_exec_sql_text (r.sql_handle) t
--CROSS APPLY sys.dm_exec_query_plan (r.plan_handle) 
WHERE r.session_id > 50 AND r.session_id <> @@spid
AND s.[program_name] NOT LIKE 'SQL Server Profiler%'
--AND db_name(r.database_id) NOT LIKE N'distribution'
--AND r.wait_type IN ('SQLTRACE_LOCK', 'IO_COMPLETION', 'TRACEWRITE')
ORDER BY s.CPU DESC;
END;

<think>嗯,用户问的是如何查询数据库死锁数据。这个问题需要分步骤来思考。首先,不同的数据库系统处理死锁的方式不同,所以得考虑主流的几种,比如MySQLSQL Server、Oracle和PostgreSQL。然后,每种数据库可能有不同的查询方法或者工具。 首先,我需要回忆一下各种数据库死锁日志机制。比如,MySQL可以通过开启InnoDB的监控来获取死锁信息,而SQL Server可能使用扩展事件或者Profiler工具。Oracle的话,可能有特定的数据字典视图,比如V$LOCK和V$SESSION,还有自动生成的跟踪文件。PostgreSQL可能需要调整日志配置,然后在日志中查找死锁信息。 接下来,用户可能需要具体的步骤,所以每个数据库的步骤要分开说明。例如,对于MySQL,需要提到设置innodb_status_output_locks,然后使用SHOW ENGINE INNODB STATUS命令。同时,用户可能需要知道如何分析输出的日志,找到LATEST DETECTED DEADLOCK部分。 还要考虑用户是否了解如何开启这些监控选项,是否需要重启服务或者动态设置。比如,在MySQL中,有些参数是动态的,可以在线设置,而有些可能需要配置文件修改后重启。需要提醒用户注意这一点。 另外,用户可能不仅想知道如何查询死锁数据,还需要如何预防或者解决死锁。虽然问题主要是查询,但可能简要提到预防措施会更好,比如合理设计事务、按顺序访问资源、设置锁超时等。 需要确保步骤清晰,避免使用过于专业的术语,但也要准确。例如,解释每个数据库的特定命令和日志位置,以及如何解读关键信息。比如,在SQL Server中使用扩展事件创建会话,然后查询xml_report字段中的死锁图。 还要注意用户可能的权限问题,比如是否有权限访问某些系统视图或修改配置参数。可能需要提醒用户需要管理员权限才能执行某些操作。 最后,总结部分要概括所有数据库的方法,并给出通用的建议,比如开启死锁日志、监控工具的使用和分析日志的方法。这样用户即使不熟悉特定数据库,也能有一个方向去查找资料。</think>以下分步骤介绍如何查询数据库死锁数据,涵盖主流数据库实现方式: 一、MySQL数据库 1. 启用InnoDB状态监控 ```sql SET GLOBAL innodb_status_output_locks = ON; -- 动态开启锁状态输出 ``` 2. 获取最近死锁信息 ```sql SHOW ENGINE INNODB STATUS\G ``` 在输出结果中查找 `LATEST DETECTED DEADLOCK` 段,包含: - 冲突的事务ID - 被锁定的表和行 - 等待资源的SQL语句 3. 日志文件监控(需配置) ```ini # my.cnf 配置 innodb_print_all_deadlocks = ON # 将所有死锁写入错误日志 ``` 二、SQL Server数据库 1. 使用扩展事件捕获 ```sql CREATE EVENT SESSION [Deadlock_Monitor] ON SERVER ADD EVENT sqlserver.xml_deadlock_report ADD TARGET package0.event_file(...); ``` 2. 查询死锁信息 ```sql SELECT event_data.value('(event/data/value/deadlock)[1]', 'varchar(max)') AS xml_report FROM sys.fn_xe_file_target_read_file(...) ``` 三、Oracle数据库 1. 查询数据字典视图 ```sql SELECT * FROM v$lock; -- 当前锁信息 SELECT * FROM v$session_wait; -- 会话等待事件 ``` 2. 分析跟踪文件 ```sql ALTER SYSTEM SET DIAGNOSTIC_DEST='/u01/app/oracle/diag'; -- 跟踪文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值