SqlServer变更数据捕获(CDC)

2023-02-22 00:00:00 数据 捕获 作业 更改 变更

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_history @capture_instance= 'dbo_CDC_Test'

?

1

2

3

--测试 DDL 操作后再查看

ALTER TABLE CDC_Test ADD info VARCHAR (20)

ALTER TABLE CDC_Test DROP COLUMN info


 

【cdc._CT】



select *from cdc.dbo_CDC_Test_CT

捕获实例表:这是重要的表,该表就是记录源表的所有DML操作记录。每个表对应一个实例表,命名方式为“架构名_表名_CT”

应用于源表的每个插入或删除操作在更改表中各占一行。插入操作生成的行的数据列包含插入后的列值。删除操作生成的行的数据列包含删除前的列值。更新操作需要两行数据:一行用于标识更新前的列值,另一行用于标识更新后的列值。


现在对源表进行插入、更新、删除后,查看该跟踪实例表:


?

1

2

3

4

5

6

7

8

9

10

--  进行相关操作

insert into CDC_Test(id, name ,insertDate,value)

select 1, 'kk' ,GETDATE(),55

go

update CDC_Test set name 'hh' ,value = 50 where  name 'kk'

go

delete from CDC_Test where id = 1

go


select from cdc.dbo_CDC_Test_CT


__$start_lsn :与相应更改的提交事务关联的日志序列号 (LSN)



