好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SQLServer中使用扩展事件获取Session级别的等待信息及SQLServer2016中Ses

什么是等待

简单说明一下什么是等待:

当应用程序对SQL Server发起一个Session请求的时候,这个Session请求在数据库中执行的过程中会申请其所需要的资源,

比如可能会申请内存资源,表上的锁资源,物理IO资源,网络资源等等,

如果当前Session运行过程中需要申请的某些资源无法立即得到满足,就会产生等待。

SQL Server会以不用的方式来展现这个等待信息,比活动Session的等待信息,实例级的等待信息等等。

SQL Server中,等待事件是作为DBA进行TroubleShooting的重要参考信息之一,SQL Server中可以通过多中方式来获取等待信息。

但是对于SQL Server 2016之前的版本来说,不管是活动Session级别的等待和实例级的等待,参考意义都有限,

更多的时候是想要更加详细的且可以事后分析的等待,这就需要收集那些曾经已执行过的Session产生的等待信息,也就是特定Session等待信息的历史记录

本文重点介绍使用扩展事件来捕获等待信息,但不介绍扩展事件本身的使用,重点放在如何使用扩展事件来获取想要的等待事件信息。

需要对扩展事件有一定的了解。

等待信息的获取途径

在SQL Server中有一个系统视图sys.dm_os_wait_stats记录了自数据库服务启动以来累积产生的等待信息,

如下图,这个结果是实例级的,也就是记录的整个数据库服务器所有的等待事件的累积。

多数时候参考意义不是很大,比如某一天的网络延时很高,sys.dm_os_wait_stats中累计记录了大量的ASYNC_NETWORK_IO等待信息。

但是到了第二天或者什么时候,网络变好了,但是sys.dm_os_wait_stats中记录的ASYNC_NETWORK_IO等待信息是不变的

也就是说sys.dm_os_wait_stats无法反映实时等待情况。

当然要获取实时的等待信息也简单,记录两个时间点之间sys.dm_os_wait_stats中等待时间的差值,可以间接地反映出来某一段时间的数据的等待信息。

但是这个信息仍然比较粗略,依旧是实例级的,某些时候依旧是不足够作为参考的。

另外一个是通过sys.dm_exec_requests这个系统视图的wait_type,wait_time等获取活动Session的等待信息

如截图,但是这个是活动Session的信息,当Session完成之后,它的等待信息就看不到曾经都产生了那些等待,分别是多久。

也就说,你无法追溯历史上某一个Session或者某一个SQL(存储过程)执行过程中的都产生了什么类型的等待,等待了多长时间。

实话说,不管是sys.dm_os_wait_stats还是sys.dm_exec_requests,在正常情况下,获取到的等待信息实用价值都是不高或者是适用场景有限。

更多的时候我们是想要更细一级的等待,比如某一个Login、某一部分Session、甚至某些特定的SQL(存储过程)的执行过程中产生的等待信息。

举个实际例子,数据库又10个Login给10个不同的应用程序访问,其中只有1个应用程序端反馈说访问数据库慢,或者有性能问题,其他Login都反馈正常

那么很有可能是这个Login请求自己的问题,此时就需要针对这一个Login的情况进行针对性分析,而不是在实例级分析诊断。

如果能够拿到这个Login执行的Session的等待情况,或者这个Login某些特定的数据库对象的执行过程中的等待信息,对定位问题的针对性的就比较强了。 

本文就以此为切入点,针对如何获取Session级别的等待信息展开说明和演示。

SQL Server 2016中获取Session级别的等待信息

在SQL Server 2016中,获取Session级别的等待信息是比较方便的,有直接的系统视图sys.dm_exec_session_wait_stats可以使用

当前情况下,想要知道某一个Session的等待信息就很简单了,

在sql语句开始的时候把当前Session的等待信息记录下来

在sql语句结束的时候把当前Session的等待信息再次记录出来

计算两次等待信息的差值,就可以知道当前Session运行的过程中有哪些等待,分别是多少。

  sqlserver开发团队可能也意识到了对于等待信息,更多的时候,需要的是较为具体的等待,而不是一个笼统的实例级的等待

  因此在SQL Server 2016中增加了sys.dm_exec_session_wait_stats这个支持统计Session级别的等待的视图

  很不幸的SQL Server2016之前的版本中是没有这个系统视图可以很方便地记录Session级别的等待。

  但是可以借助扩展事件来实现类似的功能。

使用扩展事件来捕获Session级别的等待信息

因为这里是是用扩展事件来实现的,这里要求读者要对扩展事件有一个基本的认识,扩展事件本身就不多说了。

上代码,启动一个扩展事件,来记录执行时间超过三秒的SQL语句,其执行过程中等待时间大于0的等待事件信息。

当然这个捕获的信息可以加上各种过滤条件。具体参考代码备注。

IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='CollectionSessionWaitStats')
 DROP EVENT session CollectionSessionWaitStats ON SERVER;
GO
-- 创建事件会话 
CREATE EVENT SESSION CollectionSessionWaitStats ON SERVER  
ADD EVENT sqlserver.rpc_completed
( 
  ACTION
  (
    sqlos.task_time,
    sqlserver.database_name,
    sqlserver.nt_username,
    sqlserver.username,
    sqlserver.sql_text,
    sqlserver.session_id,
    sqlserver.transaction_id
  ) WHERE [duration]>=3000000
), 
ADD EVENT sqlserver.sql_batch_completed
( 
  ACTION
  (
    sqlos.task_time,
    sqlserver.database_name,
    sqlserver.nt_username,
    sqlserver.username,
    sqlserver.sql_text,
    sqlserver.session_id,
    sqlserver.transaction_id
  ) WHERE [duration]>=3000000
),
ADD EVENT sqlos.wait_info
(
  ACTION 
  (
    sqlos.task_time,
    sqlserver.database_name,
    sqlserver.nt_username,
    sqlserver.sql_text,
    sqlserver.username,
    sqlserver.session_id,
    sqlserver.transaction_id
  ) WHERE session_id>50 
      and opcode=1 
      and duration>0
      and sql_text not like '%sp_MScdc_capture_job%' --排除某些信息
      --and username = '' --限定只记录某些信息
),
ADD EVENT sqlos.wait_info_external
(
  ACTION
  (
    sqlos.task_time,
    sqlserver.database_name,
    sqlserver.nt_username,
    sqlserver.username,
    sqlserver.sql_text,
    sqlserver.session_id,
    sqlserver.transaction_id
  ) WHERE  session_id>50 
      and opcode=1 
      and duration>0
      and sql_text not like '%sp_MScdc_capture_job%'
      --and username = ''
)
ADD TARGET package0.event_file
( 
  SET filename=N'D:\XEventFiles\CollectionSessionWaitStats',
  max_file_size=(1024),  
  max_rollover_files=(10) 
)
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=ON
  )
GO
-- 启用(停止)事件会话(START / STOP) 
ALTER EVENT SESSION CollectionSessionWaitStats ON SERVER STATE=START 
GO 

查看更多关于SQLServer中使用扩展事件获取Session级别的等待信息及SQLServer2016中Ses的详细内容...

  阅读:42次