1.业务背景
随着公司业务的成长,数据量也随之的不断增长。随之而来的问题是在做ETL的时候,时间花费也越来越长。
为了节省时间开销,我们只想要更新最新的数据,不想要把公司历年所有的数据都进行处理。这种情况就被称为变更数据捕获(Change Data Capture,又名CDC)
2.启用SQL Server 的CDC功能
首先要确保数据库版本是企业版或者开发版,标准版是不支持CDC功能的。
SELECT is_cdc_enabled,* FROM sys.databases --查看数据库是否开启了CDC功能
EXEC sys .sp_cdc_enable_db --启用CDC功能
(如果启用时发生了错误:Could not update the metadata that indicates database ...The error returned was 15517 ,执行EXEC sp_changedbowner 'sa')
以官方的示例数据库AdventureWorks2014当中的表Employee为例,执行以下语句:
execute sp_cdc_enable_table
@source_schema=N'HumanResources'
,@source_name= N'Employee'
,@role_name= N'cdc_Admin'
,@capture_instance= N'HumanResources_Employee'
,@supports_net_changes= 1
系统会在system tables 下新建名为cdc.HumanResources_Employee_CT的追踪表。
使用SELECT 语句查看该表,可以发现该表除了保留了源表Employee一样的结构以外,同时还新增了几个额外的数据列:
Column name | Description |
__$start_lsn | 表示操作的顺序,同一个transaction的lsn号相同 |
__$end_lsn | 始终为null |
__$seqval | transaction内操作的顺序 |
__$operation | 引起更改的源操作 |
1 = 删除 | |
2 = 插入 | |
3 = 更新 (前映像) | |
4 = 更新 (后映像) | |
5 = 合并 | |
__$update_mask | 表示哪些特定列发生了更改。需要通过sys.fn_cdc_has_columns_changed等函数来理解该列的意义 |
试着对employee进行操作
UPDATE [HumanResources].[Employee] SET JobTitle='IT Manager' WHERE BusinessEntityID='288'
再次查看该表:
SELECT * FROM [cdc].[HumanResources_Employee_CT]
可以看到新增了两条记录,而__$operation分别对应了更新前和更新后的内容。
3.查看捕获数据
官方并不建议直接查询追踪表,可以使用官方定义好的方法cdc.fn_cdc_get_all_changes_<capture_instance> 以及 cdc.fn_cdc_get_net_changes_<capture_instance>
DECLARE @from_lsn binary(10), @to_lsn binary(10); SET @from_lsn = sys.fn_cdc_get_min_lsn('HumanResources_Employee'); SET @to_lsn = sys.fn_cdc_get_max_lsn(); SELECT * FROM cdc.fn_cdc_get_all_changes_HumanResources_Employee(@from_lsn, @to_lsn, N'all')--返回LSN所有更改行 SELECT * FROM cdc.fn_cdc_get_net_changes_HumanResources_Employee(@from_lsn, @to_lsn, N'all');--返回LSN最终结果
4.补充说明
CDC会在服务器运行一个进程,该进程从日志文件中读取更改内容,把他们写入跟踪表中。通过这样的异步处理,CDC几乎不会增加服务器的性能开销。
如果需要强制刷新而不是等待异步处理的话,运行SP: sys.sp_cdc_start_job
如果需要关闭CDC,运行SP: sp_cdc_disable_table
版权声明:本文为博主原创文章,未经博主允许不得转载。