• SQL Server锁、闩等资源的阻塞诊断---osql/sqlcmd,sp_blocker_pss80


          osql/sqlcmd 工具是一个 SqlServer的命令提示符工具,我们可以使用它运行 Transact-SQL 语句和脚本文件。该工具所在目录:C:Program FilesMicrosoft SQL Server110ToolsBinn

    交互式输入 Transact-SQL 语句,如下

    C:UsersAdministrator>osql -E
    1> set nocount on;
    2> go
    1> select getdate();
    2> go
    
     -----------------------
     2015-06-20 18:02:18.053
    
    1> exit
    
    C:UsersAdministrator>

    osql的作用不仅仅局限于此,其他参数如下

    image

    强大之处在于:该工具可以结合存储过程,检查并输出锁、闩等资源的阻塞情况。

    1. 创建存储过程:sp_blocker_pss80
    2. 创建SQL脚本:定时执行sp_blocker_pss80存储过程
    3. 在osql命令中调用该SQL脚本,并将结果输出到文件

    以下分别是sp_blocker_pss80、SQL脚本、osql命令示例及对应的输出结果

    use master
    GO
    if exists (select * from sysobjects where id = object_id('dbo.sp_blocker_pss80') and sysstat & 0xf = 4)
       drop procedure dbo.sp_blocker_pss80
    GO
    create procedure dbo.sp_blocker_pss80 (@latch int = 0, @fast int = 1, @appname sysname='PSSDIAG')
    as 
    --version 16SP3
    if is_member('sysadmin')=0 
    begin
      print 'Must be a member of the sysadmin group in order to run this procedure'
      return
    end
    
    set nocount on
    SET LANGUAGE 'us_english'
    declare @spid varchar(6)
    declare @blocked varchar(6)
    declare @time datetime
    declare @time2 datetime
    declare @dbname nvarchar(128)
    declare @status sql_variant
    declare @useraccess sql_variant
    
    set @time = getdate()
    declare @probclients table(spid smallint, ecid smallint, blocked smallint, waittype binary(2), dbid smallint,
       ignore_app tinyint, primary key (blocked, spid, ecid))
    insert @probclients select spid, ecid, blocked, waittype, dbid,
       case when convert(varchar(128),hostname) = @appname then 1 else 0 end
       from sysprocesses where blocked!=0 or waittype != 0x0000
    
    if exists (select spid from @probclients where ignore_app != 1 or waittype != 0x020B)
    begin
       set @time2 = getdate()
       print ''
       print '8.2 Start time: ' + convert(varchar(26), @time, 121) + ' ' + convert(varchar(12), datediff(ms,@time,@time2))
    
       insert @probclients select distinct blocked, 0, 0, 0x0000, 0, 0 from @probclients
          where blocked not in (select spid from @probclients) and blocked != 0
    
       if (@fast = 1)
       begin
          print ''
          print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion)
    
          select spid, status, blocked, open_tran, waitresource, waittype, 
             waittime, cmd, lastwaittype, cpu, physical_io,
             memusage, last_batch=convert(varchar(26), last_batch,121),
             login_time=convert(varchar(26), login_time,121),net_address,
             net_library, dbid, ecid, kpid, hostname, hostprocess,
             loginame, program_name, nt_domain, nt_username, uid, sid,
             sql_handle, stmt_start, stmt_end
          from master..sysprocesses
          where blocked!=0 or waittype != 0x0000
             or spid in (select blocked from @probclients where blocked != 0)
             or spid in (select spid from @probclients where blocked != 0)
    
          print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) 
    
          print ''
          print 'SYSPROC FIRST PASS'
          select spid, ecid, waittype from @probclients where waittype != 0x0000
    
          if exists(select blocked from @probclients where blocked != 0)
          begin
             print 'Blocking via locks at ' + convert(varchar(26), @time, 121)
             print ''
             print 'SPIDs at the head of blocking chains'
             select spid from @probclients
                where blocked = 0 and spid in (select blocked from @probclients where spid != 0)
             if @latch = 0
             begin
                print 'SYSLOCKINFO'
                select @time2 = getdate()
    
                select spid = convert (smallint, req_spid),
                   ecid = convert (smallint, req_ecid),
                   rsc_dbid As dbid,
                   rsc_objid As ObjId,
                   rsc_indid As IndId,
                   Type = case rsc_type when 1 then 'NUL'
                                        when 2 then 'DB'
                                        when 3 then 'FIL'
                                        when 4 then 'IDX'
                                        when 5 then 'TAB'
                                        when 6 then 'PAG'
                                        when 7 then 'KEY'
                                        when 8 then 'EXT'
                                        when 9 then 'RID'
                                        when 10 then 'APP' end,
                   Resource = substring (rsc_text, 1, 16),
                   Mode = case req_mode + 1 when 1 then NULL
                                            when 2 then 'Sch-S'
                                            when 3 then 'Sch-M'
                                            when 4 then 'S'
                                            when 5 then 'U'
                                            when 6 then 'X'
                                            when 7 then 'IS'
                                            when 8 then 'IU'
                                            when 9 then 'IX'
                                            when 10 then 'SIU'
                                            when 11 then 'SIX'
                                            when 12 then 'UIX'
                                            when 13 then 'BU'
                                            when 14 then 'RangeS-S'
                                            when 15 then 'RangeS-U'
                                            when 16 then 'RangeIn-Null'
                                            when 17 then 'RangeIn-S'
                                            when 18 then 'RangeIn-U'
                                            when 19 then 'RangeIn-X'
                                            when 20 then 'RangeX-S'
                                            when 21 then 'RangeX-U'
                                            when 22 then 'RangeX-X'end,
                   Status = case req_status when 1 then 'GRANT'
                                            when 2 then 'CNVT'
                                            when 3 then 'WAIT' end,
                   req_transactionID As TransID, req_transactionUOW As TransUOW
                from master.dbo.syslockinfo s,
                   @probclients p
                where p.spid = s.req_spid
    
                print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) 
             end -- latch not set
          end
          else
             print 'No blocking via locks at ' + convert(varchar(26), @time, 121)
          print ''
       end  -- fast set
    
       else  
       begin  -- Fast not set
          print ''
          print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion)
    
          select spid, status, blocked, open_tran, waitresource, waittype, 
             waittime, cmd, lastwaittype, cpu, physical_io,
             memusage, last_batch=convert(varchar(26), last_batch,121),
             login_time=convert(varchar(26), login_time,121),net_address,
             net_library, dbid, ecid, kpid, hostname, hostprocess,
             loginame, program_name, nt_domain, nt_username, uid, sid,
             sql_handle, stmt_start, stmt_end
          from master..sysprocesses
    
          print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) 
    
          print ''
          print 'SYSPROC FIRST PASS'
          select spid, ecid, waittype from @probclients where waittype != 0x0000
    
          if exists(select blocked from @probclients where blocked != 0)
          begin
             print 'Blocking via locks at ' + convert(varchar(26), @time, 121)
             print ''
             print 'SPIDs at the head of blocking chains'
             select spid from @probclients
             where blocked = 0 and spid in (select blocked from @probclients where spid != 0)
             if @latch = 0
             begin
                print 'SYSLOCKINFO'
                select @time2 = getdate()
    
                select spid = convert (smallint, req_spid),
                   ecid = convert (smallint, req_ecid),
                   rsc_dbid As dbid,
                   rsc_objid As ObjId,
                   rsc_indid As IndId,
                   Type = case rsc_type when 1 then 'NUL'
                                        when 2 then 'DB'
                                        when 3 then 'FIL'
                                        when 4 then 'IDX'
                                        when 5 then 'TAB'
                                        when 6 then 'PAG'
                                        when 7 then 'KEY'
                                        when 8 then 'EXT'
                                        when 9 then 'RID'
                                        when 10 then 'APP' end,
                   Resource = substring (rsc_text, 1, 16),
                   Mode = case req_mode + 1 when 1 then NULL
                                            when 2 then 'Sch-S'
                                            when 3 then 'Sch-M'
                                            when 4 then 'S'
                                            when 5 then 'U'
                                            when 6 then 'X'
                                            when 7 then 'IS'
                                            when 8 then 'IU'
                                            when 9 then 'IX'
                                            when 10 then 'SIU'
                                            when 11 then 'SIX'
                                            when 12 then 'UIX'
                                            when 13 then 'BU'
                                            when 14 then 'RangeS-S'
                                            when 15 then 'RangeS-U'
                                            when 16 then 'RangeIn-Null'
                                            when 17 then 'RangeIn-S'
                                            when 18 then 'RangeIn-U'
                                            when 19 then 'RangeIn-X'
                                            when 20 then 'RangeX-S'
                                            when 21 then 'RangeX-U'
                                            when 22 then 'RangeX-X'end,
                   Status = case req_status when 1 then 'GRANT'
                                            when 2 then 'CNVT'
                                            when 3 then 'WAIT' end,
                   req_transactionID As TransID, req_transactionUOW As TransUOW
                from master.dbo.syslockinfo
    
                print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) 
             end -- latch not set
          end
          else
            print 'No blocking via locks at ' + convert(varchar(26), @time, 121)
          print ''
       end -- Fast not set
    
       print 'DBCC SQLPERF(WAITSTATS)'
       dbcc sqlperf(waitstats)
    
       Print ''
       Print '*********************************************************************'
       Print 'Print out DBCC Input buffer for all blocked or blocking spids.'
       Print '*********************************************************************'
    
       declare ibuffer cursor fast_forward for
       select distinct cast (spid as varchar(6)) as spid
       from @probclients
       where (spid <> @@spid) and 
          ((blocked!=0 or (waittype != 0x0000 and ignore_app = 0))
          or spid in (select blocked from @probclients where blocked != 0))
       open ibuffer
       fetch next from ibuffer into @spid
       while (@@fetch_status != -1)
       begin
          print ''
          print 'DBCC INPUTBUFFER FOR SPID ' + @spid
          exec ('dbcc inputbuffer (' + @spid + ')')
    
          fetch next from ibuffer into @spid
       end
       deallocate ibuffer
    
       Print ''
       Print '*******************************************************************************'
       Print 'Print out DBCC OPENTRAN for active databases for all blocked or blocking spids.'
       Print '*******************************************************************************'
       declare ibuffer cursor fast_forward for
       select distinct cast (dbid as varchar(6)) from @probclients
       where dbid != 0
       open ibuffer
       fetch next from ibuffer into @spid
       while (@@fetch_status != -1)
       begin
          print ''
          set @dbname = db_name(@spid)
          set @status = DATABASEPROPERTYEX(@dbname,'Status')
          set @useraccess = DATABASEPROPERTYEX(@dbname,'UserAccess')
          print 'DBCC OPENTRAN FOR DBID ' + @spid + ' ['+ @dbname + ']'
          if @Status = N'ONLINE' and @UserAccess != N'SINGLE_USER'
             dbcc opentran(@dbname)
          else
             print 'Skipped: Status=' + convert(nvarchar(128),@status)
                + ' UserAccess=' + convert(nvarchar(128),@useraccess)
    
          print ''
          if @spid = '2' select @blocked = 'Y'
          fetch next from ibuffer into @spid
       end
       deallocate ibuffer
       if @blocked != 'Y' 
       begin
          print ''
          print 'DBCC OPENTRAN FOR DBID  2 [tempdb]'
          dbcc opentran ('tempdb')
       end
    
       print 'End time: ' + convert(varchar(26), getdate(), 121)
    end -- All
    else
      print '8 No Waittypes: ' + convert(varchar(26), @time, 121) + ' ' 
         + convert(varchar(12), datediff(ms,@time,getdate())) + ' ' + ISNULL (@@servername,'(null)')
    GO

    创建一个SQL脚本文件:checkblk.sql

    WHILE 1=1
    BEGIN
       EXEC master.dbo.sp_blocker_pss80
       -- Or for fast mode 
       -- EXEC master.dbo.sp_blocker_pss80 @fast=1
       -- Or for latch mode 
       -- EXEC master.dbo.sp_blocker_pss80 @latch=1
       WAITFOR DELAY '00:00:15'
    END
    GO
    osql命令示例如下:
    C:>osql -E -S server -i checkblk.sql -o checkresult.txt -w 2000
    server:表示服务器的机器名
    checkblk.sql:表示输入的脚本文件
    checkresult.txt:表示输出的结果文件
    参数详情请使用命令 osql /? 查看
     
    执行结果如下:
    image
  • 相关阅读:
    属于程序员的算法
    知乎:全栈工程师讨论
    盘点2015年前20款表现出色的免费开源软件
    qt学习之路
    ubuntu联网经常掉线的解决方法
    备份书签
    linux 命令行测试网速
    linux中判断ssh是否启动
    php heredoc 与 nowdoc
    php 双向队列类
  • 原文地址:https://www.cnblogs.com/zhaoguan_wang/p/4590887.html
Copyright © 2020-2023  润新知