zoukankan      html  css  js  c++  java
  • SQLServer2012基于扩展事件的阻塞监控

    转自:https://www.cnblogs.com/chhuang/p/8252310.html

    SQLServer2012基于扩展事件的阻塞监控

     

    一、前言

    SQL阻塞Block是事务联机系统OLTP的产物。由于锁导致的资源等待,事务执行时间过长,直接影响业务;了解阻塞,发现阻塞,已作为DBA日常维护的重中之重。

    通过dmv可以发现当前正在阻塞的语句,编写存储过程,使用agent作业定时执行,也能达到收集阻塞的效果;然而此方法存在一定的误差。使用扩展事件记录所有等待一定时间的阻塞,能完整的记录所有发生阻塞的SQL。

    1.1、blocked process threshold (s)

    通过以下脚本查看;默认blocked process收集不开启。

    exec sp_configure 'show advanced options',1;RECONFIGURE
    exec sp_configure 'blocked process threshold (s)';

    执行以下脚本,记录所有阻塞超过10s的进程

    USE master;
    EXEC sp_configure 'blocked process threshold (s)',10
    RECONFIGURE WITH OVERRIDE;
    1.2、blocked_process_report

    我们可以通过选择blocked_process_report扩展事件,当任务被阻塞的时间超过 sp_configure 阻塞的进程阈值设置所指定的时间时,记录阻塞信息。如下情况图所示。

    clip_image002

    二、新建扩展事件

    2.1、新建扩展事件ev_block_session

    将数据写入N'd:xe_sessionsservername_ev_block_session.xel',最大文件2M,可以循环40个文件,超过40个文件将自动删除。

    复制代码
    CREATE EVENT SESSION [ev_block_session] ON SERVER
    ADD EVENT sqlserver.blocked_process_report(
    ACTION(sqlserver.query_hash,sqlserver.query_plan_hash))
    ADD TARGET package0.event_file(SET filename=N'd:xe_sessionsservername_ev_block_session.xel',max_file_size=(2),max_rollover_files=(40))
    WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
    GO
    复制代码
    2.2、默认不启动该事件

    手动启动脚本。

    ALTER EVENT SESSION [ev_block_session] ON SERVER STATE = START

    三、分析阻塞文件

    3.1、sys.Fn_xe_file_target_read_file

    使用该系统函数,分析扩展事件文件;查出结果XML格式。

    SELECT CONVERT(XML,event_data) AS data
    sys.Fn_xe_file_target_read_file(N'd:xe_sessionsservername_ev_block_session.xel',NULL,NULL,NULL)
    3.2、分析

    新建xe_block表,将分析结果保存在在该表中。具体信息如下脚本所示;每阻塞10s时间,就会再次被记录;可以通过查询同一个transaction_id下最大monitorloop,来确定当前阻塞时间。

    复制代码
    ;WITH d AS (
    SELECT
    dateadd(hh,8,data.value('(/event/@timestamp)[1]','datetime')) timestamp,--时间戳
    data.value('(/event/data[@name="duration"]/value)[1]','bigint')/1000/1000 duration_us,--阻塞时长
    data.value('(/event/data[@name="database_name"]/value)[1]','nvarchar(128)') database_name,--阻塞数据库
    data.value('(/event/data[@name="transaction_id"]/value)[1]','bigint') transaction_id,--阻塞事务id
    data.value('(//blocked-process-report/@monitorLoop)[1]','bigint') monitorLoop,--监控自增id
    data.query('//blocked-process-report') block,--阻塞内容
    data
    FROM #event_data a
    )
    INSERT INTO xe_block(
    timestamp--时间戳
    ,duration_us--阻塞时长
    ,database_name--阻塞数据库
    ,transaction_id--阻塞事务数
    ,monitorLoop--监控增长id
    ,blocked_spid--被阻塞spid
    ,blocked_trancount--被阻塞事务
    ,blocked_waitresource--被阻塞等待资源
    ,blocked_lockmode--被阻塞等待锁
    ,blocked_hostname--被阻塞主机
    ,blocked_loginname--被阻塞用户
    ,blocked_clientapp--被阻塞客户端
    ,blocked_sql--被阻塞脚本
    ,blocking_spid--阻塞spid
    ,blocking_trancount--阻塞事务数
    ,blocking_status--阻塞状态
    ,blocking_waitresource--阻塞等待资源
    ,blocking_lockmode--阻塞锁
    ,blocking_hostname--阻塞主机
    ,blocking_loginname--阻塞用户
    ,blocking_clientapp--阻塞客户端
    ,blocking_sql--阻塞脚本
    ,data
    )
    SELECT
    d.timestamp,
    d.duration_us,
    d.database_name,
    d.transaction_id,
    d.monitorLoop,
    ed.c.value('@spid','int') blocked_spid,
    ed.c.value('@trancount','int') blocked_trancount,
    ed.c.value('@waitresource','varchar(64)') blocked_waitresource,
    ed.c.value('@lockMode','varchar(32)') blocked_lockmode,
    ed.c.value('@hostname','varchar(64)') blocked_hostname,
    ed.c.value('@loginname','varchar(64)') blocked_loginname,
    ed.c.value('@clientapp','varchar(256)') blocked_clientapp,
    ed.c.query('.').value('(/process/inputbuf)[1]','varchar(max)') blocked_sql,
    ing.c.value('@spid','int') blocking_spid,
    ing.c.value('@trancount','int') blocking_trancount,
    ing.c.value('@status','varchar(32)') blocking_status,
    ing.c.value('@waitresource','varchar(64)') blocking_waitresource,
    ing.c.value('@lockMode','varchar(32)') blocking_lockmode,
    ing.c.value('@hostname','varchar(64)') blocking_hostname,
    ing.c.value('@loginname','varchar(64)') blocking_loginname,
    ing.c.value('@clientapp','varchar(256)') blocking_clientapp,
    ing.c.query('.').value('(/process/inputbuf)[1]','varchar(max)') blocking_sql,
    data
    FROM d
    CROSS APPLY d.block.nodes('//blocked-process/process') ed(c)
    CROSS APPLY d.block.nodes('//blocking-process/process') ing(c)
    复制代码

    四、监控报警

    报警方式:统计每分钟阻塞事务数,阻塞时长,通过一定规则并通过report service发送订阅,报警如下

  • 相关阅读:
    DataAdapter的Fill方法(转)
    C#读取xml节点数据方法小结
    Service-Oriented Architecture,SOA(转)
    SOAP详解(转)
    WebService到底是什么?(转)
    只需要2个工具,百度云盘大文件就能用迅雷和IDM下载
    刘铁猛-深入浅出WPF-系列资源汇总
    WCF书籍
    书籍:wpf学习书籍介绍
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器(转)
  • 原文地址:https://www.cnblogs.com/gered/p/10490485.html
Copyright © 2011-2022 走看看