SqlServer监控阻塞表、SQL语句宝典

模拟阻塞:

打开两个窗口:
窗口一:

 BEGIN TRANSACTION--开始事务
 update tblUser set [Password] = '00000' where id = 1
 --等待1分钟
 WAITFOR DELAY '00:1'; 
 

窗口二:

 select * from tblUser where id = 1
 

查询阻塞:(当前被阻塞的进程id,不一定是它阻塞其他进程,有可能是它被其他进程阻塞)

select
    request_session_id spid,
    OBJECT_NAME(resource_associated_entity_id) tableName
from
    sys.dm_tran_locks
where
    resource_type='OBJECT'

查看阻塞的语句:(根据上面查询出来的阻塞进程id)

DBCC INPUTBUFFER (54)

杀死死锁进程:(根据上面查询出来的阻塞进程id)

kill 55

知识点:WAITFOR DELAY

WAITFOR是SQL Server中Transact-SQL提供的一个流程控制语句。它的作用就是等待特定时间,然后继续执行后续的语句。它包含一个参数DELAY,用来指定等待的时间。
WAITFOR DELAY '0:0:4'--  表示延迟4秒,再继续执行。

进化版一:

查阻塞进程,及是谁在阻塞,还有阻塞的表:

select t1.spid as '等待的进程id',
    OBJECT_NAME(t2.resource_associated_entity_id) as '等待进程-表' ,
    t1.blocked as '阻塞的进程id',
    OBJECT_NAME(t3.resource_associated_entity_id) as '阻塞进程-表',
    tt1.hostname as '阻塞进程-hostname',
    tt1.nt_domain as '阻塞进程-nt_domain',
    tt1.nt_username as '阻塞进程-nt_username',
    tt1.loginame as '阻塞进程-loginame'
from (
select 0 as spid ,blocked
from (
    select * from master..sysprocesses where blocked > 0
) a
where not exists (
    select * from (select * from master..sysprocesses where blocked > 0 ) b
    where a.blocked=spid
)
union
select spid,blocked from master..sysprocesses where blocked > 0
) t1
inner join master..sysprocesses tt1 on t1.blocked = tt1.spid
left join sys.dm_tran_locks t2 on t1.spid = t2.request_session_id and t2.resource_type = 'OBJECT'
left join sys.dm_tran_locks t3 on t1.blocked = t3.request_session_id and t3.resource_type = 'OBJECT'

进化版二:(最实用,上面的精简版)

查阻塞数据库的进程id,把这些进程kill掉就可以了;

select t1.blocked as '阻塞的进程id',
    OBJECT_NAME(t2.resource_associated_entity_id) as '阻塞的表',
    t3.hostname as '阻塞进程-hostname',
    t3.nt_domain as '阻塞进程-nt_domain',
    t3.nt_username as '阻塞进程-nt_username',
    t3.loginame as '阻塞进程-loginame'
from master..sysprocesses t1
inner join sys.dm_tran_locks t2 on t1.blocked = t2.request_session_id and t2.resource_type = 'OBJECT'
inner join master..sysprocesses t3 on t1.blocked = t3.spid
where t1.blocked > 0

进化版三:(信息最全)

查看等待的进程、阻塞的进程执行的语句,账号,地址等信息;

SELECT
   WT.session_id AS '等待的进程',
   DB_NAME(TL.resource_database_id) AS '数据库名',
   (select OBJECT_NAME(resource_associated_entity_id) --resource_associated_entity_id为Bigint类型,而Object_Name方法参数为int,有可能出现转换失败的情况
   from sys.dm_tran_locks
   where request_session_id = WT.blocking_session_id
   and resource_type = 'OBJECT') as '表名',
   WT.wait_duration_ms,
   TL.request_mode,
   (SELECT SUBSTRING(ST.text, (ER.statement_start_offset/2) + 1,
      ((CASE ER.statement_end_offset
         WHEN -1 THEN DATALENGTH(ST.text)
         ELSE ER.statement_end_offset
        END - ER.statement_start_offset)/2) + 1)
   FROM sys.dm_exec_requests AS ER
      CROSS APPLY sys.dm_exec_sql_text(ER.sql_handle) AS ST
   WHERE ER.session_id = TL.request_session_id)
      AS '等待执行的sql',
   WT.blocking_session_id as '阻塞的进程',
   WT.resource_description AS blocking_resource_description,
   CASE WHEN WT.blocking_session_id > 0 THEN
      (SELECT ST2.text FROM sys.sysprocesses AS SP
             CROSS APPLY sys.dm_exec_sql_text(SP.sql_handle) AS ST2
      WHERE SP.spid = WT.blocking_session_id)
      ELSE NULL
   END AS '阻塞进程执行的sql',
    SPP.hostname as '阻塞进程-hostname',
    SPP.nt_domain as '阻塞进程-nt_domain',
    SPP.nt_username as '阻塞进程-nt_username',
    SPP.loginame as '阻塞进程-loginame'
FROM sys.dm_os_waiting_tasks AS WT
   JOIN sys.dm_tran_locks AS TL
   ON WT.resource_address = TL.lock_owner_address
   inner join sys.sysprocesses as SPP on WT.blocking_session_id = SPP.spid
WHERE WT.wait_duration_ms > 5000--等待5s以上的
   AND WT.session_id > 50;

进化版四:

一、查看阻塞进程及语句:exec sp_who_lock(在master数据库下)
二、解决阻塞:exec p_killspid 'DBName'(在master数据库下)

创建存储过程,查当前阻塞:

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[sp_who_lock]    Script Date: 2018/4/14 22:26:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create procedure [dbo].[sp_who_lock]
as
begin
declare @spid int,@bl int,
@intTransactionCountOnEntry int,
        @intRowcount    int,
        @intCountProperties   int,
        @intCounter    int

create table #tmp_lock_who (
id int identity(1,1),
spid smallint,
bl smallint)

IF @@ERROR<>0 RETURN @@ERROR

insert into #tmp_lock_who(spid,bl) select 0 ,blocked
   from (select * from sysprocesses where blocked>0 ) a
   where not exists(select * from (select * from sysprocesses where blocked>0 ) b
   where a.blocked=spid)
   union select spid,blocked from sysprocesses where blocked>0

IF @@ERROR<>0 RETURN @@ERROR

-- 找到临时表的记录数
select @intCountProperties = Count(*),@intCounter = 1
from #tmp_lock_who

IF @@ERROR<>0 RETURN @@ERROR

if @intCountProperties=0
select '现在没有阻塞和死锁信息' as message

-- 循环开始
while @intCounter <= @intCountProperties
begin
-- 取第一条记录
select @spid = spid,@bl = bl
from #tmp_lock_who where Id = @intCounter
begin
if @spid =0
            select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'
else
            select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'
DBCC INPUTBUFFER (@bl )
end

-- 循环指针下移
set @intCounter = @intCounter + 1
end

drop table #tmp_lock_who

return 0
end

创建存储过程,解除阻塞:

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[p_killspid]    Script Date: 2018/4/14 22:18:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

create proc [dbo].[p_killspid]
@dbname varchar(200)    --要关闭进程的数据库名
as
    declare @sql nvarchar(500)
    declare @spid nvarchar(20)

    declare #tb cursor for
        --select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname) --杀所有当前阻塞在数据库中的进程
        select spid=cast(blocked as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname) and blocked > 0 --只杀阻塞其他进程的进程
    open #tb
    fetch next from #tb into @spid
    while @@fetch_status=0
    begin
        exec('kill '+@spid)
        fetch next from #tb into @spid
    end
    close #tb
    deallocate #tb
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值