变更数据捕获(Change Data Capture ,简称 CDC)记录 SQL Server 表的插入、更新和删除活动。使用变更数据捕获可以更有效跟踪表对象DML历史操作,对 ETL 等数据转移也非常有用。
变更数据捕获适用版本:
SQL Server 2008 以上的 Enterprise Edition、Developer Edition 和 eva luation Edition
变更数据捕获原理:
变更数据捕获的更改数据源为 SQL Server 事务日志。当对表启用变更数据捕获时,系统将生成一个与该表结构类似的副本。当对源表进行插入、更新和删除 时,在事务日志会记录相关操作信息。变更数据捕获代理使用异步进程读取事务日志,将相关操作结果应用到副本表(捕获实例表)中,这样就完成了对源表操作的记录跟踪。
变更数据捕获实例:
在数据库 MyDatabase 中创建测试表:
?
-- 创建测试表
USE MyDatabase
GO
CREATE TABLE CDC_Test
(
id int not null,
name varchar(50) not null,
insertDate datetime not null,
value numeric(14,4) not null
)
GO
ALTER TABLE CDC_Test
ADD CONSTRAINT PK_CDC_Test PRIMARY KEY CLUSTERED (id)
GO
CREATE NONCLUSTERED INDEX IX_CDC_Test_NAME ON CDC_Test(name)
GO
CREATE UNIQUE NONCLUSTERED INDEX IX_CDC_Test_insertDate ON CDC_Test(insertDate)
GO
查看数据库或表是否启用了cdc:
?
?
-- 查看数据库是否启用cdc
SELECT name,is_cdc_enabled FROM sys.databases WHERE is_cdc_enabled = 1
-- 查看当前数据库表是否启用cdc
SELECT name,is_tracked_by_cdc FROM sys.tables WHERE is_tracked_by_cdc = 1
对当前数据库启用cdc :
?
?
-- 对当前数据库启用cdc
USE MyDatabase
GO
EXECUTE sys.sp_cdc_enable_db;
GO
可能出现以下错误及解决办法:
?
?
/*
消息 22830,级别 16,状态 1,过程 sp_cdc_enable_db_internal,第 186 行
无法更新元数据来指示已对数据库 MyDatabase 启用了变更数据捕获。执行命令 'SetCDCTracked(Value = 1)' 时失败。
返回的错误为 15404: '无法获取有关 Windows NT 组/用户 'KK\administrator' 的信息,错误代码 0x54b。'。
请使用此操作和错误来确定失败的原因并重新提交请求。
消息 266,级别 16,状态 2,过程 sp_cdc_enable_db_internal,第 0 行
EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。
消息 266,级别 16,状态 2,过程 sp_cdc_enable_db,第 0 行
EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。
消息 3998,级别 16,状态 1,第 1 行
在批处理结束时检测到不可提交的事务。该事务将回滚。
*/
-- 原因是数据库所有者为Windows用户,改为“sa”
EXEC dbo.sp_changedbowner @loginame = N'sa', @map = false
GO
--依赖别名已删除
?
启动数据库cdc后,接着对指定源表启用 cdc :
?
-- 接着对指定源表启用cdc
EXEC sys.sp_cdc_enable_table
@source_schema= 'dbo', --源表架构
@source_name = 'CDC_Test', --源表
@role_name = 'CDC_Role' --角色(将自动创建)
GO
--作业 'cdc.MyDatabase_capture' 已成功启动。
--作业 'cdc.MyDatabase_cleanup' 已成功启动。
创建完成后,将看到数据库中创建了以下对象:
?

?
-- 也可以使用脚本查看跟踪表的信息
EXEC sys.sp_cdc_help_change_data_capture
GO
EXEC sys.sp_cdc_help_change_data_capture 'dbo', 'CDC_Test'
GO
下面介绍系统表中,各表的主要信息:
?
?
【cdc.captured_columns】
select * from cdc.captured_columns
每个启用变更数据库捕获的表,其已跟踪的列都可在该系统表中查看(参考: cdc.captured_columns )
?
EXEC sys.sp_cdc_get_captured_columns N'dbo_CDC_Test';
建议使用该存储过程返回列的元数据信息 (参考:sys.sp_cdc_get_captured_columns )
【cdc.change_tables】
?
select *from cdc.change_tables
每对一个源表启用变更数据捕获时,该表都会记录其实例表的详细信息(参考:cdc.change_tables)
?
EXEC sys.sp_cdc_help_change_data_capture
EXEC sys.sp_cdc_help_change_data_capture @source_schema= 'dbo' ,@source_name ='CDC_Test'
最多可为每个源表返回两行,为每个捕获实例返回一行 (参考:sys.sp_cdc_help_change_data_capture)
【cdc.index_columns】
?
select *from cdc.index_columns
对源表中的主键列或者启用变更数据捕获时指定的唯一索引列(指定索引优于主键)记录一行,变更数据捕获使用这些索引列来唯一标识源表中的行。默认情况下,将包括源表的主键列。(参考:cdc.index_columns)
EXEC sys.sp_cdc_help_change_data_capture @source_schema = 'dbo' ,@source_name = 'CDC_Test'
或者使用该存储过程查看(如上图)
【cdc.ddl_history】
?
select *from cdc.ddl_history
针对启用了变更数据捕获的表所做的每一数据定义语言(DDL)更改返回一行。可以使用此表来确定源表发生DDL 更改的时间以及更改的内容。(参考:cdc.ddl_history)
?
EXEC sys.sp_cdc_get_ddl_hist