首页 > 数据库 >SQL Server 查询是否死锁与解决办法

SQL Server 查询是否死锁与解决办法

时间:2022-12-05 16:11:41浏览次数:50  
标签:-- sp Server 死锁 spid SQL 进程 blocked

  • SQL Server 查询是否死锁与解决办法

     

    Sys.SysProcesses 系统表是一个很重要的系统视图,主要用来定位与解决Sql Server的阻塞和死锁

    视图中主要的字段:
    1. Spid:Sql Servr 会话ID
    2. Kpid:Windows 线程ID
    3. Blocked:正在阻塞求情的会话 ID。如果此列为 Null,则标识请求未被阻塞
    4. Waittype:当前连接的等待资源编号,标示是否等待资源,0 或 Null表示不需要等待任何资源
    5. Waittime:当前等待时间,单位为毫秒,0 表示没有等待
    6. DBID:当前正由进程使用的数据库ID
    7. UID:执行命令的用户ID
    8. Login_time:客户端进程登录到服务器的时间。
    9. Last_batch:上次执行存储过程或Execute语句的时间。对于系统进程,将存储Sql Server 的启动时间
    10.Open_tran:进程的打开事务个数。如果有嵌套事务,就会大于1
    11.Status:进程ID 状态,dormant = 正在重置回话 ; running = 回话正在运行一个或多个批处理 ; background = 回话正在运行一个后台任务 ; rollback = 会话正在处理事务回滚 ; pending = 回话正在等待工作现成变为可用 ; runnable = 会话中的任务在等待获取 Scheduler 来运行的可执行队列中 ; spinloop = 会话中的任务正在等待自旋锁变为可用 ; suspended = 会话正在等待事件完成
    12.Hostname:建立链接的客户端工作站的名称
    13.Program_name:应用程序的名称,就是 连接字符串中配的 Application Name
    14.Hostprocess:建立连接的应用程序在客户端工作站里的进程ID号
    15.Cmd:当前正在执行的命令
    16.Loginame:登录名

    应用实例:

    1. 检查数据库是否发生阻塞

    先查找哪个链接的 blocked 字段不为0。如 SPID53的blocked 字段不为0,而是 52。SPID 52 的 blocked 为0,就可以得出结论:此时有阻塞发生,53 被 52 阻塞住了。如果你发现一个连接的 blocked 字段的值等于它自己,那说明这个连接正在做磁盘读写,它要等自己的 I/O 做完。

    2. 查找链接在那个数据库上

    检查 dbid 即可。得到 dbid,可以运行以下查询得到数据库的名字:
    Select name,dbid from master.sys.sysdatabases

    3. 查看此进程执行的SQL 是哪个,查找问题原因
    dbcc inputbuffer(spid);

    4. KILL 掉当前导致阻塞的SQL
    kill spid

    5. sql阻塞进程查询

    select A.SPID as 被阻塞进程,a.CMD AS 正在执行的操作,b.spid AS 阻塞进程号,b.cmd AS 阻塞进程正在执行的操作
    from master..sysprocesses a,master..sysprocesses b
    where a.blocked<>0 and a.blocked= b.spid
    
    exec sp_who 'active'--查看系统内所有的活动进程 BLK不为0的为死锁
    
    exec sp_lock 60 --返回某个进程对资源的锁定情况
    
    SELECT object_name(1504685104)--返回对象ID对应的对象名
    
    DBCC INPUTBUFFER (63)--显示从客户端发送到服务器的最后一个语句

    6. SQL Server简洁查询正在运行的进程SQL

    SELECT   spid,
             blocked,
             DB_NAME(sp.dbid) AS DBName,
             program_name,
             waitresource,
             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
    WHERE    spid > 50
    ORDER BY blocked DESC, DB_NAME(sp.dbid) ASC, a.[text];

    SqlServer查询和Kill进程死锁的语句

    查询死锁进程语句

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

    sqlserver检测死锁;杀死锁和进程;查看锁信息

    --检测死锁
    --如果发生死锁了,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程?
    --这时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。SQL Server自带的系统存储过程sp_who和sp_lock也可以用来查找阻塞和死锁, 但没有这里介绍的方法好用。
    use master
    go
    create procedure 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
    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_killspid]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[p_killspid]
    GO
    create proc 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)
     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
    go
    --用法 
    exec p_killspid 'newdbpy'
    --查看锁信息
    --如何查看系统中所有锁的详细信息?在企业管理管理器中,我们可以看到一些进程和锁的信息,这里介绍另外一种方法。
    --查看锁信息
    create table #t(req_spid int,obj_name sysname)
    declare @s nvarchar(4000)
     ,@rid int,@dbname sysname,@id int,@objname sysname
    declare tb cursor for
     select distinct req_spid,dbname=db_name(rsc_dbid),rsc_objid
     from master..syslockinfo where rsc_type in(4,5)
    open tb
    fetch next from tb into @rid,@dbname,@id
    while @@fetch_status=0
    begin
     set @s='select @objname=name from ['+@dbname+']..sysobjects where id=@id'
     exec sp_executesql @s,N'@objname sysname out,@id int',@objname out,@id
     insert into #t values(@rid,@objname)
     fetch next from tb into @rid,@dbname,@id
    end
    close tb
    deallocate tb
    select 进程id=a.req_spid
     ,数据库=db_name(rsc_dbid)
     ,类型=case rsc_type when 1 then 'NULL 资源(未使用)'
      when 2 then '数据库'
      when 3 then '文件'
      when 4 then '索引'
      when 5 then '表'
      when 6 then '页'
      when 7 then '键'
      when 8 then '扩展盘区'
      when 9 then 'RID(行 ID)'
      when 10 then '应用程序'
     end
     ,对象id=rsc_objid
     ,对象名=b.obj_name
     ,rsc_indid
     from master..syslockinfo a left join #t b on a.req_spid=b.req_spid
    go
    drop table #t
    © 版权声明 文章版权归作者所有,若需转载,请在显著位置标志该文章地址。

