前几天,有生产人员反映库中某张表的数据总是会被更新,而该表的维护方式为纯人工维护,所以找到我,希望找出这张表的操作记录.由于该表的更新人并未发生变化,所以排除人工更新数据的可能性。借此判断是后台程序更新数据所致。
找相应的操作记录,我首先想到的是使用DMV查询正在进行的进程。但是由于不知道这张表的更新规律,无法确定更新时间。且该表数据可能是一条条更新,实际执行时间极短,很难抓到操作语句,因此此方法并未帮助我找到操作语句。
第二个方法是使用fn_dblog()获取日志记录进行分析。但是由于该库数据表多,操作多,因此每分钟的日志数量都很庞大,想在几十万条日志记录中找出一条操作记录,不太现实。使用时间条件限制,有可能会导致数据库出现短暂的宕机风险,所以该方法也不太现实。
第三个方法是使用日志分析工具分析。但是由于日志量太大,也失败了。
就是这么无奈。。。
后来这个事情是怎么解决的呢?看标题也知道啦,靠得就是扩展事件。我们来看一下微软官方是怎么介绍扩展事件的。
SQL Server 扩展事件 (Extended Events) 是用于服务器系统的常规事件处理系统。扩展事件基础结构支持 SQL Server 中数据的关联,并且在某些情况下,还支持操作系统和数据库应用程序中数据的关联。所有应用程序都具有在应用程序外部和内部均有用的执行点。在应用程序内部,可以使用任务初始执行期间收集到的信息对异步处理进行排队。在应用程序外部,执行点为监视实用工具提供被监视应用程序的行为和性能特征的有关信息。
接下来,我们通过GUI界面实际操作来了解扩展事件的相关概念与实际功能。
打开数据库,打开新建会话向导
输入会话名称,此名称即为扩展事件名称。
下一步,选择模板,该页面有两个选项,一个是选择模板.该模板中有预先定义好的事件模板,从中可以看到有查询执行类,锁和块类等模板。
左侧为事件库,从中可以选择我们想要监控的事件,官方对她的解释是:事件是程序(例如SQL Server)的执行路径中的相关监视点。事件触发即表明已经到达相关点,并具有自事件触发以来的状态信息。
事件可仅用于跟踪目的或用于触发操作。这些操作可以是同步的,也可以是异步的。
通俗理解即我们想监控的是什么。
在下方搜索框中输入事件关键字,即可搜索到相关事件,点击事件可以在左下角看到该事件的详细解释。中下部分可以看到该事件字段,说明中写有详细含义。双击该事件或单击该事件后点击右侧箭头,即可选中该事件。
由于我们需要找到这张表的操作记录,所以在事件里面选择rpc_completed(远程过程调用已完成时发生),sql_satement_completed 事件(在语句完成时发生)。
点击下一步选择全局字段,该页面含有选择事件可捕获的相关字段,右侧附有详细说明.
由于需要找出语句的执行者及详细脚本,所以这里选择收集客户端应用程序名称,客户端主机名,数据库名称,脚本,用户名等信息。
点击下一步进行设置会话事件筛选器。第一列标识的是多条家条件下的逻辑关系。第二列为可选择的全局字段。第三列为运算符,第四列为值,四个列拼接在一起就是满足该条件的事件才会被捕获。
这里我们限制只捕获test表的相关语句,即将条件设置为SQL脚本包含’test’
点击下一步,指定会话数据存储,可以选择将数据保存至文件,以待存档和后续数据分析,或选择不存档数据,仅使用最新数据。这对于较小数据集或短暂性收集数据十分便利。
点击“下一步”,新建向导完成。
右键选择该扩展事件属性,可设置各项参数。
常规:会话名称,模板,计划
事件:重新选择监控事件
数据存储:确定数据存储的文件目标类型或聚合事件数据等操作
高级:事件保留模式,最大调度滞后时间(事件触发到写入目标文件的滞后时间),最大内存大小,最大事件大小。
创建完成后,可在左侧列表中查看到该扩展事件会话。右键点击开启即可
启动该扩展事件。
其创建脚本如下:
CREATE EVENT SESSION [test] ON SERVER
ADD EVENT sqlserver.rpc_completed(
ACTION(sqlserver.client_hostname,sqlserver.database_name,sqlserver.server_instance_name,sqlserver.session_id,sqlserver.sql_text,sqlserver.username)
WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%test%')AND [sqlserver].[database_name]=N'AdventureWorks2012')),
ADD EVENT sqlserver.sp_statement_completed(
ACTION(sqlserver.client_hostname,sqlserver.database_name,sqlserver.server_instance_name,sqlserver.session_id,sqlserver.sql_text,sqlserver.username)
WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%test%')AND [sqlserver].[database_name]=N'AdventureWorks2012'))
ADD TARGET package0.event_file(SET filename=N'test')
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=OFF,STARTUP_STATE=OFF)
GO
双击文件,可查看捕获到的事件。由于设置了最大调度滞后时间,所以并不是查询完成后就乐意立即看到,通常要等一段时间。
最终效果图如下: