SQL数据库死锁查询语句整理

2025-07-07 04:03:37 2102

1.查询数据库

Select name, --数据库名

dbid --数据ID

from master.sys.sysdatabases

2.查询死锁语句及内容

SELECT * FROM sys.sysprocesses

where spid >50 and blocked <> 0

select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName,*

from sys.dm_tran_locks

where resource_type='OBJECT'

说明 死锁必定是blocked‌ <>0

block 输出的ID是当前死锁的ID:假设ID是1991,所以要解决死锁就是要KILL掉即 【 kill 1991 】

spid --SQL Server会话ID

kpid ‌--Windows线程ID。

‌blocked‌,--正在阻塞其他会话的会话ID。如果此列为Null,则表示请求未被阻塞。

‌waittype,--当前连接的等待资源编号,0或Null表示不需要等待任何资源。

‌waittime‌,--当前等待时间,单位为毫秒,0表示没有等待。

‌dbid,‌--当前正由进程使用的数据库ID。

‌uid‌,--执行命令的用户ID。

‌login_time‌,--客户端进程登录到服务器的时间。

‌last_batch‌‌,--上次执行存储过程或Execute语句的时间。对于系统进程,将存储Sql Server的启动时间。

‌open_tran‌,‌--进程的打开事务个数。如果有嵌套事务,就会大于1。

‌status‌,‌--进程状态,如dormant(正在重置会话)、running(会话正在运行一个或多个批处理)、background(会话正在运行一个后台任务)、rollback(会话正在处理事务回滚)、pending(会话正在等待工作线程变为可用)、runnable(会话中的任务在等待获取Scheduler来运行的可执行队列中)、spinloop(会话中的任务正在等待自旋锁变为可用)、suspended(会话正在等待事件完成)‌3。

‌hostname‌‌,--建立链接的客户端工作站的名称。

‌program_name‌,‌--应用程序的名称,即连接字符串中配置的应用程序名称。

‌hostprocess‌‌,--建立连接的应用程序在客户端工作站里的进程ID号。

‌cmd‌‌,--当前正在执行的命令。

‌loginame‌--登录名‌。

3.查询CPU消耗时间

SELECT TOP 20

total_worker_time/1000 AS [总消耗CPU 时间(ms)],execution_count [运行次数],

qs.total_worker_time/qs.execution_count/1000 AS [平均消耗CPU 时间(ms)],

last_execution_time AS [最后一次执行时间],max_worker_time /1000 AS [最大执行时间(ms)],

SUBSTRING(qt.text,qs.statement_start_offset/2+1,

(CASE WHEN qs.statement_end_offset = -1

THEN DATALENGTH(qt.text)

ELSE qs.statement_end_offset END -qs.statement_start_offset)/2 + 1)

AS [使用CPU的语法], qt.text [完整语法],

dbname=db_name(qt.dbid),

object_name(qt.objectid,qt.dbid) ObjectName

FROM sys.dm_exec_query_stats qs WITH(nolock)

CROSS apply sys.dm_exec_sql_text(qs.sql_handle) AS qt

WHERE execution_count>1

ORDER BY total_worker_time DESC

4.状态说明

SQL 系统进程的运行(status)状态(Runnable、Running、Suspended、Sleeping、Pending、Dormant、Background、Spinlock)1pending(等待)代表这个process,既没有Thread可用,也没有CPU可用,正在同时等待这两项系统资源。2runnable代表这个process,有Thread可用,但没有CPU可用,所以它正在等待CPU这项系统资源。3runningprocess,有Thread可用,有CPU可用。4suspended(暂停)process,正在「等待」别的process执行,等待的系统资源可能是Disk I/O或数据库的Lock。(若这个process执行的SELECT没加上NOLOCK关键字,而别的process正在进行「交易」或写入(会加Lock),则这个SELECT的process就会呈现“suspended”的状态。)5sleepingprocess,目前没在做任何事,正在等待进一步的指令。(sleeping 代表建立了数据库连接,但程序没有发出SQL命令. 因为应用程序为了减少打开和关闭连接的开销,在完成数据库中的操作后,仍然保持数据库的连接,这些连接的最主要目的是重用。)6dormant(暂时搁置)SQL Server正在对这个process做reset。7backgroundprocess正在SQL Server背景执行。即使你看到有很多“background”process正在执行,也不必担心。8Spinlock(自旋锁)查询处于某种运行模式,它在CPU中忙于等待自己的轮询。

