Blocked Process Report
Profiler提供一个被阻塞进程报告的事件Errors and Warnings->Blocked Process Report

指示某个任务已被阻塞,导致超过指定的时间。此事件类不包括系统任务和正在等待未发现死锁的资源的任务。若要配置报告的频率,请使用 sp_configure 命令配置阻塞的进程阈值选项。

默认阈值为0,此时出现阻塞不会触发此事件,可以使用下面脚本设置该阈值为5秒

exec sp_configure 'blocked process threshold',5;
reconfigure;
select * from sys.configurations
--where name='blocked process threshold (s)'
order by name

我们运行下面语句,创建一个阻塞的查询

--创建测试数据表
IF (SELECT OBJECT_ID('dbo.t1')
) IS NOT NULL
DROP TABLE dbo.t1
GO
CREATE TABLE dbo.t1
(c1 INT
,c2 INT
,c3 DATETIME)
INSERT INTO dbo.t1
VALUES (11, 12, GETDATE())
INSERT INTO dbo.t1
VALUES (21, 22, GETDATE()) --会话1执行
BEGIN TRAN user1
UPDATE dbo.t1 SET c3=GETDATE()
--ROLLBACK --会话2执行
BEGIN TRAN user2
SELECT c2 FROM dbo.t1 WHERE c1=11
--ROLLBACK

在超过被阻塞进程阈值之后,可以在Profiler中看到Blocked Process Report事件被触发

如果保持代码一直运行,每5秒它将被触发一次,所生成的是一个XML文件

<blocked-process-report>
<blocked-process>
<process id="process14f4c8" taskpriority="0" logused="0" waitresource="RID: 6:1:90:0" waittime="36021" ownerId="85965" transactionname="user2" lasttranstarted="2016-12-11T22:44:17.640" XDES="0xcd51730" lockMode="S" schedulerid="1" kpid="1872" status="suspended" spid="56" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2016-12-11T22:44:17.640" lastbatchcompleted="2016-12-11T22:44:12.160" lastattention="2016-12-11T21:18:25.980" clientapp="Microsoft SQL Server Management Studio - 查询" hostname="VUEST" hostpid="1700" loginname="VUEST\Vuest" isolationlevel="read committed (2)" xactid="85965" currentdb="6" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
<executionStack>
<frame line="2" stmtstart="38" sqlhandle="0x020000001be0f42a9b3a6fd8eae5b4ae648e87cc70b1f6ba"/>
<frame line="2" stmtstart="38" sqlhandle="0x0200000008b74f04b02b5eed91a834b9706e0fc33245acd6"/>
</executionStack>
<inputbuf>
begin tran user2
select c2 from dbo.t1 where c1=11 </inputbuf>
</process>
</blocked-process>
<blocking-process>
<process status="sleeping" spid="52" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2016-12-11T22:44:09.750" lastbatchcompleted="2016-12-11T22:44:09.790" clientapp="Microsoft SQL Server Management Studio - 查询" hostname="VUEST" hostpid="1700" loginname="VUEST\Vuest" isolationlevel="read committed (2)" xactid="85956" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack/>
<inputbuf>
begin tran user1
update dbo.t1 set c3=GETDATE() </inputbuf>
</process>
</blocking-process>
</blocked-process-report>

此时用语句获取阻塞信息

        --得到阻塞对应关系
SELECT distinct
wt.session_id AS BlockedSessionId,
DB_NAME(tl.resource_database_id) AS DatabaseName,
wt.wait_type AS WaitType,
tl.request_mode+':'+tl.resource_type+':'+tl.resource_description AS WaitResource,
se1.last_request_start_time AS BlockedTime,ec1.last_read,
wt.wait_duration_ms AS WaitDuration_ms,
ec1.client_net_address AS BlockedClientAddress,
--h1.text AS BlockedStmt,
SUBSTRING(
h1.text,
(er1.statement_start_offset / 2) + 1,
(
(
CASE
WHEN er1.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), h1.text))
* 2
ELSE er1.statement_end_offset
END - er1.statement_start_offset
) / 2
) + 1
) AS BlockedStmt,
wt.blocking_session_id AS BlockingSessionId,
se2.transaction_isolation_level AS BlockingIsolationLevel,
wt.resource_description AS BlockingHoldResource,
--h2.text AS BlockingStmt,
SUBSTRING(
h2.text,
(ISNULL(er2.statement_start_offset, 0) / 2) + 1,
(
(
CASE
WHEN ISNULL(er2.statement_end_offset, 0) <= 0 THEN
LEN(CONVERT(NVARCHAR(MAX), h2.text))
* 2
ELSE er2.statement_end_offset
END - ISNULL(er2.statement_start_offset, 0)
) / 2
) + 1
) AS BlockingStmt,
ec2.client_net_address AS BlockingClientAddress,
se2.program_name AS BlockingProgramName,
se2.login_name AS BlockingLoginame,
GETDATE() AS InsertTime
FROM sys.dm_tran_locks AS tl WITH(NOLOCK) --会过滤并行问题CXPACKET
INNER JOIN sys.dm_os_waiting_tasks AS wt WITH(NOLOCK)
ON wt.resource_address = tl.lock_owner_address
INNER JOIN sys.dm_exec_connections ec1 WITH(NOLOCK)
ON ec1.session_id = wt.session_id
INNER JOIN sys.dm_exec_connections ec2 WITH(NOLOCK)
ON ec2.session_id = wt.blocking_session_id
INNER JOIN sys.dm_exec_sessions AS se1 WITH(NOLOCK)
ON se1.session_id = ec1.session_id
INNER JOIN sys.dm_exec_sessions AS se2 WITH(NOLOCK)
ON se2.session_id = ec2.session_id
INNER JOIN sys.dm_exec_requests er1 WITH(NOLOCK)
ON er1.session_id = ec1.session_id
LEFT JOIN sys.dm_exec_requests er2 WITH(NOLOCK)
ON er2.session_id = ec2.session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2


