Skip to content

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 EventsSQL Server Profiler
性能开销低(通常<5%)高(可达20%+)
事件类型丰富(数百种)有限(约100种)
自定义能力
目标选项多种(文件、内存、环形缓冲区等)有限(文件、表等)
生产环境适用性适合不推荐
可扩展性支持自定义事件和目标有限扩展能力
版本支持SQL Server 2008+(推荐2012+)SQL Server 2000-2019(已弃用)

XEvents 核心架构

XEvents 包体系

XEvents包含多个预定义包,每个包提供特定功能的事件:

包名描述主要事件类型
sqlserver数据库引擎核心事件查询执行、锁、死锁、存储过程等
package0系统核心功能错误、警告、调试事件等
sqlosSQLOS相关事件内存、调度器、等待统计等
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
);
GO

XEvents 会话管理

创建和启动会话

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;

最佳实践

生产环境最佳实践

  1. 使用谓词过滤:只收集必要的事件,减少性能开销
  2. 选择合适的目标
    • 短期监控:使用ring_buffer
    • 长期监控:使用event_file
    • 实时分析:使用histogram或event_counter
  3. 合理设置内存:根据监控需求调整MAX_MEMORY参数
  4. 设置适当的调度延迟:MAX_DISPATCH_LATENCY平衡实时性和性能
  5. 启用因果跟踪:TRACK_CAUSALITY=ON有助于分析相关事件
  6. 配置启动状态:STARTUP_STATE=ON确保SQL Server重启后自动启动会话
  7. 限制文件大小:使用max_file_size和max_rollover_files防止磁盘空间耗尽

性能优化建议

  1. 减少事件数量:只添加必要的事件类型
  2. 使用窄化谓词:谓词条件越具体,收集的数据越少
  3. 避免不必要的动作:只添加需要的ACTION
  4. 使用内存分区:MEMORY_PARTITION_MODE=PER_CPU可提高高并发环境下的性能
  5. 定期清理旧数据:设置合理的文件滚动策略
  6. 避免在高负载时段进行详细监控:可根据时间设置谓词过滤

常见问题(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性能开销的方法包括:

  1. 使用谓词过滤,只收集必要的事件
  2. 减少事件数量和动作数量
  3. 使用高效的目标类型(如ring_buffer或event_counter)
  4. 合理设置内存和调度延迟
  5. 避免在高负载时段进行详细监控

如何查看死锁图形?

答案:可以通过以下方式查看死锁图形:

  1. 在SSMS中,将XML死锁图形结果点击保存为.xdl文件,然后双击打开
  2. 使用SQL Server Profiler打开.xdl文件
  3. 使用第三方工具如SentryOne Plan Explorer查看

XEvents 可以替代 SQL Server Profiler 吗?

答案:是的,Microsoft已经在SQL Server 2019中弃用了SQL Server Profiler,并推荐使用XEvents作为替代方案。XEvents提供了更丰富的功能和更好的性能。

如何监控Azure SQL Database中的事件?

答案:Azure SQL Database支持XEvents,但有一些限制:

  1. 不支持所有XEvents包和事件
  2. 目标类型有限制,主要支持event_file和ring_buffer
  3. 管理方式主要通过T-SQL
  4. 存储位置使用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的新特性,以适应不断变化的数据库环境和业务需求。