笔记101 查询阻塞与死锁的sql语句

笔记101 查询阻塞与死锁的sql语句

 1 --查询阻塞与死锁的sql语句
 2 --1、
 3 --排在前两位的等待状态有下面几个:asynch_io_,completion,io_completion,logmgr,writelog,pageiolatch_x
 4 --这些等待状态意味着有I/O等待
 5 --如果排在前两位的等待状态以这样开头:LCK_M_?? 说明系统经常有阻塞
 6 SELECT TOP 2 [wait_type] FROM sys.[dm_os_wait_stats] ORDER BY [wait_time_ms] DESC
 7 
 8 
 9 --2、阻塞发生频率
10 EXEC [sys].[sp_helpdb] @dbname = gposdb -- sysname 要查询阻塞的数据库
11 SELECT * FROM sys.[dm_db_index_operational_stats](10,NULL,NULL,null) --根据上面的dbid填入第一个参数
12 
13 --3、开启阻塞事件报告
14 EXEC [sys].[sp_configure] @configname = 'blocked process threshold', -- varchar(35)
15     @configvalue = 1 -- int
16     RECONFIGURE
17 
18 --4、平均阻塞时间 建议阀值>100ms
19 EXEC [sys].[sp_helpdb] @dbname = gposdb -- sysname 要查询阻塞的数据库
20 SELECT [row_lock_wait_in_ms],[page_lock_wait_in_ms],[page_latch_wait_in_ms],[page_io_latch_wait_in_ms] FROM sys.[dm_db_index_operational_stats](10,NULL,NULL,null) --根据上面的dbid填入第一个参数
21 
22 --5、查询当前数据库上所有用户表格在row lock上发生阻塞的频率
23 --查询当前数据库上所有用户表在row lock上发生的阻塞频率
24 use GPOSDB   --要查询阻塞的数据库
25 DECLARE @dbid INT
26 SELECT @dbid=DB_ID()
27 SELECT
28 dbid=database_id,
29 objectname=OBJECT_NAME(s.object_id),
30 indexname=i.name,
31 i.index_id,
32 partition_number,
33 row_lock_count,
34 row_lock_wait_count,
35 [block%]=CAST(100*row_lock_wait_count/(1+row_lock_count)AS NUMERIC(15,2)),
36 row_lock_wait_in_ms,
37 [avg row lock waits in ms]=CAST(1*row_lock_wait_in_ms/(1+row_lock_wait_count)AS NUMERIC(15,2))
38 FROM sys.dm_db_index_operational_stats(@dbid,NULL,NULL,null) AS s,
39 sys.indexes AS i
40 WHERE OBJECTPROPERTY(s.object_id,'IsUserTable')=1
41 AND i.object_id=s.object_id
42 AND i.index_id=s.index_id
43 ORDER BY row_lock_wait_count DESC
44 
45 
46 
47 --6、查看DMV看一下数据库中有多少个锁-----------------------------------------------------------
48 USE [AdventureWorks] --要查询申请锁的数据库
49 GO
50 SELECT
51 [request_session_id],
52 c.[program_name],
53 DB_NAME(c.[dbid]) AS dbname,
54 [resource_type],
55 [request_status],
56 [request_mode],
57 [resource_description],OBJECT_NAME(p.[object_id]) AS objectname,
58 p.[index_id]
59 FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p
60 ON a.[resource_associated_entity_id]=p.[hobt_id]
61 LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid]
62 WHERE c.[dbid]=DB_ID('AdventureWorks')  ----要查询申请锁的数据库
63 ORDER BY [request_session_id],[resource_type]

 

 


 

使用扩展事件xevent记录历史发生的阻塞

 https://mp.weixin.qq.com/s/qZepNFWhqTy0Obqf56u5NQ

 

设置阻塞报警时间 blocked process threshold是sql2005新增的一个选项

超过这个阻塞阈值都会记录到扩展事件里面

sp_configure 'show advanced options', 1 ;  
GO  
RECONFIGURE ;  
GO  
sp_configure 'blocked process threshold', 20 ;   --设置为20秒
GO  
RECONFIGURE ;  
GO  

 

 

 

 

查找历史发生的阻塞

笔者见过很多人遇到长时间阻塞导致应用响应缓慢时候,病急乱投医,指望一个SQLServer高手来了,马上就能问题抓出来。

排查是否是阻塞导致的问题,首先要排查下面的问题:

  1. 是否是服务器CPU高导致

  2. 在服务器上执行一个SQL是否缓慢。

  3. 网络正常。

如果以上几个都正常,那多半是阻塞问题导致。

SQLServer默认是不捕获历史的长时间阻塞的问题的,这里需要新建一个SQLServer的扩展事件。

第一步命名,

第二步选择不使用模板,

第三步搜索block,选择blocked_process_report

 

 

 

然后选择几个最重要的指标,sql_text, session_id

 

 

下一步,注意在最后一步选择将数据保存到文件。点击完成。

 

 

这时我们在扩展事件里面可以看到block_report已经创建好了。

 

 

 

最后不要忘记设置阻塞捕获的时间的阈值。数据库默认是不会启用阻塞捕获,所以一定要启用设置这个阈值。

下面的示例将 blocked process threshold 设置为 20 秒,超过该阈值将为阻塞的每个任务生成阻塞的进程报告。


sp_configure 'show advanced options', 1 ;  
GO  
RECONFIGURE ;  
GO  
sp_configure 'blocked process threshold', 20 ;  
GO  
RECONFIGURE ;  
GO  

 

好了,我们再此运行之前的SQL语句(不在赘述),然后再去查看block_report会发生什么。

 

打开报告,扩展事件文件(xx.xel )需用Python进行分析,因为是xml格式文件,需用用xml模块 来分析和格式化然后在前端显示

 

 

f

posted @ 2013-08-02 23:33  桦仔  阅读(756)  评论(0编辑  收藏  举报