自动化侦测和收集阻塞信息
《SQLServer2008查询性能优化》第355页有说使用[SQL Server警报+作业]来自动侦测和收集阻塞信息。下面参考原文进行测试


[常规]页面计数器Average Wait Time (ms)(我使用计数器Lock Wait Time (ms)一直收不到邮件)对应的是累计值,并且只有当阻塞解除后才会进行累加。例如我重启数据库服务,然后执行前面的创建阻塞语句,只要会话1不回滚/提交,阻塞将一直持续,计数器Average Wait Time (ms)的值不会变动。一旦会话1回滚/提交,计数器Average Wait Time (ms)的值将更新(原值+阻塞时长)。当计数器Average Wait Time (ms)的值满足设定的警报条件时,它将触发警报并响应动作(此例中:执行作业+通知操作员)。之后哪怕没有阻塞,警报还将一直被触发(计数器Average Wait Time (ms)的值一直满足触发警报条件)。警报相关操作可参考:SQL Server代理警报
警报的[响应]页面勾选的执行作业Blocking Analysis,作业执行的语句实际是[将Profiler中定义Blocked Process Report事件导出生成跟踪定义的脚本]

-- Create a Queue
declare @rc int
declare @TraceID int
declare @maxfilesize BIGINT
declare @DateTime datetime
declare @TraceFile nvarchar(256) set @DateTime = DATEADD(MI,5,GETDATE())
set @maxfilesize = 5
select @TraceFile='F:\TroubleShooting\'+REPLACE(@@SERVERNAME,'\','_')+'_Blocked' exec @rc = sp_trace_create @TraceID output, 2, @TraceFile, @maxfilesize, @Datetime
if (@rc != 0) goto error -- Client side File and Table cannot be scripted -- Set the events
declare @on bit
set @on = 1
exec sp_trace_setevent @TraceID, 137, 1, @on
exec sp_trace_setevent @TraceID, 137, 3, @on
exec sp_trace_setevent @TraceID, 137, 4, @on
exec sp_trace_setevent @TraceID, 137, 12, @on
exec sp_trace_setevent @TraceID, 137, 13, @on
exec sp_trace_setevent @TraceID, 137, 14, @on
exec sp_trace_setevent @TraceID, 137, 15, @on
exec sp_trace_setevent @TraceID, 137, 24, @on
exec sp_trace_setevent @TraceID, 137, 32, @on
exec sp_trace_setevent @TraceID, 137, 41, @on
exec sp_trace_setevent @TraceID, 137, 51, @on -- Set the Filters
declare @intfilter int
declare @bigintfilter bigint -- Set the trace status to start
exec sp_trace_setstatus @TraceID, 1 -- display trace id for future references
select TraceID=@TraceID
goto finish error:
select ErrorCode=@rc finish:
go

将上面脚本保存到.sql文件,作业步骤类型使用cmdExec,命令中键入:sqlcmd -E -S127.0.0.1,7777 -iF:\TroubleShooting\TraceBlocked.sql
语句查询计数器的取值

select * from sys.dm_os_performance_counters
WHERE [object_name]='MSSQL$SQL08R2:Locks'
AND instance_name='_Total'
ORDER BY counter_name


收到的邮件

个人对这种自动化侦测和收集不太满意,原因就是警报触发条件所使用的计数器是累计值。更多的时候我们希望遇到阻塞,并且阻塞时长持续>某个值的时候能有提醒。因此倾向于定期从sys.dm_os_waiting_tasks中获取阻塞信息。

