一、扩展事件是什么
1. 体系架构
扩展事件(Extended Events)引入于2008版本,具有高度可伸缩可配置的体系结构,使用户能够按需收集解决性能问题或确定问题所需的信息。扩展事件是轻型性能监视系统,性能消耗非常少,未来可能会替代掉profiler和trace(目前还做不到,功能相比前两者还有差距)。
扩展事件基础结构支持 SQL Server 中数据的关联,还支持将扩展事件输出定向到 Windows 事件跟踪 (ETW),使事件数据与操作系统或应用程序事件数据建立关联。
2. 特点
- 事件同步触发,但可同步或异步进行处理。
- 几乎任何动作都可以与任何事件配对,从而能够更深入地监控系统。
- 支持大量谓词,允许使用布尔逻辑来构建复杂的过滤规则。
- 可以使用 Transact-SQL 对扩展事件会话进行全面控制。
- 可以监控性能关键代码而几乎不会对性能产生影响。
3. 常见用途
- 查找最消耗资源的查询、执行超过指定时间的查询
- 查找导致闩锁争用的根本原因
- 查找锁阻塞问题原因
- 排查死锁问题
- 查询重编译导致的CPU过高问题
- 某些功能(例如alwayson)的详细执行过程及原理分析
二、 扩展事件概念解析
下图描述了扩展事件中引入的几个新概念:
1. 事件(可监控项)
事件是指代码中定义的点。此类示例包括:T-SQL 语句完成执行时的点或结束获取锁定时的点。每个事件都有一个定义的负载(该事件返回的列的集合),它是使用 ETW 模型来定义的,以便能够与 ETW 集成。
查看支持的事件列表:
SELECT xp.[name], xo.*
FROM sys.dm_xe_objects xo, sys.dm_xe_packages xp
WHERE xp.[guid] = xo.[package_guid]
AND xo.[object_type] = 'event'
ORDER BY xp.[name];
查找某个特定事件的负载:
SELECT * FROM sys.dm_xe_object_columns
WHERE [object_name] = 'sql_statement_completed';
2. 谓词(过滤条件)
谓词是指在事件消耗前利用一组逻辑规则来筛选事件的方法。谓词可以很简单,如检查事件负载中的其中一个返回列是否为某个特定值。它们还具有一些高级功能,如统计会话期间某个特定事件发生的次数、仅允许事件在发生一次后消耗等。
谓词可以使用布尔逻辑来编写,这使得只需执行最少数量的同步处理即可确定是否需要消耗事件。
3. 动作(触发监控项后要干什么)
动作是指在消耗某个事件前同步执行的一组命令。它们通常会收集大量数据并追加到事件负载中(如 T-SQL 堆栈或查询执行计划)或执行某个被追加到事件负载中的计算。
由于执行这些动作可能需要极高的代价,因此事件的动作仅在所有谓词都计算完毕后才执行,如果在随后确定该事件不会被消耗,则将不会有同步执行某个动作的点。使用下列代码可找到预定义动作的列表:
SELECT xp.[name], xo.*
FROM sys.dm_xe_objects xo, sys.dm_xe_packages xp
WHERE xp.[guid] = xo.[package_guid]
AND xo.[object_type] = 'action'
ORDER BY xp.[name];
4. 目标(结果存在哪里)
目标只提供一种消耗事件的方法,任何目标都可以消耗任何事件(或至少可以在目标空闲时对事件进行处理 — 如获取非审计事件的审计目标)。目标可以同步或异步消耗事件。
- 同步目标包括:事件计数器、Windows事件跟踪(ETW)
- 异步目标包括:事件文件、事件配对、直方图和环形缓冲区
SELECT xp.[name], xo.*
FROM sys.dm_xe_objects xo, sys.dm_xe_packages xp
WHERE xp.[guid] = xo.[package_guid]
AND xo.[object_type] = 'target'
ORDER BY xp.[name];
SQL Server提供了多种格式来保存会话事件:
- Etw_classic_sync_target:输出事件以Event Tracing for Windows(ETW)格式。
- Event_counter:输出事件到内存记录会话中跟踪事件触发的次数。
- Event_file:输出事件到磁盘上的一个目录的文件。
- Histogram:输出事件到内存基于域和行动分组计数事件。
- Pair_matching:输出事件到内存跟踪基于目标配置没有对应事件的事件。
- Ring_buffer:输出事件到内存跟踪基于目标配置的一定量的事件数据。
5. 数据包
数据包位于它所描述的模块(如可执行程序或 DLL)中,是一个用于定义扩展事件对象(如事件、动作和目标)的容器。使用扩展事件引擎注册数据包时,它所定义的全部对象都可供使用。
6. 会话
会话是一种将多个扩展事件对象链接到一起进行处理的方法。会话可链接任何注册的数据包中的对象,任何数量的会话都可以使用同一个事件、动作等。下图sessions文件夹下每个都是一个扩展事件会话。
使用下列代码可查看已定义了哪些扩展事件会话:
SELECT * FROM sys.dm_xe_sessions;
可使用 T-SQL 命令来创建、删除、更改、停止和启动会话。可以想见,这将提供很多灵活性,甚至提供通过对会话本身所捕获的数据进行程序化分析来动态更改会话的功能。
三、 性能注意事项
尽管扩展事件对性能影响已经较小,我们还是需要认真正确配置一些设置,因为它们可能会在无意中对性能产生影响。
1. 选择同步还是异步处理事件
同步对性能产生的影响显然要大过异步。如前所述,同步消耗某个事件时,触发该事件的代码必须一直等待,直到该事件被消耗为止。显然,如果事件消耗是一个复杂的过程,则这可能会降低代码的性能。
例如,在一个每秒处理数千个小事务的繁忙系统中,同步消耗 sql_statement_completed 事件及捕获查询计划动作很可能会对性能产生负面影响。
谓词始终是同步执行的,因此应注意不要为性能关键代码触发的事件创建过于复杂的谓词。另一方面,您可能会被强制同步消耗事件。要计算某个特定事件的出现次数,最简单的方法很可能是使用 synchronous_event_counter 目标。
2. 如何配置事件缓冲
如果决定使用异步目标,那么该如何配置事件缓冲?事件缓冲的默认可用内存数为 4MB,事件被触发,随后被目标消耗,期间的默认调度延迟为 30 秒。如果您希望每 10 秒生成一些事件统计数据,则必须对延迟时间进行调整。
对用于缓冲事件的内存进行分区的方法是将其绑定到事件缓冲设置。默认情况下是为整个实例创建一组缓冲区。在 SMP(对称多处理器)和 NUMA(非统一内存访问)计算机中,这可能会使处理器不得不等待访问内存,从而导致出现性能问题。
3. 如何处理事件丢失
在定义扩展事件会话时,可指定事件是否可以“丢失”。这意味着如果没有足够的内存来缓冲某个事件,则可将其直接丢弃。默认设置是允许丢弃单个事件,但也可以允许整个事件缓冲区都丢失(适用于事件缓冲区很快就被填满的会话),甚至还可以指定任何事件都不得丢失。
使用最后一个选项时应格外注意,因为它会强制触发事件的代码一直等待,直到有足够的缓冲区内存来存储该事件为止,几乎肯定会对性能产生不利影响。
四、 事件的寿命
定义并启动扩展事件会话后,处理过程将照常进行,直到所监控的代码遇到某个事件为止。
下图介绍了扩展事件系统所遵循的步骤。
具体步骤如下:
- 执行检查是否有扩展事件会话正在监控该事件。如果没有,控制权将返给包含该事件的代码,继续进行处理。
- 创建事件负载,将所需的全部信息都收集到内存中
- 如果为该事件定义了谓词,则执行它们。如果事件不符合谓词条件,控制权将返给包含该事件的代码,继续进行处理。
- 如果符合谓词条件,系统会得知事件将被消耗,将执行链接到该事件的所有动作。现在事件已具有完整的负载,已为消耗做好准备。
- 将事件提供给同步目标(如果有的话)。
- 如果存在异步目标,将会缓冲该事件以便随后进行处理。
- 扩展事件处理完成,控制权将返给包含该事件的代码。
如前所述,在创建事件会话时应格外注意,要避免同步动作或异步目标的缓冲对所监控代码的性能产生影响。