使用SQLServer2008的CDC功能实现数据变更捕获


 

    SQLServer2008之前,对数据变更的捕获通常使用触发器、时间戳等低效高成本的功能来实现,所以很多系统都没有做数据变更或者仅仅对核心表做监控。

    自从SQLServer2008引入了数据变更捕获功能(后面简称为CDC)后,解决了很多烦恼问题,如客户2个月前更改了一个数据,但是由于服务器空间不足,经常只能保留一个月的备份。此时客户为了逃避因为更改数据带来的较大负面影响,往往会把责任推给软件开发商或者运维商,如果此时有变更捕获的话,就有证据了,当然分析日志也能实现,但是比较痛苦。

 

    使用CDC功能需要表有主键数据库版本为企业版。

 

1.创建一个测试数据库

USE master

GO

IF EXISTS(SELECT name FROM sys.databases WHERE name = 'TEST_DB')

DROP DATABASE TEST_DB

GO

CREATE DATABASE TEST_DB

GO

 

 

2.切换数据库到TEST_DB,并开启CDC

--查看数据库是否启用CDC

SELECT name,is_cdc_enabled FROM sys.databases WHERE name = 'TEST_DB'

 

--启用数据库TEST

USE TEST_DB

GO

EXECUTE sys.sp_cdc_enable_db;

GO

 

--检查启用是否成功

SELECT is_cdc_enabled,CASE WHEN is_cdc_enabled=0 THEN 'CDC功能禁用' ELSE 'TEST功能启用' END 描述

FROM sys.databases

WHERE NAME = 'TEST_DB'

 

 

3.创建测试表,并对测试表启用CDC捕获数据

----创建一个测试表,对表行变更启用捕获,为表t_shall启用CDC,首先会在系统表中创建[TEST_DB].[dbo_t_shall_CT],会在Agent中创建两个作业,cdc.TEST_DB_capturecdc.TEST_DB_cleanup,启用表变更捕获需要开启SQL Server Agent服务,不然会报错。每对一个表启用捕获就会生成一个向对应的记录表。

--创建测试表

USE TEST_DB

GO

CREATE TABLE [dbo].[t_shall](

    [ID] [smallint] IDENTITY(1,1) NOT NULL,

    [Name] [nvarchar](200) NULL,

    [GroupName] [nvarchar](50) NOT NULL,

    [ModifiedDate] [datetime] NOT NULL,

    [AddName] [nvarchar](120) NULL,

 CONSTRAINT [PK_t_shall_ID] PRIMARY KEY CLUSTERED

(

    [ID] ASC

) ON [PRIMARY]

) ON [PRIMARY]

GO

 

--对表启用捕获

EXEC sys.sp_cdc_enable_table

    @source_schema= 'dbo',

       @source_name = 't_shall',

       @role_name = N'cdc_Admin',  --会在该数据库中自动创建一个cdc_admin角色

       @capture_instance = DEFAULT,

       @supports_net_changes = 1,

    @index_name = NULL,

    @captured_column_list = NULL,

    @filegroup_name = DEFAULT

 


 

--检查是否成功

SELECT name, is_tracked_by_cdc ,

    CASE WHEN is_tracked_by_cdc = 0 THEN 'CDC功能禁用' ELSE 'CDC功能启用' END 描述

FROM sys.tables

WHERE OBJECT_ID= OBJECT_ID('dbo.t_shall')

 

--返回某个表的变更捕获配置信息

EXEC sys.sp_cdc_help_change_data_capture 'dbo', 't_shall'

 

 

4.执行dml测试语句,并看效果

--测试插入数据

INSERT  INTO dbo.t_shall(

    Name ,

    GroupName ,

    ModifiedDate

)VALUES('zhong','groups',GETDATE())

go

INSERT  INTO dbo.t_shall(

    Name ,

    GroupName ,

    ModifiedDate

)VALUES('zhang','dml',GETDATE())

go

 

--测试更新数据

UPDATE dbo.t_shall SET Name = 'shall',ModifiedDate = GETDATE()

WHERE Name = 'zhong'

go

 

--测试删除数据

DELETE FROM dbo.t_shall WHERE Name= 'zhang'

go

 

--查询捕获数据

SELECT * FROM cdc.dbo_t_shall_CT

go

----对于insert/delete操作,会有对应的一行记录,而对于update,会有两行记录。__$operation列:1 = 删除、2= 插入、3= 更新(旧值)、4= 更新(新值)

 

5.启用CDC之后,怎么从中获取到数据呢?

----通过数据我们可以对数据进行恢复。使用LSN查看CDC记录

--查询捕获数据

SELECT * FROM cdc.dbo_t_shall_CT

go

 

SELECT sys.fn_cdc_map_time_to_lsn