如何使用Profiler跟踪阻塞信息的更多相关文章

  1. NET Memory Profiler 跟踪.net 应用内存

    NET Memory Profiler 跟踪.net 应用内存 用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇 作者:肖波      .net 框架号称永远 ...

  2. 十、K3 WISE 开发插件《SQL Profiler跟踪单据操作时产生的SQL语句》

    =================================== 目录: 1.查询帐套的数据库DBID 2.配置需要跟踪数据库的DBID 3.配置跟踪参数 4.跟踪进行 5.分析跟踪语句 === ...

  3. PHP打印跟踪调试信息

    对于大部分编译型语言来说,比如 C . Java . C# ,我们都能很方便地进行断点调试,但是 PHP 则必须安装 XDebug 并且在编辑器中进行复杂的配置才能实现断点调试的能力.不过,如果只是简 ...

  4. Sql Server Profiler跟踪死锁

    Sql Server Profiler一个很重要的应用场景就是监视分析死锁. 下面通过一个例子来学习Profiler是如何监视死锁的. 1. 创建测试数据模拟死锁, 创建表Table_A和Table_ ...

  5. 统计分析SQL Server Profiler 跟踪的SQL

    --跟踪文件读入到表中分析 SELECT * INTO ZGSJY FROM fn_trace_gettable('E:\wxxcdbprofiler.trc', default); --某时间内,最 ...

  6. 【SQL跟踪工具】SQL Profiler 跟踪器

    什么是SQL Profiler SQL Server Profiler 是一个功能丰富的界面,用于创建和管理跟踪并分析和重播跟踪结果. 事件保存在一个跟踪文件中,稍后试图诊断问题时,可以对该文件进行分 ...

  7. 用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇(转)

    .net 框架号称永远不会发生内存泄漏,原因是其引入了内存回收的机制.但实际应用中,往往我们分配了对象但没有释放指向该对象的引用,导致对象永远无法释放.最 常见的情况就是给对象添加了事件处理函数,但当 ...

  8. SQLSERVER——查看阻塞信息(sp_who_lock优化无误版)

    经常会需要分析SQLSERVER的阻塞情况,尤其是某些SQL操作异常缓慢从而怀疑是有人在搞事情的情况下.网上有许多一模一样的帖子,是关于sp_who_lock这个存储过程的,然而,网上流传的这个是略有 ...

  9. profiler跟踪事件存为表之后性能分析工具

    使用profiler建立跟踪,将跟踪结果存到表中,使用下面存储过程执行 exec temp_profiler 'tra_tablename'对表数据进行处理归类,然后进行性能分析 1.先建存储过程 2 ...

随机推荐

  1. 【leetcode】Majority Element

    题目概述: Given an array of size n, find the majority element. The majority element is the element that ...

  2. B站开源ijkplayer 等多个项目

    弹幕视频网 Bilibili(B 站)近日在 GitHub 网站上建立了开源工作组(BOSTF),用以分享与维护自己的开源项目,其中包括 DanmakuFlameMaster(燃烧吧!烈焰弹幕使)与 ...

  3. JavaScript(一)

    JavaScript 是脚本语言 JavaScript 是一种可插入 HTML 页面的轻量级的编程语言,它跟Java没有什么蛋关系. JavaScript使用: <script language ...

  4. 从零开始山寨Caffe·贰:主存模型

    你左手是内存,右手是显存,内存可以打死显存,显存也可以打死内存. —— 请协调好你的主存 从硬件说起 物理之觞 大部分Caffe源码解读都喜欢跳过这部分,我不知道他们是什么心态,因为这恰恰是最重要的一 ...

  5. dbflow 批量 增删查改

    @ModelContainer @Table(database = DemoDatabase.class) class Person extends BaseModel implements Seri ...

  6. Tornado 学习笔记13 TCPServer

         为了实现TCPServer的功能,定义一个类用于继承TCPServer并实现handle_stream方法.HttpServer就是一个很好的例子. 13.1 构造函数 def __init ...

  7. 【Linux】unzip命令,记一次遇到的问题

    最近在做BOSS系统云平台部署脚本,联调时发现Shell脚本中存在问题,下方记录 某个地方提示是否覆盖 [root@haiwai test]# unzip /home/redis/test/main- ...

  8. python 反射器

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @author: zengchunyun ""& ...

  9. [Android]关于filed 遍历资源文件的排序问题

    Field[] svgfields = R.drawable.class.getFields(); listid = new ArrayList<Integer>(); for (Fiel ...

  10. css 注意点

    HTML css 一.整体布局 1.创建一个html标签 2.创建三个div标签(分别是网页的头部,中间,和底部三部分) 3.一般都用class选择器 4.用css给body标签加个 margin:0 ...