使用SQL Server扩展事件捕获访问视图的用户
扩展事件捕获视图访问的优化方案
原测试代码的问题分析
Test 1 问题
- object_type过滤值错误:
[object_type]='V '包含多余空格,SQL Server中视图的object_type值是'V'(无空格),这是导致无数据捕获的核心原因。 - 缺少数据库过滤:未限定目标数据库,可能捕获其他库同名视图的访问,也会增加不必要的事件量。
- 未排除系统操作:没有过滤
sqlserver.is_system = 0,会捕获SQL Server内部的系统访问操作。
Test 2 问题
- sql_text匹配不可靠:用
like_i_sql_unicode_string匹配sql_text中的视图名称,无法覆盖所有场景(比如视图被别名引用、嵌套在子查询/存储过程中,或者语句中包含与视图名相同的字符串),会出现漏捕或误捕。 - 仅捕获批量查询开始:
sql_batch_starting只能捕获即席查询的开始事件,无法捕获通过存储过程、函数等模块调用视图的场景。
优化后的扩展事件会话代码
方案1:精确捕获所有视图访问(推荐)
使用sqlserver.object_accessed事件,能够精确捕获任何方式(直接查询、模块调用、嵌套访问)对视图的访问,过滤条件更精准:
CREATE EVENT SESSION [Track_View_Access] ON SERVER ADD EVENT sqlserver.object_accessed( ACTION( sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.database_name, sqlserver.session_server_principal_name, sqlserver.username, sqlserver.sql_text, sqlserver.tsql_stack ) WHERE ( sqlserver.is_system = 0 -- 排除系统操作 AND object_type = 'V' -- 视图类型,无空格 AND object_name = N'MyView' -- 目标视图名 AND database_name = N'myDB' -- 目标数据库名 ) ) ADD TARGET package0.event_file( SET filename=N'C:\Event_Trace\XE_Track_view.xel', max_rollover_files=(20) ) WITH ( MAX_MEMORY=1048576 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=5 SECONDS, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=PER_CPU, TRACK_CAUSALITY=ON, STARTUP_STATE=ON ) GO
方案2:修正Test1的module_start事件
如果坚持使用module_start,修正过滤条件并补充必要限制:
CREATE EVENT SESSION [Track_View_Module] ON SERVER ADD EVENT sqlserver.module_start( SET collect_statement=1 ACTION( sqlserver.client_app_name, sqlserver.database_name, sqlserver.session_server_principal_name, sqlserver.username, sqlserver.sql_text, sqlserver.tsql_stack ) WHERE ( sqlserver.is_system = 0 -- 排除系统操作 AND object_type = 'V' -- 修正为无空格的'V' AND object_name = N'MyView' AND database_name = N'myDB' -- 限定数据库 ) ) ADD TARGET package0.histogram( SET filtering_event_name=N'sqlserver.module_start', source=N'object_name', source_type=(0) ), ADD TARGET package0.event_file( SET filename=N'C:\Event_Trace\XE_Track_view.xel', max_rollover_files=(20) ) WITH ( MAX_MEMORY=1048576 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=5 SECONDS, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=PER_CPU, TRACK_CAUSALITY=ON, STARTUP_STATE=ON ) GO
关键注意事项
- 启动事件会话:创建完成后需执行
ALTER EVENT SESSION [Track_View_Access] ON SERVER STATE = START;启动会话,否则不会捕获数据。 - 权限验证:确保创建会话的账号拥有
ALTER ANY EVENT SESSION权限,查看事件文件需要对应文件系统权限。 - 测试验证:使用不同方式访问视图(直接查询、存储过程调用、应用程序访问),然后通过以下语句查看捕获的事件数据:
SELECT event_data.value('(event/@name)[1]', 'varchar(50)') AS event_name, event_data.value('(event/@timestamp)[1]', 'datetime2') AS event_time, event_data.value('(event/action[@name="database_name"]/value)[1]', 'varchar(100)') AS database_name, event_data.value('(event/action[@name="session_server_principal_name"]/value)[1]', 'varchar(100)') AS login_name, event_data.value('(event/action[@name="username"]/value)[1]', 'varchar(100)') AS database_user, event_data.value('(event/action[@name="client_app_name"]/value)[1]', 'varchar(100)') AS client_app, event_data.value('(event/action[@name="sql_text"]/value)[1]', 'nvarchar(max)') AS sql_text FROM (SELECT CAST(event_data AS XML) AS event_data FROM sys.fn_xe_file_target_read_file('C:\Event_Trace\XE_Track_view*.xel', NULL, NULL, NULL)) AS x ORDER BY event_time DESC;
内容的提问来源于stack exchange,提问作者dan Kalio
相关产品推荐
相关产品推荐