('smallest greater than or equal', '2016-09-01 14:13:14.813') AS BeginLSN

go

SELECT sys.fn_cdc_map_time_to_lsn

('largest less than or equal', '2016-09-01 14:13:24.947') AS EndLSN

go

 

/******* 查看某时间段所有CDC记录*******/

DECLARE @FromLSN binary(10) =

sys.fn_cdc_map_time_to_lsn

('smallest greater than or equal' , '2016-09-01 14:13:14.813')

 

DECLARE @ToLSN binary(10) =

sys.fn_cdc_map_time_to_lsn

('largest less than or equal' , '2016-09-01 14:13:24.947')

 

SELECT CASE [__$operation]

WHEN 1 THEN 'DELETE'

WHEN 2 THEN 'INSERT'

WHEN 3 THEN 'Before UPDATE'

WHEN 4 THEN 'After UPDATE'

END Operation,[__$operation],[__$update_mask],Id,Name,GroupName,ModifiedDate,AddName

FROM [cdc].[fn_cdc_get_all_changes_dbo_t_shall]

(@FromLSN, @ToLSN,  N'all update old')

 

/*

all 其中的update,只包含新值

all update old 包含新值和旧值

*/

 

 

6.CDC的维护

--返回所有表的变更捕获配置信息

EXECUTE sys.sp_cdc_help_change_data_capture;

 

--返回某个表的变更捕获配置信息

EXEC sys.sp_cdc_help_change_data_capture 'dbo', 't_shall'

 

--查看对某个表的哪些列做了捕获监控,使用上面返回的capture_instance列值

EXEC sys.sp_cdc_get_captured_columns

@capture_instance = 'dbo_t_shall'

 

 

    由于sys.sp_cdc_enable_table 的参数:@captured_column_list = NULL,所以dbo.t_shall表的所有字段都进行监控了,如果你只关心某些字段,强烈建议在创建捕获的时候设置这个属性;

 

--所有数据库CDC Job信息

SELECT B.name,A.* FROM msdb.dbo.cdc_jobs AS A

LEFT JOIN sys.databases AS B

ON A.database_id = B.database_id

 

--当前数据库CDC Job信息

EXEC sp_cdc_help_jobs

 

 

7.补充说明

    SQL Server记录数据变更有四种方法:触发器、Output子句、变更数据捕获(Change Data Capture CDC)功能、同步更改跟踪。其中后两个为SQL Server 2008所新增。

 

    1> CDC功能主要捕获SQLServer指定表的增删改操作;

    2> CDC除了捕获数据变更之外,还能捕获DDL操作的变化;

    3> 无法对系统数据库和分发数据库启用该功能。且执行者需要用sysadmin角色权限;

    4> cdc._CT   可以看到,这样命名的表,是用于记录源表更改的表。

 

对于insert/delete操作,会有对应的一行记录,而对于update,会有两行记录;

对于__$start_lsn列:由于更改是来源与数据库的事务日志,所以这里会保存其事务日志的开始序列号(LSN);

对于__$end_lsn列:

对于__$seqval列:

对于__$operation列:1 = 删除、2= 插入、3= 更新(旧值)、4= 更新(新值);

对于__$update_mask列:

 

恢复模式为简单模式一样可以进行CDC

虽然能捕获到数据变更,但是没有办法找到是谁更新的?

能使用这个做回滚嘛?备份的另外一种路径?对表更新不频繁的情况下?

如果是添加或者删除了某些字段DDL,那么创建的CDC表并没有做更改,那新字段的数据怎么捕获呢?修改字段长度等这些操作同样会一起修改CDC对应的表字段;

sys.sp_cdc_enable_table @role_name参数,是指角色-数据库角色,这个有什么用呢?应用程序角色又有什么用呢?

cdc.Person_Contact_CT这名字中CT代表什么意思呢?Capture Table?(用户.架构__CT

SQL Server 自启动了两个job,一个捕获,一个清除,注意清除是默认凌晨2点,清除72小时以上的数据。如果同一数据库的表中CDC已经启用,不会重建job。

all

返回指定 LSN 范围内的所有更改。 对于由更新操作导致的更改,此选项只返回在应用更新之后包含新值的行。

all update old

返回指定 LSN 范围内的所有更改。 对于由更新操作导致的更改,此选项将返回在更新之前包含列值的行和更新之后包含列值的行。

 

 

 

 

 

reference    http://blog.csdn.net/dba_huangzj/article/details/8130448

http://www.cnblogs.com/gaizai/p/3479731.html

 

 

 

 

 

 

 

 

 

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30130773/viewspace-2124392/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/30130773/viewspace-2124392/

你可能感兴趣的:(使用SQLServer2008的CDC功能实现数据变更捕获)