8. 继续在Product表上提交DML语句
DELETE dbo.Product WHERE ProductID = 1;提交完了这条命令后,就会在lsn_time_mapping和dbo_Product_CT中分别看到一条新记录。
其中dbo_Product_CT表中的_$operation字段的值是1,_$update_mask字段的值是0x07。
9. 提交一个DDL试试看
ALTER TABLE dbo.Product ADD Description nvarchar(100);提交完这句命令后,只会在ddl_history表中看到一条新的记录。
10. 然后再试试DML
UPDATE dbo.Product SET Description = N'NA';提交完这句语句后,所有cdc架构下的表中都没有看到新记录。说明新增的列Description不跟踪更新了......估计有人会说(细心的人哦!):“这次当然看不到新记录了,因为在前面第7步我们已经删除了所有的记录,因此这次的UPDATE语句没有影响到任何记录,当然CDC的表中不会有任何记录了。”那么到底对Description更新会不会记录呢,经过测试确实是不记录的。
那么如果我们想对Description也进行更新跟踪应该怎么办呢?很简单的,由另外一个存储过程叫做sp_cdc_disable_table_change_data_capture可以禁用对某张表的更新跟踪,可以使用这个存储过程先对Product表禁用更新跟踪,然后再重新启用对Product表的更新跟踪就可以了。
11. 最后试一下DROP命令
DROP TABLE dbo.Product;dbo.Product表消失了,同时cdc.dbo_Product_CT表也消失了。
12. 评估结束。哦,对了。一定有人问,捕获到的更新怎么用呢,还有一堆系统函数和存储过程可以帮助用户,但是那段测试的过程就不详细写了。
其中最重要的应该就是cdc.fn_cdc_get_all_changes_<capture_instance>和cdc.fn_cdc_get_net_changes_<capture_instance>两个函数了,这两个函数可以帮助我们获取dbo_Product_CT表中数据,其中cdc.fn_cdc_get_all_changes_<capture_instance>是用于获取所有更新,而cdc.fn_cdc_get_net_changes_<capture_instance>则是用于获取精简后的更新,在精简的更新中有一些重复的更新就会被合并成一条记录,比如说我们把产品类型由A改为B,然后又改回A,在cdc.fn_cdc_get_all_changes_<capture_instance>中应该有3条记录,而在cdc.fn_cdc_get_net_changes_<capture_instance>中则只有1条记录。两个函数的范例如下(你会发现精简结果集的函数运算相当慢,至少在CTP4中是这样的,不知道以后的版本会不回有改进):
SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_Product(0x00000048000001760004, 0x00000048000001F70004, 'all');CDC功能的IO开销
SELECT * FROM cdc.fn_cdc_get_net_changes_dbo_Product(0x00000048000001760004, 0x00000048000001F70004, 'all');
很明显,CDC功能是会产生一定的IO和存储开销的,为了评估CDC功能产生的这些开销。我又进行了一段评测。
整个评估的思路是这样的:
1. 创建两个数据库
2. 在两个数据库中分别创建一张结构完全相同的表,一个数据库启用CDC功能,而另外一个禁用CDC功能
3. 向两张表中写入相同行数的数据
4. 利用动态管理视图sys.dm_io_virtual_file_stats来获得两个数据库文件上的IO
5. 利用sysindexes来获得两个数据库中数据表的存储消耗情况
因为是在虚拟机中进行的测试,所以选取了比较小的数据表(AdventureWorks数据库中的SalesOrderDetails),大约有12万行数据。
评估的结果如下:
从上面两张表中可以看到,CDC激活后日志文件的读会显著增加。原因是CDC在写更新跟踪表时,需要读取日志。

