快速入门:扩展事件
适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例
扩展事件是一种轻型性能监视功能,它允许用户收集监视和解决问题所需的数据。 借助此功能,可以出于性能监视和解决问题的相关目的,查看数据引擎内部运行的详细信息。 若要了解有关扩展事件的详细信息,请参阅扩展事件概述。
本文旨在帮助不熟悉扩展事件的 SQL 管理员、工程师和开发人员,以及想要在几分钟内开始使用和查看事件数据的开发人员。
扩展事件也称为 XEvents,有时简称为 XE。
阅读本文后,你将可以:
- 了解如何在 SQL Server Management Studio (SSMS) 中创建事件会话,如示例屏幕截图所示
- 将屏幕截图与等效的 Transact-SQL 语句相互关联。
- 详细了解 SSMS 用户界面和 XEvents T-SQL 语句背后的术语和概念
- 了解如何测试事件会话
- 了解会话结果,包括:
- 结果存储的可用选项
- 已处理的结果与原始结果
- 用于在不同时间范围以不同方式查看结果的工具
- 了解如何搜索并发现所有可用事件
- 了解扩展事件系统视图之间的关系
提示
有关 Azure SQL 数据库中的扩展事件的详细信息(包括代码示例),请参阅 Azure SQL 数据库和 Azure SQL 托管实例中的扩展事件。
先决条件
需要满足以下先决条件才能开始使用:
- 下载 SQL Server Management Studio (SSMS)。 建议使用包含最新改进和修复的最新版本的 SSMS。
- 确保你的帐户具有
ALTER ANY EVENT SESSION
服务器权限。
有关扩展事件的安全性和权限的更多详细信息,请参阅本文末尾的附录。
SSMS 中的扩展事件
SSMS 为扩展事件提供功能齐全的用户界面 (UI)。 许多应用场景下都可以使用此 UI 完成,而无需使用 T-SQL 或动态管理视图 (DMV)。
在下一节中,可以看到创建扩展事件会话的 UI 步骤以及它报告的数据。 亲自操作体验或查看过本文中介绍的步骤后,可以更深入地了解这些步骤中涉及的概念。
在 SSMS 中创建事件会话
创建扩展事件会话时,需要告诉系统:
- 你感兴趣的事件
- 希望系统以哪种方式向你报告数据
演示会打开“新建会话”对话框,演示如何使用其四个页面,分别是:
- 一般
- 事件
- 数据存储
- 高级
SSMS 版本中的文本和支持屏幕截图可能略有不同,但应该仍和基本概念的解释相关。
连接到数据库引擎实例。 从 SQL Server 2014 (12.x) 开始,Azure SQL 数据库和Azure SQL 托管实例支持扩展事件。
在“对象资源管理器”中,依次选择“管理 > 扩展事件”。 Azure SQL 数据库的事件会话的范围限于数据库之内,因此可在每个数据而不是“管理”下方找到“扩展事件”选项。 右键单击“会话”文件夹,然后选择“新建会话”。 “新建会话”对话框优于“新建会话向导”,虽然两者非常相似。
选择“常规”页。 然后在“会话名称”文本框中,键入
YourSession
或者任何你喜欢的名称。 不要选择“确定”,因为还需要在其他页面中输入一些详细信息。选择“事件”页。
在“事件库”区域的下拉列表中,选择“仅事件名称”。
- 在文本框中键入“
sql_statement_
”。 这会对列表进行筛选以仅显示名称中带有“sql_statement_
”的事件。 - 滚动并选择名为“
sql_statement_completed
”的事件。 - 选择右箭头按钮
>
将该事件移到“所选事件”框中。
- 在文本框中键入“
继续留在“事件”页,选择“配置”按钮。 会打开所选事件的“事件配置选项”框。
选择“筛选器(谓词)”选项卡,然后选择这里的“选择”添加子句。 我们将此筛选器(也称为谓词)配置为捕获具有
HAVING
子句的所有SELECT
语句。在“字段”下拉列表中选择
sqlserver.sql_text
。- 在“运算符”处,选择
like_i_sql_unicode_string
。 此处,运算符名称里的i
表示不区分大小写。 - 在“值”这里,输入
%SELECT%HAVING%
。 此处,百分号是通配符,代表任何字符串。
注意
在该字段由两部分组成的名称中,sqlserver 是包名称,sql_text 是字段名称。 我们之前选择的事件 sql_statement_completed 必须与我们选择的字段位于同一个包中。
- 在“运算符”处,选择
选择“数据存储”页。
在“目标”区域中,选择“选择此处添加目标”。
- 在“类型”下拉列表中,选择“
event_file
”。 这意味着,事件数据存储在我们可以稍后打开并查看的文件中。 在 Azure SQL 托管实例和 Azure SQL 数据库中,事件数据存储在 Azure 存储 Blob 中。
注意
从 SQL Server 2019 (15.x) 开始,可以在 SQL Server 中的
event_file
目标中使用 Azure Blob 存储。- 在“类型”下拉列表中,选择“
在“属性”区域的“服务器上的文件名”文本框中,键入完整路径和文件名。 你还可以使用“浏览”按钮。 文件扩展名必须为
xel
。 在本示例中,我们使用的是C:\Temp\YourSession_Target.xel
。选择“高级”页。 将“最大调度滞后时间”减少至 3 秒。
选择底部的“确定”,创建此活动会话。
返回对象资源管理器,打开或刷新“会话”文件夹,并查看
YourSession
的新节点。 会话尚未启动。 稍后启动会话。
在 SSMS 中编辑事件会话
在 SSMS 的对象资源管理器中,可以通过右键单击事件会话的节点来编辑该会话,然后选择“属性”。 此时将显示相同的多页对话框。
使用 T-SQL 创建事件会话
在 SSMS 扩展事件 UI 中,可以生成 T-SQL 脚本来创建事件会话,如下所示:
- 右键单击事件会话节点,然后选择“脚本会话作为 > 创建到 > 剪贴板”。
- 粘贴到任意文本编辑器中。
以下是为 YourSession
生成的 CREATE EVENT SESSION
T-SQL 语句:
CREATE EVENT SESSION [YourSession]
ON SERVER -- For SQL Server and Azure SQL Managed Instance
-- ON DATABASE -- For Azure SQL Database
ADD EVENT sqlserver.sql_statement_completed
(
ACTION(sqlserver.sql_text)
WHERE
( [sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text], N'%SELECT%HAVING%')
)
)
ADD TARGET package0.event_file
(SET
filename = N'C:\Temp\YourSession_Target.xel',
max_file_size = (2),
max_rollover_files = (2)
)
WITH (
MAX_MEMORY = 2048 KB,
EVENT_RETENTION_MODE = ALLOW_MULTIPLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY = 3 SECONDS,
MAX_EVENT_SIZE = 0 KB,
MEMORY_PARTITION_MODE = NONE,
TRACK_CAUSALITY = OFF,
STARTUP_STATE = OFF
);
GO
事件会话的条件 DROP
如果已存在具有相同名称的会话,可以在 CREATE EVENT SESSION
语句的前面执行条件语句 DROP EVENT SESSION
。 这会删除现有会话。 如果不执行此操作,则尝试具有相同名称的会话会导致错误。
IF EXISTS (SELECT *
FROM sys.server_event_sessions
WHERE name = 'YourSession')
BEGIN
DROP EVENT SESSION YourSession
ON SERVER;
END
GO
使用 T-SQL 启动和停止事件会话
在创建事件会话时,默认为不自动开始运行该会话。 你可以随时使用以下 T-SQL ALTER EVENT SESSION
语句启动或停止事件会话。
ALTER EVENT SESSION [YourSession]
ON SERVER
STATE = START; -- STOP;
你可以选择配置事件会话在数据库引擎实例启动时自动启动。 请参阅 CREATE EVENT SESSION
中的关键字“STARTUP STATE = ON
”。
在“新建会话 > 一般”页上,SSMS UI 提供相应复选框“当服务器启动时启动事件会话”。
测试事件会话
通过执行以下这些步骤来测试事件会话:
- 在对象资源管理器中,右键单击事件会话节点,然后选择“启动会话”。
- 连接到事件会话创建所在同一服务器(或 Azure SQL 数据库 中的同一服务器)后,运行几次以下
SELECT...HAVING
语句。 每次运行前,考虑更改HAVING
子句中的值,在 2 和 3 之间来回切换。 这样你就可以看到结果中的差异。 - 右键单击会话节点,然后选择“停止会话”。
- 有关如何使用 SELECT 查看结果,请阅读下一小节。
SELECT c.name,
COUNT(*) AS [Count-Per-Column-Repeated-Name]
FROM sys.syscolumns AS c
INNER JOIN sys.sysobjects AS o
ON o.id = c.id
WHERE o.type = 'V'
AND c.name LIKE '%event%'
GROUP BY c.name
HAVING Count(*) >= 3 --2 -- Try both values during session.
ORDER BY c.name;
为了完整起见,下面是上述 SELECT...HAVING
的预期输出。
/* Approximate output, 6 rows, all HAVING Count >= 3:
name Count-Per-Column-Repeated-Name
--------------------- ------------------------------
event_group_type 4
event_group_type_desc 4
event_session_address 5
event_session_id 5
is_trigger_event 4
trace_event_id 3
*/
查看 XML 格式的事件会话数据
在 SSMS 查询窗口中,运行以下 SELECT
语句查看会话捕获的事件数据。 每一行代表有一个事件发生。 CAST(... AS xml)
将 nvarchar 列的数据类型更改为 xml。 这样可以选择列值,在新窗口中打开,更便于查看。
注意
event_file
目标始终在 xel
文件名中插入数字部分。 在运行以下查询之前,必须复制包含此数字部分的文件的实际全名 xel
,然后将其粘贴到语句 SELECT
中。 在以下示例中,数字部分为 _0_131085363367310000
。
SELECT object_name,
file_name,
file_offset,
event_data,
'CLICK_NEXT_CELL_TO_BROWSE_XML RESULTS!' AS [CLICK_NEXT_CELL_TO_BROWSE_XML_RESULTS],
CAST(event_data AS XML) AS [event_data_XML]
-- TODO: In the SSMS results grid, click this XML cell
FROM sys.fn_xe_file_target_read_file(
'C:\Temp\YourSession_Target_0_131085363367310000.xel', NULL, NULL, NULL
);
此查询提供两种方法来查看任何给定事件行的完整结果:
在 SSMS 中运行 SELECT,然后选择
event_data_XML
列中的单元格。从
event_data
列的单元格中复制 XML 字符串。 粘贴到记事本等任意的文本编辑器中,并保存扩展名为xml
文件。 然后在能够显示 XML 数据的浏览器或编辑器中打开此文件。
XML 格式的事件数据
我们下面看到的是结果的一部分,其格式为 XML。 为了简洁起见,以下 XML 已经过编辑。 <data name="row_count">
显示值 6
,这与前面显示的 6 行结果匹配。 我们可以看到整个 SELECT
语句。
<event name="sql_statement_completed" package="sqlserver" timestamp="2016-05-24T04:06:08.997Z">
<data name="duration">
<value>111021</value>
</data>
<data name="cpu_time">
<value>109000</value>
</data>
<data name="physical_reads">
<value>0</value>
</data>
<data name="last_row_count">
<value>6</value>
</data>
<data name="offset">
<value>0</value>
</data>
<data name="offset_end">
<value>584</value>
</data>
<data name="statement">
<value>SELECT c.name,
COUNT(*) AS [Count-Per-Column-Repeated-Name]
FROM sys.syscolumns AS c
INNER JOIN sys.sysobjects AS o
ON o.id = c.id
WHERE o.type = 'V'
AND c.name LIKE '%event%'
GROUP BY c.name
HAVING Count(*) >= 3 --2 -- Try both values during session.
ORDER BY c.name;</value>
</data>
</event>
在 SSMS 中显示事件会话数据
可以使用 SSMS UI 中的多项高级功能来查看事件会话捕获的数据。 有关详细信息,请参阅在 SQL Server Management Studio 中查看事件数据。
从标为“查看目标数据”和“查看实时数据”的上下文菜单选项开始。
查看目标数据
在 SSMS 的 对象资源管理器中,可以右键单击事件会话节点下的目标节点。 在上下文菜单中选择“查看目标数据”。 SSMS 将显示数据。
显示不会更新,因为会话中发生新事件。 不过,你可以再次选择“查看目标数据”。
查看实时数据
在 SSMS 的 对象资源管理器中,可以右键单击事件会话节点。 在上下文菜单中选择“查看实时数据”。 SSMS 将在传入数据持续实时到达时显示这些数据。
扩展事件中的术语和概念
下表列出了用于扩展事件的术语,并描述了它们的含义。
术语 | 说明 |
---|---|
event session |
一种构造,该构造以一个或多个事件为中心,再加上一些支持项(如操作或目标)。 CREATE EVENT SESSION 语句创建每个事件会话。 你可以随时使用 ALTER 来启动和停止事件会话。事件会话有时简称为会话,但前提是上下文表明了它指的是事件会话。 以下文章介绍了有关事件会话的更多详细信息:扩展事件会话。 |
event |
系统中发生的由活动事件会话监视的特定事件。 例如, sql_statement_completed 事件表示任何给定 T-SQL 语句完成的那一刻。 该事件可以报告其持续时间和其他数据。 |
target |
从捕获的事件接收输出数据的项。 目标会向你显示数据。 示例包括本快速入门之前使用的 event_file 目标,以及将最近的事件保存到内存的 ring_buffer 目标。任何类型的目标均可用于任何事件会话。 有关详细信息,请参阅扩展事件的目标。 |
action |
事件已知的字段。 该字段中的数据将发送到目标。 操作字段与 谓词筛选器密切相关。 |
predicate ,或筛选器 |
对事件字段中数据的测试,通过使用该筛选器,可以仅将相关的一部分事件实例发送到目标。 例如,筛选器可以只包含那些 T-SQL 语句含字符串 HAVING 的 sql_statement_completed 事件实例。 |
package |
一种名称限定符,它附加到以事件核心为中心的一组项中的每个项。 例如,包可能包含与 T-SQL 文本有关的事件。 一个事件可能与某个批次中的所有 T-SQL 有关。 同时,另一个更狭窄的事件与单个 T-SQL 语句有关。 此外,任何一个 T-SQL 语句都有 started 和 completed 事件。适用于事件的字段也位于事件所在的包中。 大多数目标位于 package0 中,可与其他许多包中的事件一起使用。 |
扩展事件应用场景和使用情况详细信息
在许多应用场景下,都会用到扩展事件来监视和解决数据库引擎以及查询工作负载的问题。 以下文章提供了与锁定相关的应用场景示例:
- 查找具有最多锁定的对象
- 此应用场景使用目标直方图,该目标会将原始事件数据处理后再以汇总(放入存储桶的)形式向你显示。
- 确定持有锁的查询
- 此应用场景使用 pair_matching 目标,其中事件对是
sqlserver.lock_acquire
和sqlserver.lock_release
。
- 此应用场景使用 pair_matching 目标,其中事件对是
如何发现包中的可用事件
以下查询将为每个名称中包含“sql
”(由三个字符组成的字符串)的可用事件返回一行。 可以编辑 LIKE
子句以搜索不同的事件名称。 结果集还会标识包含相应事件的包。
SELECT -- Find an event you want.
p.name AS [Package-Name],
o.object_type,
o.name AS [Object-Name],
o.description AS [Object-Descr],
p.guid AS [Package-Guid]
FROM sys.dm_xe_packages AS p
INNER JOIN sys.dm_xe_objects AS o
ON p.guid = o.package_guid
WHERE o.object_type = 'event' --'action' --'target'
AND p.name LIKE '%'
AND o.name LIKE '%sql%'
ORDER BY p.name,
o.object_type,
o.name;
以下结果示例显示返回的列,此处透视为 column name = value
格式。 数据来自前面的示例步骤中所使用的 sql_statement_completed
事件。 对象(在本示例中为事件)的说明充当文档字符串。
Package-Name = sqlserver
object_type = event
Object-Name = sql_statement_completed
Object-Descr = Occurs when a Transact-SQL statement has completed.
Package-Guid = 655FD93F-3364-40D5-B2BA-330F7FFB6491
使用 SSMS UI 查找事件
另一个按名称搜索事件的选项是使用“新建会话 > 事件 > 事件库”对话框,如前面的屏幕截图所示。 可以键入部分活动名称,查找所有匹配的活动名称。
SQL 跟踪事件类。
以下文章介绍了如何将扩展事件与 SQL 跟踪事件类和列配合使用:查看与 SQL 跟踪事件类等效的扩展事件。
Windows 事件跟踪 (ETW)
以下文章介绍了如何将扩展事件与 Windows 事件跟踪 (ETW) 配合使用:
系统事件会话
在 SQL Server 和 Azure SQL 托管实例 中,默认情况下会创建多个系统事件会话,并配置为在启动数据库引擎时启动。 与大多数事件会话一样,它们只消耗少量资源,并且不会对工作负载性能造成重大影响。 Microsoft 建议这些会话保持启用和运行。 运行状况会话(尤其是 system_health 会话)通常用于监视和故障排除。
你可以在 SSMS 的对象资源管理器中的“管理 > 扩展事件 > 会话”下面看到这些事件会话。 例如,在 SQL Server 中,这些系统事件会话包括:
AlwaysOn_health
system_health
telemetry_events
PowerShell 提供程序
你可以使用 SQL Server PowerShell 提供程序来管理扩展事件。 有关详细信息,请参阅对扩展事件使用 PowerShell 提供程序。
系统视图
扩展事件的系统视图包括:
- 目录视图:提供由
CREATE EVENT SESSION
定义的事件会话的相关信息。 - 动态管理视图 (DMV):提供正在运行的(已启动)事件会话的相关信息。
SQL Server 中扩展事件系统视图中的 SELECT 和 JOIN — 提供以下内容的相关信息:
- 如何联接视图
- 基于这些视图的多个有用查询
- 以下对象之间的相关性:
- 查看列
CREATE EVENT SESSION
子句- SSMS UI
附录:用于查找扩展事件权限持有者的查询
本文中提到的权限包括:
ALTER ANY EVENT SESSION
VIEW SERVER STATE
CONTROL SERVER
以下 SELECT...UNION ALL
语句返回的行显示了具有为扩展事件创建事件会话和查询系统目录视图所需的权限的人员。
-- Ascertain who has the permissions listed in the ON clause.
-- 'CONTROL SERVER' permission includes the permissions
-- 'ALTER ANY EVENT SESSION' and 'VIEW SERVER STATE'.
SELECT 'Owner-is-Principal' AS [Type-That-Owns-Permission],
NULL AS [Role-Name],
prin.name AS [Owner-Name],
PERM.permission_name COLLATE Latin1_General_CI_AS_KS_WS AS [Permission-Name]
FROM sys.server_permissions AS PERM
INNER JOIN sys.server_principals AS prin
ON prin.principal_id = PERM.grantee_principal_id
WHERE PERM.permission_name IN (
'ALTER ANY EVENT SESSION',
'VIEW SERVER STATE',
'CONTROL SERVER'
)
UNION ALL
-- Plus check for members of the 'sysadmin' fixed server role,
-- because 'sysadmin' includes the 'CONTROL SERVER' permission.
SELECT 'Owner-is-Role',
prin.name, -- [Role-Name]
CAST((IsNull(pri2.name, N'No members')) AS NVARCHAR(128)),
NULL
FROM sys.server_role_members AS rolm
RIGHT JOIN sys.server_principals AS prin
ON prin.principal_id = rolm.role_principal_id
LEFT JOIN sys.server_principals AS pri2
ON rolm.member_principal_id = pri2.principal_id
WHERE prin.name = 'sysadmin';
HAS_PERMS_BY_NAME 函数
以下 SELECT
语句会报告你的权限。 它依赖于内置函数 HAS_PERMS_BY_NAME。
此外,如果有权限临时模拟其他登录,可以取消注释作为登录执行和 REVERT
语句,以查看其他登录是否拥有 ALTER ANY EVENT SESSION
权限。
--EXECUTE AS LOGIN = 'LoginNameHere';
SELECT HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION');
--REVERT;