__$end_lsn : (在 SQL Server 2008中,此列始终为 NULL

__$seqval :对事务内的行更改顺序

__$operation :源表DML操作

1 = 删除

2 = 插入

3 = 更新(旧值)

4 = 更新(新值)

__$update_mask :基于更改表的列序号的位掩码,用于标识那些发生更改的列


再测试 DDL 对更改表的影响:


?

1

2

3

4

5

6

7

8

9

10

11

12

13

--  进行相关操作

INSERT INTO CDC_Test(id, name ,insertDate,value) SELECT 2, 'mm' ,GETDATE(),0


ALTER TABLE CDC_Test ADD info VARCHAR (20) --添加1新列


INSERT INTO CDC_Test(id, name ,insertDate,value) SELECT 2, 'mm' ,GETDATE(),0


ALTER TABLE CDC_Test DROP COLUMN value --删除1列


INSERT INTO CDC_Test(id, name ,insertDate) SELECT 3, 'hh' ,GETDATE()



SELECT FROM cdc.dbo_CDC_Test_CT   --查看更改表


结果总结:


1. 新添加的列(如 info),在更改表中不会添加。但仍可进行跟踪记录操作,只是不在表cdc.captured_columns 中的列则不跟踪记录。

2. 删除了列(如 value),更改表中则标识为null 。即时再添加创建原来的字段,也。

增加或者删除一列后,没有记录跟踪,这种情况增么办?

一种方法是:

1. 增删某字段

2. 再对同一个表启用另一个变更数据捕获(新的变更表为源表当前的结构)

3.再根据 ID/时间/键 等从新的跟踪表取数据(非实时获取数据情况,如定期转移数据等)

4. 如觉得每次调用都更改表名,可以使用视图,调用视图查询更改表,视图只要更改对应的表就行。


捕获实例表中的一些约束:


?

1

2

3

4

5

6

7

8

9

Timestamp / rowversion  列的数据类型被定义为 binary (8)


  Identity  列的数据类型被定义为 int 或 bigint


  对于 LOB 数据类型 varchar ( max )、nvarchar( max )、varbinary( max )、image、text、ntext 和 xml,如果LOB列被更新,则在捕获表才记录更新前的值,否则(即时更新其他列)更新前的值为 null 。这样节省了空间。

  

Truncate table 将无法对启用跟踪的表使用

  

SWITCH PARTITION  部分行将不会被捕获


 


【cdc.lsn_time_mapping】



select * from cdc.lsn_time_mapping

当捕获进程提交每批新的更改数据时,将在该表中为每个具有更改表项的事务添加新的项(参考:cdc.lsn_time_mapping)



建议执行 sys.fn_cdc_map_lsn_to_time和 sys.fn_cdc_map_time_to_lsn系统函数


结合 cdc.fn_cdc_get_all_changes_ 和 cdc.fn_cdc_get_net_changes_ ,可获取一段范围内的数据变化情况。


?

1

2

3

4

5

6

7

8

9

DECLARE @begin_time datetime, @end_time datetime, @begin_lsn binary (10), @end_lsn binary (10);

SET @begin_time = '2015-05-16 00:00:00.000' ;

SET @end_time = '2015-05-17 00:00:00.000' ;

SELECT @begin_lsn = sys.fn_cdc_map_time_to_lsn( 'smallest greater than or equal' , @begin_time);

SELECT @end_lsn = sys.fn_cdc_map_time_to_lsn( 'largest less than' , @end_time);

--SELECT @begin_lsn,@end_lsn

SELECT FROM cdc.fn_cdc_get_all_changes_dbo_CDC_Test( @begin_lsn , @end_lsn , 'all update old' )

SELECT FROM cdc.fn_cdc_get_all_changes_dbo_CDC_Test( @begin_lsn , @end_lsn , 'all' )

SELECT FROM cdc.fn_cdc_get_net_changes_dbo_CDC_Test( @begin_lsn , @end_lsn , 'all' )



些统计信息:参考 管理和监视变更数据捕获 (SQL Server)


?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

--如果有连续的空结果集(例如,当捕获作业正在连续运行时),则后一个现有行中的 empty_scan_count 将递增


--  为变更数据捕获日志扫描会话中遇到的每个错误返回一行

select from sys.dm_cdc_errors


--  针对当前数据库中的每个日志扫描会话返回一行。返回的后一行表示当前会话。

select from sys.dm_cdc_log_scan_sessions


--  空扫描的会话

SELECT from sys.dm_cdc_log_scan_sessions where empty_scan_count <> 0


--  返回近进行的会话的平均滞后时间

SELECT latency FROM sys.dm_cdc_log_scan_sessions WHERE session_id = 0


--  返回近会话的平均吞吐量

SELECT command_count/duration AS [Throughput] FROM sys.dm_cdc_log_scan_sessions WHERE session_id = 0


 



?

1

2

3

4

5

--  查看捕获作业或清除作业的信息

--  SELECT * FROM msdb.dbo.sysjobs

SELECT FROM msdb.dbo.cdc_jobs


EXEC sys.sp_cdc_help_jobs


 


对作业的更改 (参考 sys.sp_cdc_change_job)


?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

--对作业的更改

EXEC sys.sp_cdc_change_job

  @job_type = 'capture'

  ,@maxtrans = 1000      --每个扫描循环可以处理的多事务数

  ,@maxscans = 10        --为了从日志中提取所有行而要执行的大扫描循环次数

  ,@continuous = 1       --连续运行多处理(max_trans * max_scans) 个事务

  ,@pollinginterval = 5



EXEC sys.sp_cdc_change_job

  @job_type = 'cleanup'

  ,@retention = 4320     --更改行将在更改表中保留的分钟数

  ,@threshold = 5000     --清除时可以使用一条语句删除的删除项的大数量




  --更改后需重启作业

EXEC sys.sp_cdc_stop_job @job_type = N 'capture' ;

EXEC sys.sp_cdc_stop_job @job_type = N 'capture' ;


EXEC sys.sp_cdc_start_job @job_type = N 'cleanup' ;

EXEC sys.sp_cdc_start_job @job_type = N 'cleanup' ;


后一项,禁用(删除)变更数据捕获:



?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

--  对表禁用变更数据捕获

USE MyDatabase;

GO


EXEC sys.sp_cdc_disable_table

@source_schema = N 'dbo' ,

@source_name   = N 'CDC_Test' ,

@capture_instance = N 'dbo_CDC_Test'

GO



--  对数据库禁用变更数据捕获

USE MyDatabase;

GO

EXECUTE sys.sp_cdc_disable_db;

GO


--执行完成后,相关的表、函数、用户、角色、架构、作业都会完全删除!

本文来源https://www.modb.pro/db/439035

相关文章