5.查询超时语句及记录

SELECT Status, --进程ID 状态:dormant(重置),running(有CPU可用)....

--1.dormant = 正在重置回话((暂时搁置),代表SQL Server正在对这个process做reset) ;

--2.running = 回话正在运行一个或多个批处理 ;

--3.background = 回话正在运行一个后台任务 ;

--4.rollback = 会话正在处理事务回滚 ;

--6.pending = 回话正在等待工作现成变为可用 ;

--7.runnable = 会话中的任务在等待获取 Scheduler 来运行的可执行队列中 ;

--8.spinloop = 会话中的任务正在等待自旋锁变为可用 ;

--9.suspended = 会话正在等待事件完成

login_time,--客户端进程登录到服务器的时间

last_batch,--上次执行存储过程或Execute语句的时间。对于系统进程,将存储Sql Server的启动时间。

spid, --SQL Server会话ID

blocked, --正在阻塞其他会话的会话ID

object_name(C.resource_associated_entity_id) as TABLENAME,

sp.dbid, --进程使用的数据库ID

DB_NAME(sp.dbid) AS DBName,--进程使用的数据库名

program_name,--应用程序的名称,就是 连接字符串中配的 Application Name

waitresource, --当前连接的等待资源编号,标示是否等待资源,0 或 Null表示不需要等待任何资源

lastwaittype,

sp.loginame, --登入数据库名

sp.hostname, --使用主机名

a.[Text] AS [TextData],--查询语句

SUBSTRING ( A. TEXT,sp.stmt_start / 2,(CASE WHEN sp.stmt_end = - 1 THEN DATALENGTH (A. TEXT) ELSE sp.stmt_end END - sp.stmt_start) / 2) AS [current_cmd] --当前命令

FROM sys.sysprocesses AS sp OUTER APPLY sys.dm_exec_sql_text (sp.sql_handle) AS A ,sys.dm_tran_locks C

WHERE spid > 50 AND

blocked >0 AND --查询blocked字段来找出正在阻塞其他会话的进程

request_session_id =spid AND resource_type = 'OBJECT'

--ORDER BY blocked DESC,

--DB_NAME(sp.dbid) ASC,

--a.[text];

6.创建表格记录及存储过程

USE [KingFa_SH]

GO

