外观
SQLServer XEvents
SQLServer Extended Events 概述
SQLServer Extended Events(简称XEvents)是一个轻量级、高性能的事件监控系统,用于收集SQLServer的详细性能和诊断数据。它提供了比传统SQL Server Profiler更高效、更灵活的监控能力,是现代SQL Server性能调优和故障诊断的核心工具。
XEvents 核心优势
- 高性能:性能开销低(通常<5%),适合生产环境长期运行
- 灵活性:支持丰富的事件类型和自定义配置
- 可扩展性:支持多种目标存储和自定义事件
- 深度诊断:提供详细的事件数据,支持深入分析
- 现代化:Microsoft推荐的替代SQL Server Profiler的工具
XEvents 核心概念
| 组件 | 描述 |
|---|---|
| 事件(Event) | 系统中发生的特定操作或状态变化,如查询执行、锁获取、死锁发生等 |
| 包(Package) | 相关事件和操作的集合,如sqlserver包包含数据库引擎相关事件 |
| 会话(Session) | 定义要收集的事件、过滤器和目标的配置单元 |
| 目标(Target) | 事件数据的存储或处理位置,如文件、内存、环形缓冲区等 |
| 谓词(Predicate) | 用于过滤事件的条件表达式,减少不必要的数据收集 |
| 动作(Action) | 事件触发时执行的操作,如收集客户端信息、SQL文本等 |
| 事件字段(Event Field) | 事件包含的具体数据,如执行时间、CPU使用率等 |
XEvents 与 SQL Server Profiler 对比
| 特性 | Extended Events | SQL Server Profiler |
|---|---|---|
| 性能开销 | 低(通常<5%) | 高(可达20%+) |
| 事件类型 | 丰富(数百种) | 有限(约100种) |
| 自定义能力 | 强 | 弱 |
| 目标选项 | 多种(文件、内存、环形缓冲区等) | 有限(文件、表等) |
| 生产环境适用性 | 适合 | 不推荐 |
| 可扩展性 | 支持自定义事件和目标 | 有限扩展能力 |
| 版本支持 | SQL Server 2008+(推荐2012+) | SQL Server 2000-2019(已弃用) |
XEvents 核心架构
XEvents 包体系
XEvents包含多个预定义包,每个包提供特定功能的事件:
| 包名 | 描述 | 主要事件类型 |
|---|---|---|
| sqlserver | 数据库引擎核心事件 | 查询执行、锁、死锁、存储过程等 |
| package0 | 系统核心功能 | 错误、警告、调试事件等 |
| sqlos | SQLOS相关事件 | 内存、调度器、等待统计等 |
| database_audit_specification | 数据库审计事件 | 数据访问、权限变更等 |
| server_audit_specification | 服务器审计事件 | 登录、服务器配置变更等 |
XEvents 目标类型
XEvents支持多种目标类型,用于存储或处理事件数据:
| 目标类型 | 描述 | 适用场景 |
|---|---|---|
| event_file | 将事件数据写入文件 | 长期数据收集、详细分析 |
| ring_buffer | 将事件数据存储在内存中 | 短期监控、实时分析 |
| pair_matching | 跟踪相关事件对(如锁的获取和释放) | 锁分析、持续时间计算 |
| histogram | 按指定字段聚合事件数据 | 热点分析、趋势统计 |
| event_counter | 统计事件发生次数 | 事件频率监控、阈值告警 |
| etw_classic_sync_target | 将事件发送到ETW(Event Tracing for Windows) | 与Windows事件系统集成 |
版本差异
SQL Server 2008-2012
- 初始版本:SQL Server 2008引入XEvents,但功能有限
- 基本功能:支持核心事件收集和简单目标
- 管理方式:主要通过T-SQL管理,缺乏图形化界面
- 事件数量:约200种事件
SQL Server 2014-2016
- 增强功能:添加了更多事件类型和目标
- 图形化管理:SSMS 2016开始提供完善的XEvents图形化界面
- 性能优化:降低了事件收集的性能开销
- 新增事件:添加了In-Memory OLTP、Columnstore等新特性相关事件
- 事件数量:约400种事件
SQL Server 2017-2019
- 跨平台支持:Linux和容器环境支持
- 增强诊断:添加了更多性能诊断事件
- 智能查询处理:添加了智能查询相关事件
- Azure集成:增强了与Azure SQL Database的兼容性
- 事件数量:约500种事件
SQL Server 2022
- 增强可观测性:添加了更多可观测性相关事件
- 性能提升:进一步优化了事件收集的性能
- 智能分析:增强了与SQL Server 2022智能功能的集成
- 事件数量:约600种事件
生产场景应用
场景1:死锁监控
场景描述:生产环境中偶尔发生死锁,需要捕获死锁详细信息以便分析。
解决方案:创建XEvents会话监控死锁事件
会话创建脚本:
sql
-- 创建死锁监控会话
CREATE EVENT SESSION [Deadlock_Monitor] ON SERVER
ADD EVENT sqlserver.lock_deadlock_graph,
ADD EVENT sqlserver.lock_deadlock
ADD TARGET package0.event_file(
SET filename=N'C:\XEvents\Deadlock_Monitor.xel',
max_file_size=(50),
max_rollover_files=(10)
) ON PARTITION(SQL Server Partition)
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=ON,
STARTUP_STATE=ON
);
GO
-- 启动会话
ALTER EVENT SESSION [Deadlock_Monitor] ON SERVER STATE=START;
GO数据查询:
sql
-- 查询死锁信息
SELECT
XEvent.query('(event/data/value/deadlock)[1]') AS DeadlockGraph,
XEvent.value('(event/@timestamp)[1]', 'datetime2(3)') AS EventTime
FROM
(SELECT CAST(event_data AS XML) AS XEvent
FROM sys.fn_xe_file_target_read_file('C:\XEvents\Deadlock_Monitor*.xel', NULL, NULL, NULL)) AS Events
WHERE
XEvent.value('(event/@name)[1]', 'varchar(50)') = 'lock_deadlock_graph'
ORDER BY
EventTime DESC;场景2:慢查询跟踪
场景描述:需要监控执行时间超过5秒的查询,以便进行性能优化。
解决方案:创建XEvents会话监控慢查询
会话创建脚本:
sql
-- 创建慢查询监控会话
CREATE EVENT SESSION [Slow_Query_Monitor] ON SERVER
ADD EVENT sqlserver.rpc_completed(
ACTION(
sqlserver.client_app_name,
sqlserver.client_hostname,
sqlserver.database_id,
sqlserver.database_name,
sqlserver.nt_username,
sqlserver.query_hash,
sqlserver.query_plan_hash,
sqlserver.session_id,
sqlserver.sql_text,
sqlserver.username
)
WHERE (
[duration] > 5000000 -- 5秒,单位微秒
)
),
ADD EVENT sqlserver.sql_batch_completed(
ACTION(
sqlserver.client_app_name,
sqlserver.client_hostname,
sqlserver.database_id,
sqlserver.database_name,
sqlserver.nt_username,
sqlserver.query_hash,
sqlserver.query_plan_hash,
sqlserver.session_id,
sqlserver.sql_text,
sqlserver.username
)
WHERE (
[duration] > 5000000 -- 5秒,单位微秒
)
)
ADD TARGET package0.ring_buffer(SET max_memory=(10240)),
ADD TARGET package0.event_file(
SET filename=N'C:\XEvents\Slow_Query_Monitor.xel',
max_file_size=(100),
max_rollover_files=(20)
)
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=ON,
STARTUP_STATE=ON
);
GO
-- 启动会话
ALTER EVENT SESSION [Slow_Query_Monitor] ON SERVER STATE=START;
GO数据查询:
sql
-- 查询慢查询信息
SELECT
XEvent.value('(event/@timestamp)[1]', 'datetime2(3)') AS EventTime,
XEvent.value('(event/@name)[1]', 'varchar(50)') AS EventName,
XEvent.value('(event/action[@name="database_name"]/value)[1]', 'varchar(128)') AS DatabaseName,
XEvent.value('(event/action[@name="client_app_name"]/value)[1]', 'varchar(128)') AS ClientApp,
XEvent.value('(event/action[@name="client_hostname"]/value)[1]', 'varchar(128)') AS ClientHost,
XEvent.value('(event/action[@name="username"]/value)[1]', 'varchar(128)') AS Username,
XEvent.value('(event/data[@name="duration"]/value)[1]', 'bigint')/1000000.0 AS DurationSeconds,
XEvent.value('(event/data[@name="cpu_time"]/value)[1]', 'bigint') AS CPUTime,
XEvent.value('(event/data[@name="logical_reads"]/value)[1]', 'bigint') AS LogicalReads,
XEvent.value('(event/action[@name="sql_text"]/value)[1]', 'nvarchar(max)') AS SQLText
FROM
(SELECT CAST(event_data AS XML) AS XEvent
FROM sys.fn_xe_file_target_read_file('C:\XEvents\Slow_Query_Monitor*.xel', NULL, NULL, NULL)) AS Events
ORDER BY
DurationSeconds DESC;场景3:锁争用分析
场景描述:数据库存在锁争用问题,需要分析锁的获取和等待情况。
解决方案:创建XEvents会话监控锁事件
会话创建脚本:
sql
-- 创建锁争用监控会话
CREATE EVENT SESSION [Lock_Contention_Monitor] ON SERVER
ADD EVENT sqlserver.lock_acquired(
ACTION(
sqlserver.client_app_name,
sqlserver.client_hostname,
sqlserver.database_name,
sqlserver.sql_text,
sqlserver.username
)
WHERE (
[duration] > 100000 -- 100毫秒
AND [mode] > 3 -- 只监控排它锁和更新锁
)
),
ADD EVENT sqlserver.lock_wait_completed(
ACTION(
sqlserver.client_app_name,
sqlserver.client_hostname,
sqlserver.database_name,
sqlserver.sql_text,
sqlserver.username
)
WHERE (
[duration] > 100000 -- 100毫秒
)
)
ADD TARGET package0.ring_buffer(SET max_memory=(20480)),
ADD TARGET package0.event_file(
SET filename=N'C:\XEvents\Lock_Contention_Monitor.xel',
max_file_size=(100),
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=ON,
STARTUP_STATE=OFF
);
GOXEvents 会话管理
创建和启动会话
sql
-- 创建会话
CREATE EVENT SESSION [Session_Name] ON SERVER
ADD EVENT ...
ADD TARGET ...
WITH (...);
-- 启动会话
ALTER EVENT SESSION [Session_Name] ON SERVER STATE=START;查看会话状态
sql
-- 查看所有XEvents会话状态
SELECT
name,
start_time,
state_desc
FROM
sys.dm_xe_sessions;
-- 查看会话的事件和目标
SELECT
s.name AS SessionName,
e.event_name,
t.target_name
FROM
sys.dm_xe_sessions s
JOIN
sys.dm_xe_session_events e ON s.address = e.event_session_address
JOIN
sys.dm_xe_session_targets t ON s.address = t.event_session_address;停止和删除会话
sql
-- 停止会话
ALTER EVENT SESSION [Session_Name] ON SERVER STATE=STOP;
-- 删除会话
DROP EVENT SESSION [Session_Name] ON SERVER;动态管理视图
XEvents提供了多个动态管理视图,用于监控和管理会话:
| DMV | 描述 |
|---|---|
| sys.dm_xe_sessions | 显示活跃的XEvents会话 |
| sys.dm_xe_session_events | 显示会话中的事件 |
| sys.dm_xe_session_targets | 显示会话中的目标 |
| sys.dm_xe_session_event_actions | 显示会话中事件的动作 |
| sys.dm_xe_map_values | 显示映射值(如事件名称到ID的映射) |
| sys.dm_xe_object_columns | 显示事件对象的列 |
数据查询与分析
从文件目标查询数据
sql
-- 从文件目标读取事件数据
SELECT
CAST(event_data AS XML) AS EventData
FROM
sys.fn_xe_file_target_read_file(
'C:\XEvents\SessionName*.xel', -- 文件路径和通配符
NULL, -- 元数据文件(通常为NULL)
NULL, -- 开始时间(NULL表示所有)
NULL -- 结束时间(NULL表示所有)
);从环形缓冲区查询数据
sql
-- 从环形缓冲区读取事件数据
SELECT
CAST(xet.target_data AS XML) AS EventData
FROM
sys.dm_xe_sessions xs
JOIN
sys.dm_xe_session_targets xet ON xs.address = xet.event_session_address
WHERE
xs.name = 'Session_Name' AND xet.target_name = 'ring_buffer';解析XML事件数据
sql
-- 解析事件数据示例
SELECT
EventData.value('(event/@timestamp)[1]', 'datetime2(3)') AS EventTime,
EventData.value('(event/@name)[1]', 'varchar(50)') AS EventName,
EventData.value('(event/data[@name="duration"]/value)[1]', 'bigint') AS Duration,
EventData.value('(event/action[@name="sql_text"]/value)[1]', 'nvarchar(max)') AS SQLText
FROM
(SELECT CAST(event_data AS XML) AS EventData
FROM sys.fn_xe_file_target_read_file('C:\XEvents\SessionName*.xel', NULL, NULL, NULL)) AS Events;最佳实践
生产环境最佳实践
- 使用谓词过滤:只收集必要的事件,减少性能开销
- 选择合适的目标:
- 短期监控:使用ring_buffer
- 长期监控:使用event_file
- 实时分析:使用histogram或event_counter
- 合理设置内存:根据监控需求调整MAX_MEMORY参数
- 设置适当的调度延迟:MAX_DISPATCH_LATENCY平衡实时性和性能
- 启用因果跟踪:TRACK_CAUSALITY=ON有助于分析相关事件
- 配置启动状态:STARTUP_STATE=ON确保SQL Server重启后自动启动会话
- 限制文件大小:使用max_file_size和max_rollover_files防止磁盘空间耗尽
性能优化建议
- 减少事件数量:只添加必要的事件类型
- 使用窄化谓词:谓词条件越具体,收集的数据越少
- 避免不必要的动作:只添加需要的ACTION
- 使用内存分区:MEMORY_PARTITION_MODE=PER_CPU可提高高并发环境下的性能
- 定期清理旧数据:设置合理的文件滚动策略
- 避免在高负载时段进行详细监控:可根据时间设置谓词过滤
常见问题(FAQ)
XEvents 适合生产环境吗?
答案:是的,XEvents设计为轻量级,性能开销通常低于5%,适合生产环境长期运行。相比之下,SQL Server Profiler性能开销较高,不推荐在生产环境使用。
如何选择合适的事件类型?
答案:选择事件类型时,应根据监控目标确定:
- 死锁监控:lock_deadlock, lock_deadlock_graph
- 慢查询:rpc_completed, sql_batch_completed
- 锁争用:lock_acquired, lock_wait_completed
- 查询执行:sql_statement_starting, sql_statement_completed
- 存储过程:sp_statement_starting, sp_statement_completed
可以使用sys.dm_xe_objects视图查看所有可用事件:
sql
SELECT name, description FROM sys.dm_xe_objects WHERE object_type = 'event';如何降低XEvents的性能开销?
答案:降低XEvents性能开销的方法包括:
- 使用谓词过滤,只收集必要的事件
- 减少事件数量和动作数量
- 使用高效的目标类型(如ring_buffer或event_counter)
- 合理设置内存和调度延迟
- 避免在高负载时段进行详细监控
如何查看死锁图形?
答案:可以通过以下方式查看死锁图形:
- 在SSMS中,将XML死锁图形结果点击保存为.xdl文件,然后双击打开
- 使用SQL Server Profiler打开.xdl文件
- 使用第三方工具如SentryOne Plan Explorer查看
XEvents 可以替代 SQL Server Profiler 吗?
答案:是的,Microsoft已经在SQL Server 2019中弃用了SQL Server Profiler,并推荐使用XEvents作为替代方案。XEvents提供了更丰富的功能和更好的性能。
如何监控Azure SQL Database中的事件?
答案:Azure SQL Database支持XEvents,但有一些限制:
- 不支持所有XEvents包和事件
- 目标类型有限制,主要支持event_file和ring_buffer
- 管理方式主要通过T-SQL
- 存储位置使用Azure存储或Azure Monitor
示例Azure SQL Database XEvents会话:
sql
CREATE EVENT SESSION [Azure_XEvent_Session] ON DATABASE
ADD EVENT sqlserver.sql_batch_completed(
WHERE [duration] > 5000000
)
ADD TARGET package0.event_file(
SET filename=N'https://storageaccount.blob.core.windows.net/xecontainer/Azure_XEvent_Session.xel'
);总结
SQLServer Extended Events是一个强大的性能监控和诊断工具,提供了比传统SQL Server Profiler更高效、更灵活的监控能力。通过合理配置和使用XEvents,可以实现对SQL Server的深度监控,快速定位和解决性能问题。
在生产环境中,XEvents已成为DBA进行性能调优和故障诊断的核心工具。掌握XEvents的使用,对于提升SQL Server运维水平至关重要。
随着SQL Server版本的不断更新,XEvents的功能也在持续增强,支持更多事件类型和更高效的数据收集方式。作为DBA,应该不断学习和掌握XEvents的新特性,以适应不断变化的数据库环境和业务需求。
