我们在读写数据库文件时,当文件被读、写或者出现错误时,这些过程活动都会触发一些运行时事件。从一个用户角度来看,有些时候会关注这些事件,特别是我们调试、审核、服务维护。例如,当数据库错误出现、列数据被更新、CPU占用过高等,跟踪这些状态是非常有用地。
本章节覆盖了事件系统的关键区域:触发器、事件通知器、改变跟踪、SQL跟踪、扩展事件等。这些事件都有一个相似目的:响应或者记录发生的事件。但每一中事件的工作方式又不一样。
基础:触发器和事件通知器
触发器非常多,Data Manipulation Language (DML) triggers定义于当插入、更新数据时激发一个操作;Data Definition Language (DDL)
triggers 定义于当服务器或者数据库级活动发生时激发某个操作,例如登陆或者删除某张表。DML触发器能激发代替触发中的事件,或者当这个事件完成后但是没有提交时。DDL triggers只能配置成事件已经完成但事物没有提交。事件通知器和DDL Trigger相似,不同的一重要点是它不需要任何Transaction,作为一个结果支持非事物事件。例如一个用户断开和数据库的连接。
改变跟踪
首先举一个例:有些系统需要把数据库缓存在本地,同时要求随时关注数据库数据是否有更新,能够随时保持缓存和数据库的同步。这种情况更多的实现方式是使用触发器或者时间戳。但这样设计也会经常带来问题问题。例如,如果时间戳列在插入数据时统计而不是在提交时统计时,时间戳经常失效。这样存在的问题是,如果一个大数据插入的同时其他小数据也在插入,但这个大数据提交比小数据提交慢。因此影响了时间戳的自然排序。触发器可以解决一些问题,但是它也增加了事物的提交时间。
Change Tancking被设计用来跟踪单表或者多表的数据变化。让用户方便的决定改变触发的顺序。它作为事物的一部分同步跟踪改变发生。
Change Tracking基于基线工作的思想。数据客户首先请求跟踪表里边所有行的当前状态也得到了每一行的版本号。基线版本号是系统知道的当前最大的版本号。直到下一个同步器请求时它会被同步,当这个请求发生,基线版本号被发送回到Change Tracking系统,通过比对跟踪表裂变的版本和基线表里边的版本确定该系统哪些行已经被修改自从第一次请求。
Sql Server 2008包括两个相似的技术用来支持同步:Change Tracking和Change Data Capture。Change Tracking支持离线应用,也支持某些连接的应用以及其他不需要实时通知当数据被更新。
改变跟踪配置
改变跟踪配置有两个配置级别,一个是数据库配置级别,另外一个是表配置级别。
1)数据库配置级别。可以使用sql指令ALTER DTABASE来修改变化跟踪配置 ,数据库默认是启动了跟踪配置,我们可以执行以下指令启动跟踪:
ALTER DATABASE heavi_case1
SET CHANGE_TRACKING = ON;
说明:执行这条语句后,一旦表级别跟踪启动后将跟踪两个变化:第一个,一个隐藏的系统表将用来跟踪目标数据库;第二个,一个清理任务将开始评估相关表里边是否遗留比较久的行数据。
a)隐藏的系统表
这个隐藏的表叫做提交表(Commit Table),它为在变化跟踪里边出现的每一个数据库提交事物生成一个行数据。当事物发生,一个等量的事物被标记,它包含一个唯一标识、序列标识(Commit Sequence Number,CSN)。CSN随着事物标示、日期序列信息、开始时间、其他数据一起插入到Commit Table中。这个表主要用来提供数据给改变跟踪(Change Tracking)和帮助决策当一个用户请求一个更新时哪个改变将要被同步。
我们可以通过sys.all_columns目录视图查看Commit Table的列和索引。Commit Table的历史名称叫做sys.syscommitab。我们可以执行以下语句:
SELECT *
FROM sys.all_columns
WHERE object_id = OBJECT_ID('sys.syscommittab');
执行结果如下:
sys.syscommitab有两个索引:一个聚集索引在commit_ts和xdes_id列上,一个非聚集索引在xdes_id上。
必须说明的是Commit Table值存储事物信息,而没有存储真实的行数据。这些相关的数据是存储在分割的系统表中。因为一个事物能联合多个表并且每个表可能有多行数据,如果都存储在Commit Table中那么数据量会非常大。Commit Table中所有的列除了dbfragid,都可以通过动态管理试图(DMV)sys.dm_tran_commit_table来查询。
b)内部清理任务
一旦Commit生成了数据,这些数据也将占据数据库一定内存。Change Tracking包含功能启动内部任务来处理哪些不需要的历史数据。我们可通过以下sql来配置:
ALTER DATABASE heavi_case1
SET CHANGE_TRACKING = ON
(AUTO_CLEANUP=ON, CHANGE_RETENTION=1 hours);
如果可用,内存任务每30分钟执行一次,评估哪些事务需要被移除(通过当前时间减去保留时间得到一个时间差,然后通过一个接口从Commit Table中找出时间范围大于时间差的事物ID,最后通过事物ID从Commit Table和其他隐藏表中移除事物)。
清理任务配置可通过以下sql查询:
select * from sys.change_tracking_databases;
2)表级配置
要为某一个表启动表级别配置。可通过ALTER TABLE和ENABLE CHANGE_TRACKING配置。例如,我们为hvi_Order表启动配置:
ALTER TABLE hvi_Order ENABLE CHANGE_TRACKING;
如果Change Tracking启动了数据库级配置,当运行这条语句会产生两个变化。第一,数据库会创建一个内部表跟踪目标表的行数据事物。第二,一个隐藏的列被增加到目标表,通过事物ID跟踪特殊行变化。
被创建的内部表命名规则为sys.change_tracking_[object_id],object id可通过sys.all_objects目录视图查找。或者通过sys.internal_tables查找(条件为internal_type等于209)。sql语句分别如下:
select distinct * from sys.all_objects where parent_object_id in
(select object_id from sys.all_objects where [name] like 'hvi_Order') # 我这样写便于大家识别
select * from sys.internal_tables where parent_object_id in
(select object_id from sys.all_objects where [name] like 'hvi_Order')
上面我们说到别级别还会杂目标表中增加额外的8字节列记录最新的事物ID。如果Change tracking关闭,该列也会被移除。
改变跟踪运行时行为
Change Tracking启动表级别后附加的修改了每一个DML操作行为。也可以通过CHANGETABLE允许数据用户找出哪些行发生了变化并需要同步。
接下来我们往hvi_Order表中插入一行数据,同时查看执行计划过程。
sql语句:insert into dbo.hvi_Order(createtime, cus_id) values('2015/11/1', 2);
查询分析过程:
我们比对下没有启动表级别跟踪的表插入数据执行分析过程:
可以看出,启动表级别跟踪后,执行过程会通过内部变化表如果有输入插入更新。
跟踪和Profiling(没明白中文意思)
查询调整、优化、一般故障解决都可以通过可见的过程产生。SQL Trace是一个比较强大的工具用来提供查询数据库引擎正在做什么。通过跟踪工具,我们可以监视180个事件。在这些事件中,我们可以通过特殊的session id(SPID)查看用户登录、锁活动的细节信息。这些数据通过SQL Server Profiler生成,以及一系列的服务端存储过程和.NET classes,并且可以提供给你灵活性回滚自定义的解决方法当出现问题。
SQL Trace是一个数据库引擎技术,必须要理解的一点是常常客户端配置工具仅仅是去封装了服务端的功能。在跟踪时,当各种活动出现在数据库引擎中,我们监视各种事件。例如,一个用户登录或者执行查询的每一个活动都会出发事件去捕获。并且这些事件是通过数据库引擎代码去捕获。换一种说法,特殊的代码已经被添加到执行路径中,通过这些代码出发事件。例如一个查询案例,当查询开始我们能收集数据,包括查询执行时间、占用CPU多少时间。
Sql Server来龙去脉系列目录结构:
Sql Server来龙去脉系列之五 日志以及恢复
Sql Server来龙去脉系列之六 表
Sql Server来龙去脉系列之七 索引
Sql Server来龙去脉系列之八 比较特殊的存储
Sql Server来龙去脉系列之九 查询优化
Sql Server来龙去脉系列之十 计划缓存
Sql Server来龙去脉系列之十一 事务和并发