/****** Object: StoredProcedure [dbo].[SP_WCS_LOCK] Script Date: 2024/12/13 16:30:41 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

ALTER PROCEDURE [dbo].[SP_WCS_LOCK]

-- =============================================

-- WCS JOB自动处理-- Create by FISH

-- DATE 2024.12.12

-- MOD USER&DATE

-- =============================================

AS

BEGIN TRY

BEGIN TRAN -----开始事务

INSERT INTO A_LOCK_LOG(Status,login_time,last_batch,spid,blocked,TABLENAME,dbid,DBName,program_name,waitresource,lastwaittype,loginame,hostname,TextData,current_cmd)

SELECT Status, --进程ID 状态:dormant(重置),running(有CPU可用)....

--1.dormant = 正在重置回话((暂时搁置),代表SQL Server正在对这个process做reset) ;

--2.running = 回话正在运行一个或多个批处理 ;

--3.background = 回话正在运行一个后台任务 ;

--4.rollback = 会话正在处理事务回滚 ;

--6.pending = 回话正在等待工作现成变为可用 ;

--7.runnable = 会话中的任务在等待获取 Scheduler 来运行的可执行队列中 ;

--8.spinloop = 会话中的任务正在等待自旋锁变为可用 ;

--9.suspended = 会话正在等待事件完成

login_time,--客户端进程登录到服务器的时间

last_batch,--上次执行存储过程或Execute语句的时间。对于系统进程,将存储Sql Server的启动时间。

spid, --SQL Server会话ID

blocked, --正在阻塞其他会话的会话ID

object_name(C.resource_associated_entity_id) as TABLENAME,

sp.dbid, --进程使用的数据库ID

DB_NAME(sp.dbid) AS DBName,--进程使用的数据库名

program_name,--应用程序的名称,就是 连接字符串中配的 Application Name

waitresource, --当前连接的等待资源编号,标示是否等待资源,0 或 Null表示不需要等待任何资源

lastwaittype,

sp.loginame, --登入数据库名

sp.hostname, --使用主机名

a.[Text] AS [TextData],--查询语句

SUBSTRING ( A. TEXT,sp.stmt_start / 2,(CASE WHEN sp.stmt_end = - 1 THEN DATALENGTH (A. TEXT) ELSE sp.stmt_end END - sp.stmt_start) / 2) AS [current_cmd] --当前命令

FROM sys.sysprocesses AS sp OUTER APPLY sys.dm_exec_sql_text (sp.sql_handle) AS A ,sys.dm_tran_locks C

WHERE spid > 50 AND

blocked >0 AND --查询blocked字段来找出正在阻塞其他会话的进程

request_session_id =spid AND resource_type = 'OBJECT'

AND SPID <>blocked --2024 ADD 有时候存在两个ID一样,还是记录很多的资料!!!

--ORDER BY blocked DESC,

--DB_NAME(sp.dbid) ASC,

--a.[text];

COMMIT TRAN

RETURN(0)

END TRY

BEGIN CATCH

IF @@TRANCOUNT > 0

BEGIN

ROLLBACK TRAN

END

RETURN(1)

END CATCH

7.汇总集合 ---恶意TEST模拟长期锁定 WAITFOR DELAY '00:05:30'的时候 block 不会>0

恶意TEST模拟长期锁定 WAITFOR DELAY '00:05:30'的时候 block 不会>0!!!!!!!

所以上述5的 blocked>0 无法查询出来!

如果有PAGE 或KEY 会导致 OBJECT_NAME(resource_associated_entity_id) AS LOCK_NAME -- 锁定对象名 会报错!!!!!!

所以在WHERE语句加入 resource_type = ‘OBJECT’ ,否则就不要 OBJECT_NAME(resource_associated_entity_id) AS LOCK_NAME

应该使用如下

select distinct

b.blocked,

c.resource_type -- as [资源锁定类型]

--object --表,可以用 OBJECT_NAME(resource_associated_entity_id)

--key 或page 有行锁 或 页锁,所以影响不大,但是如果有行/页

--- OBJECT_NAME(resource_associated_entity_id) 会报错!!!!!

--DATABASE

, b.loginame --登入数据库名

, b.hostname --使用主机名

, DB_NAME(resource_database_id) AS DB_NAME -- 数据库名

, OBJECT_NAME(resource_associated_entity_id) AS LOCK_NAME -- 锁定对象名

, c.resource_associated_entity_id AS LOCK_ID -- 锁定对象

, c.request_mode AS LOCK_MODE -- 等待者请求的锁定模式

, c.request_session_id AS WAIT_ID -- 等待者SID,表示持有锁的会话 ID,也就是 SPID。

, a.wait_duration_ms AS WAIT_TIME -- 等待时间

-- , b.waittime -- 等待时间-X

, b.status --当前等待状态

, b.last_batch --最后更新时间

, (select TEXT

from sys.dm_exec_requests r

cross apply

sys.dm_exec_sql_text(r.sql_handle)

where r.session_id = a.session_id) as WAIT_DO_SQL-- 等待者要执行的SQL

, (select TEXT

from sys.sysprocesses p

cross apply

sys.dm_exec_sql_text(p.sql_handle)

where p.spid = a.session_id

) as LOCK_DO_SQL --锁定者执行语句

from sys.dm_os_waiting_tasks A,sys.sysprocesses(NOLOCK) b,sys.dm_tran_locks c

where b.spid =A.session_id --and b.waittime >10000

and c.request_session_id =a.session_id

and c.resource_type ='object ' ---请加上!!!谢谢!!!!

要解锁就是: kill 77