标签:--,sp,Server,死锁,spid,SQL,进程,blocked
From: https://www.cnblogs.com/zhukuntang/p/16952581.html

相关文章

  • MySQL
    一、ACID1.1原子性(Atomicity)原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做,如果事务中一个sql语句执行失败,则已执行的语句也必须回滚,数......
  • SQL查询语句的执行顺序
    SELECT语句定义SELECTDISTINCT<select_list>FROM<left_table><join_type>JOIN<right_table>ON<join_condition>WHERE<where_condition>GROUPBY<group_by_l......
  • mysql的varchar最大能存储多少个字符?
    mysql中varchar能够存储可变长度的字符串。过去我做的诸多业务中,一般存储短字符串的需求,都会使用varchar类型,并且定义长度为255,也就是varchar(255)。不过为了探究varchar......
  • mysql8 添加用户,赋予表操作权限
    1.mysql8修改了安全规则,不能像mysql5.7一次性创建用户并授权,需要分批创建1.创建用户createuser'username'@'host'identifiedby'password'创建用户说明:1.use......
  • 关于 SAP HANA 数据库的死锁问题(deadlock)
    一个朋友在我的知识星球里提问:hana数据库发生死锁后,会自动解开吗?还是会等着自动超时后报错。笔者在15年的SAP开发生涯中对HANA数据库接触得比较少,这里只能根据网络上......
  • postgresql序列基本操作
    1、创建序列CREATESEQUENCEifnotexiststest_mergetable_id_seqINCREMENT1MINVALUE1MAXVALUE999999999START1CACHE1;//或者:createsequenceifnotexis......
  • Kettle:跨库(SQLServer->PostgreSQL)同步多张表数据的详细设计过程
    〇、参考地址1、多个Excel实现同步​​https://www.wangt.cc/2021/05/kettle%E5%A4%9A%E4%B8%AA%E8%A1%A8%E4%B8%80%E8%B5%B7%E8%BF%81%E7%A7%BB-%E9%80%9A%E8%BF%87%E9%85%......
  • Windows Server部署.net Core应用
    安装.netcorewindowserverhosting重启IISiisreset参考文档:​​​https://docs.microsoft.com/en-us/aspnet/core/publishing/iis?tabs=aspnetcore2x​​​​​https:......
  • CodeSmith部署安装以及编写MySQL模板的时候无法获取description
    最近需要使用VS2015开发新项目,由于考虑到后期的扩展性,打算使用EF的codefirst模式来编写,但是前期又设计好了数据库结构,不想大动干戈的去重新写代码,网上搜索了说用“EntityF......
  • C# 使用Mono.SQLite进行跨平台开发
    SQLite安装1.windows安装1.进入官网下载最新的SQLite版本,找到:sqlite-tools-osx-x86-3150100.zip。[不区分64位和32位]​​http://www.sqlite.org/download.html​​2.......