微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SQL Server阻塞的检查

1. 阻塞  

除了内存、cpuI/O这些系统资源以外,阻塞和死锁是影响数据库应用性能的另一大因素。

所谓的「阻塞」,是指当一个数据库会话中的事务,正在锁定其他会话事务想要读取或修改的资源,造成这些会话发出的请求进入等待的状态。sql Server 认会让被阻塞的请求无限期地一直等待,直到原来的事务释放相关的锁,或直到它超时、服务器关闭、进程被杀死。一般的系统中,偶尔有短时间的阻塞是正常且合理的;但若设计不良的程序,就可能导致长时间的阻塞,这样就不必要地锁定了资源,而且阻塞了其他会话欲读取或更新的需求。遇到这种情况,可能就需要手工排除阻塞的状态。

2.阻塞和死锁可能带来的问题

(1)并发用户少的时候,一切还都正常。但是随着并发用户增加性能越来越慢。

(2)应用程序运行很慢,但是sql Server 这个cpu和磁盘利用率很低。

(3)客户端经常受到以下错误

   Error 1222--Lock request time out period exceeded.

   Error 1205--Your transaction(process ID #XX) was deadlocked on resources with another process and has been chosen as the deadlock victim. Return your transaction.

  超时错误--Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

(4)有些查询能够进行,但是有些特定的查询修改总是不能返回。

(5)重启sql Server就能解决。但是有可能跑一段时间以后又会出现问题。

3.阻塞的检查

3.1 主要的系统表或函数

Sys.SysProcesses 系统表是一个很重要的系统视图,主要用来定位与解决sql Server的阻塞和死锁。主要字段1.Spid:sql Servr 会话ID 2.Blocked:正在阻塞求情的会话 ID。如果此列为 Null,则标识请求未被阻塞 3. Program_name:应用程序的名称,就是 连接字符串中配的 Application Name 4. Hostname:建立链接的客户端工作站的名称

sys.dm_exec_requests、sys.dm_exec_sql_text返回指定SPIDer的 sql 查询文本。

DBCC INPUTBUFFER 显示从客户端发送到 Microsoft sql Server 实例的最后一个语句。

sp_lock 系统存储过程,报告有关锁的信息。

3.2 Check逻辑

对应的存储为dblockcheck(job为DB_Lockcheck),主要Check逻辑如下:

3.3 保存的数据

所收集的数据保存dblock_@R_821_4045@ion中,主要包含信息如截图,定期的统计分析可获得经常被阻塞和引起阻塞sql语句和Table,这些信息是进行数据库优化的一个角度。

select top 100* from dblock_@R_821_4045@ion
order by TransDateTime desc 

4.代码实现

4.1 Table的创建脚本

CREATE TABLE [dbo].dblock_@R_821_4045@ion](
    ID] intIDENTITY(1,1) NOT NULL,Messagenvarchar](300) LockTypechar1) SPID1] SPID2EventType100) Parameters10) EventInfo3000) IndividualQuery1000) TransDateTimedatetimeNULL CONSTRAINT DF_dblock_@R_821_4045@ion_TransDateTime]  DEFAULT (getdate()),1)">AppNamevarchar50) HostNamePK_dblock_@R_821_4045@ionPRIMARY KEY CLUSTERED 
(
    ASC
)WITH (PAD_INDEX = OFF,STATISTICS_norECOmpuTE norE_DUP_KEY ON,ALLOW_PAGE_LOCKS ON) ON PRIMARY
) ]

4.2 存储的创建脚本

Create procedure dblockcheck] 
     @AlarmThreshold as tinyint=10
 as
set nocount on
--------------------------------------------------------------------------------------------------------
--*Program*: <dblock check for job>*Programer*:<>*Date*:<>*Description*:<Query sql Locking Process>*unify*:<UA>########## Parameter Description Begin ##########

########## Parameter Description End # ##########

##########Update Log Begin #############################Update Log End # ###################------------------------------------------------------------------------------------------------------
declare @sql varchar(200)
@Subject @Body nvarchar(max@SPName @Message nvarchar(@dbname 15@IP 20@CNT int
@cnt2 @IndividualQuery 1000@HostName 50@AppName SET @dbname=DB_NAME()

SELECT @IP'XXX.XXX.XXX.XXX'
--不手动定义IP也可通过以下函数来实现
Declare @ServerIP NVARCHAR(30)'',@SERVERNAME 60)'' 
    1 @SERVERNAME @@SERVERNAME,1)">@ServerIP=LOCAL_NET_ADDRESS
    FROM SYS.DM_EXEC_CONNECTIONS where LOCAL_NET_ADDRESS is not null
------
begin
    @spid int,1)">@bl int@intTransactionCountOnEntry @intRowcount @intCountProperties @intCounter int

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

 #tmp_lock_@R_821_4045@ion (
    id char(100arameters 10)
    )

IF @@ERROR<>0 RETURN @@ERROR
    insert into #tmp_lock_who(spid,bl) 
    select 0from (from master..sysprocesses where blocked> ) a
        where not exists( ) b
    where a.blockedspid)
    union 
    select spid,blocked 0
     找到临时表的记录数
        @intCountProperties = Count(*),1)">@intCounter = 1
             #tmp_lock_who
    @@ERROR
        if @intCountProperties0
            select N现在没有阻塞信息!' as message
             循环开始
                while <= @intCountProperties
                    begin
                     取第一条记录
                        @spid = spid,1)">@bl  bl
                            from #tmp_lock_who where Id @intCounter
                        begin
                            @IndividualQuerySUBSTRING (qr.text,qs.statement_start_offset/2CASE WHEN qs.statement_end_offset -THEN LEN(CONVERT(NVARCHAR(MAX),qr.text)) * 2 
                                           ELSE qs.statement_end_offset END - qs.statement_start_offset))
                            FROM SYS.DM_EXEC_REQUESTS qs OUTER APPLY SYS.DM_EXEC_sql_TEXT(qs.sql_handle) AS qr
                            WHERE qr.text null and qs.session_id@bl
                            @HostName=left(HostName,1); font-weight: bold">50),1)">@AppName=Left(Program_Name,1)">) 
                                With(nolock) Where SPIDset @sqlDBCC INPUTBUFFER ('+cast(20)))'
                            0
                                begin
                                    @Message=N引起数据库阻塞的是: + CAST(AS 100)) + N进程号,其执行的sql语法如下'
                                    set @sql='DBCC INPUTBUFFER ('+cast(@bl as char(20))+')'
                                    into #tmp_lock_@R_821_4045@ion(EventType,Parameters,EventInfo) exec(@sql)
                                    update #tmp_lock_@R_821_4045@ion set LockType1',SPID1@bl,SPID2@IndividualQuery,]@Message,AppName@APPName,HostNamewhere is null
                                end
                            else
                                进程号SPID:100))' 10)) +N阻塞,其当前进程执行的sql语法如下2@spid,1)">end 
                        end
                         循环指针下移
                        + 1
                    end
            drop  #tmp_lock_who
            if  #tmp_lock_@R_821_4045@ion)
            Begin

                    Insert  dblock_@R_821_4045@ion(Message,LockType,SPID1,SPID2,EventType,EventInfo,IndividualQuery,AppName,HostName) 
                    Select ],1)">Substring(EventInfo,1); font-weight: bold">500),HostName  #tmp_lock_@R_821_4045@ion

            End

             #tmp_lock_@R_821_4045@ion
            return 0
end

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