CDC-更改数据捕获存储过程 (Transact-SQL)-学习

背景:

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

适用环境:

仅在SQLServer2008(含)以后的企业版、开发版和评估版中可用。

官方介绍:

更改数据捕获存储过程 (Transact-SQL)

变更数据捕获使得在启用表上发生的数据操纵语言 (DML) 活动的历史记录能够以方便的关系格式提供。使用以下存储过程可以配置变更数据捕获、管理变更数据捕获代理作业和为更改数据使用者提供当前元数据。


sys.sp_cdc_add_job (Transact-SQL)


sys.sp_cdc_generate_wrapper_function (Transact-SQL)


sys.sp_cdc_change_job (Transact-SQL)


sys.sp_cdc_get_captured_columns (Transact-SQL)


sys.sp_cdc_cleanup_change_table (Transact-SQL)


sys.sp_cdc_get_ddl_history (Transact-SQL)


sys.sp_cdc_disable_db (Transact-SQL)


sys.sp_cdc_help_change_data_capture (Transact-SQL)


sys.sp_cdc_disable_table (Transact-SQL)


sys.sp_cdc_help_jobs (Transact-SQL)


sys.sp_cdc_drop_job (Transact-SQL)


sp_cdc_scan (Transact-SQL)


sys.sp_cdc_enable_db (Transact-SQL)


sys.sp_cdc_start_job (Transact-SQL)


sys.sp_cdc_enable_table (Transact-SQL)


sys.sp_cdc_stop_job (Transact-SQL)

变更数据捕获函数 (Transact-SQL)

变更数据捕获用于记录应用于 SQL Server 表的插入、更新和删除操作,同时采用易于使用的关系格式提供有关更改的详细信息。此操作将为已修改的行捕获反映了所跟踪源表列结构的列信息,同时还捕获将更改应用到目标环境所需的元数据。以下函数用于返回有关更改的信息。

cdc.fn_cdc_get_all_changes_<捕获实例> (Transact-SQL)


sys.fn_cdc_has_column_changed


cdc.fn_cdc_get_net_changes_<capture_instance> (Transact-SQL)


sys.fn_cdc_increment_lsn (Transact-SQL)


sys.fn_cdc_decrement_lsn


sys.fn_cdc_is_bit_set


sys.fn_cdc_get_column_ordinal


sys.fn_cdc_map_lsn_to_time


sys.fn_cdc_get_max_lsn


sys.fn_cdc_map_time_to_lsn (Transact-SQL)


sys.fn_cdc_get_min_lsn

详解:

CDC功能主要捕获SQLServer指定表的增删改操作,由于任何操作都会写日志(哪怕truncate),所以CDC的捕获来源于日志文件。日志文件会把更改应用到数据文件中,同时也会标记符合要求的数据标记为需要添加跟踪的项。然后通过一些配套函数,最后写入到数据仓库中。大概流程:

具体操作:(下面例子是项目中用到的直接贴出来)

跟一般操作一样首先要打开这个功能,然后才可以开始监控

--打开CDC
USE DB_Name  --数据库名称
GO
EXECUTE sys.sp_cdc_enable_db;
GO

检查是否打开

--检查是否成功
SELECT  is_cdc_enabled, CASE WHEN is_cdc_enabled=0 THEN ‘CDC功能禁用‘ELSE ‘CDC功能启用‘END 描述
FROM    sys.databases
WHERE   NAME = ‘DB_Name‘

也可以在用户和架构中查看系统表中也会有增加

打开数据库的CDC功能之后就是打开数据库的具体业务表的监控了

sys.sp_cdc_enable_table
    [ @source_schema = ] ‘source_schema‘,
    [ @source_name = ] ‘source_name‘ ,
    [ @role_name = ] ‘role_name‘
    [,[ @capture_instance = ] ‘capture_instance‘ ]
    [,[ @supports_net_changes = ] supports_net_changes ]
    [,[ @index_name = ] ‘index_name‘ ]
    [,[ @captured_column_list = ] ‘captured_column_list‘ ]
    [,[ @filegroup_name = ] ‘filegroup_name‘ ]
  [,[ @partition_switch = ] ‘partition_switch‘ ]

sp_cdc_enable_table 语法

[ @source_schema = ] ‘source_schema‘
是源表所属的架构的名称。source_schema 的数据类型为 sysname,无默认值,并且不能为 NULL。
[ @source_name = ] ‘source_name‘
是对其启用变更数据捕获的源表的名称。source_name 的数据类型为 sysname,无默认值,并且不能为 NULL。
source_name 必须存在于当前数据库中。不能对 cdc 架构中的表启用变更数据捕获。
[ @role_name = ] ‘role_name‘
是用于控制更改数据访问的数据库角色的名称。role_name 为 sysname,并且必须指定。如果显式设置为 NULL,则没有控制角色用于限制对更改数据的访问。
如果当前存在该角色,则使用它。如果不存在该角色,则会尝试创建具有指定名称的数据库角色。在尝试创建该角色之前,将删除角色名称字符串右侧的空格。如果调用方无权在数据库中创建角色,则存储过程操作将失败。
[ @capture_instance = ] ‘capture_instance‘
是用于命名特定于实例的变更数据捕获对象的捕获实例的名称。capture_instance 为 sysname,并且不能为 NULL。
如果未指定,则该名称将从源架构名称加上源表名称中派生而来,格式为 schemaname_sourcename。capture_instance 不能超过 100 个字符,并且在数据库中必须是唯一的。不管是指定的还是派生的,都将删除 capture_instance 字符串右侧的任何空格。
源表最多可以有两个捕获实例。有关详细信息,请参阅sys.sp_cdc_help_change_data_capture (Transact-SQL)。
[ @supports_net_changes = ] supports_net_changes
指示是否对此捕获实例启用净更改查询支持。supports_net_changes 为 bit,如果此表有主键,或者有已使用 @index_name 参数进行标识的唯一索引,则此参数的默认值为 1。否则,此参数默认为 0。
如果为 0,则只生成查询所有更改的支持函数。
如果为 1,则还会生成查询净更改所需的函数。
如果将 supports_net_changes 设置为 1,则必须指定 index_name,或者源表必须具有已定义的主键。
[ @index_name = ] ‘index_name‘
用于唯一标识源表中的行的唯一索引的名称。index_name 为 sysname,并且可以为 NULL。如果指定,则 index_name 必须是源表的唯一有效索引。如果指定 index_name,则标识的索引列优先于任何定义的主键列,就像表的唯一行标识符一样。
[ @captured_column_list = ] ‘captured_column_list‘
标识将包括在更改表中的源表列。captured_column_list 的数据类型为 nvarchar(max),并且可以为 NULL。如果为 NULL,则所有列都将包括在更改表中。
列名称必须是源表中的有效列。必须包括在主键索引中定义的列,或在 index_name 所引用的索引中定义的列。
captured_column_list 是以逗号分隔的列名称列表。可以选择将列表中的单个列名称放在双引号 ("") 或方括号 ([]) 中。如果列名称包含嵌入的逗号,则必须将该列名称引起来。
captured_column_list 不能包含以下保留的列名称:__$start_lsn、__$end_lsn、__$seqval、__$operation 和 __$update_mask。
[ @filegroup_name = ] ‘filegroup_name‘
是要用于为捕获实例创建的更改表的文件组。filegroup_name 为 sysname,并且可以 NULL。如果指定,则必须为当前数据库定义 filegroup_name。如果为 NULL,则使用默认文件组。
我们建议为变更数据捕获的更改表创建一个单独的文件组。有关详细信息,请参阅配置变更数据捕获。
[ @allow_partition_switch= ] ‘allow_partition_switch‘
指示是否可以对启用了变更数据捕获的表执行 ALTER TABLE 的 SWITCH PARTITION 命令。allow_partition_switch 为 bit,默认值为 1。
对于非分区表,此开关设置始终为 1,并忽略实际的设置。如果对于非分区表将此开关显式设置为 0,则发出警告 22857 以指示已忽略此开关设置。如果对于分区表将此开关显式设置为 0,则发出警告 22356 以指示将禁止源表上的分区切换操作。最后,如果此开关设置显式设置为 1 或允许默认为 1 并且被启用的表已分区,则发出警告 22855 以指示不会阻塞分区切换。如果发生任何分区切换,则变更数据捕获不会跟踪由此切换产生的更改。这将导致使用更改数据时数据不一致。

参数

EXECUTE sys.sp_cdc_enable_table
    @source_schema = N‘dbo‘
  , @source_name = N‘User_Info‘
  , @role_name = NULL
  , @capture_instance=N‘CDC_User_Info‘
  , @captured_column_list =‘UserInfoID,UserName,NickName,RealName,Photo,Phone,IDCard,AddTime,Status,RoleType,Province,City,District‘
  , @index_name=‘PK_USER_INFO‘
  ;
GO
语法
  --查看配置
  --sys.sp_cdc_help_change_data_capture
  --[ [ @source_schema = ] ‘source_schema‘ ]--表的架构名
  --[, [ @source_name = ] ‘source_name‘ ]      --表名称  

EXEC sys.sp_cdc_help_change_data_capture ‘dbo‘,‘User_Info‘

 --执行结果

--查看是否启用
SELECT is_tracked_by_cdc
FROM SYS.TABLES
WHERE NAME=‘User_Info‘
AND SCHEMA_ID=SCHEMA_ID(‘DBO‘)

下面开始测试一下这个监控是否起效:

注意:必须在 SQL Server 配置管理器中打开SQL 代理,

直接在SQL里面做测试:

                                SELECT * FROM cdc.CDC_User_Info_CT                                 --插入测试
                                INSERT INTO [dbo].[User_Info]
                               ([UserName],[Password],[NickName],[Email],[RealName],[IDCard],[Photo],[Sex],[Phone],[Profile],[Description]
                               ,[AddTime],[Province],[City],[District],[Birthday],[RoleType],[Status],[VIPCardNumber],[VerifiedStatus]
                               ,[PayPassword],[QQ],[LastLoginTime],[IsShowRealName])
                                VALUES
                               (‘test‘,‘test‘,‘test‘,‘test‘,‘test‘,‘test‘,‘test‘,1,‘test‘,‘test‘,‘test‘,‘2015-02-03 00:00:00.000‘,‘test‘,‘test‘,‘test‘,‘1983-03-18 00:00:00.000‘,1,1,1,1,‘test‘,‘test‘,‘2015-02-03 00:00:00.000‘,1)

                                SELECT * FROM cdc.CDC_User_Info_CT
                                GO

                                --修改测试
                                UPDATE [dbo].[User_Info]
                                   SET[Sex] = 0
                                      ,[Phone] = ‘4‘
                                      ,[QQ] = ‘4111114‘
                                 WHERE UserInfoID=1

                                SELECT * FROM dbo.User_Info
                                SELECT * FROM cdc.CDC_User_Info_CT
                                GO
                                --删除测试
                                DELETE FROM  [dbo].[User_Info] WHERE UserInfoID=99999                      SELECT * FROM dbo.User_Info 
                                SELECT * FROM cdc.CDC_User_Info_CT
                                GO

从测试看来已经达到了我们想要的监控效果了!存储过程部分也就这么几个,其他的可以参考最前面那个表格!

接下来看看如何使用CDC函数吧:

使用CDC的函数来获取更改

1、 cdc.fn_cdc_get_all_changes_<捕获实例> (Transact-SQL)

针对在指定日志序列号 (LSN) 范围内应用到源表的每项更改均返回一行。如果源行在该间隔内有多项更改,则每项更改都会表示在返回的结果集中。除了返回更改数据外,四个元数据列还提供了将更改应用到另一个数据源所需的信息。行筛选选项可控制元数据列的内容以及结果集中返回的行。当指定“all”行筛选选项时,针对每项更改将只有一行来标识该更改。当指定“all update old”选项时,更新操作会表示为两行:一行包含更新之前已捕获列的值,另一行包含更新之后已捕获列的值。

此枚举函数是在对源表启用变更数据捕获时创建的。此函数名称是派生的,采用 cdc.fn_cdc_get_all_changes_capture_instance 格式,其中 capture_instance 是在对源表启用变更数据捕获时为捕获实例指定的值。

语法:

cdc.fn_cdc_get_all_changes_capture_instance ( from_lsn , to_lsn , ‘<row_filter_option>‘ )

<row_filter_option> ::=
{ all
 | all update old
}

参数:
from_lsn
LSN 值,它表示要包含在结果集中的 LSN 范围的低端点。from_lsn 的数据类型为 binary(10)。
结果集中仅包含 cdc.[capture_instance]_CT 更改表中 __$start_lsn 中的值大于或等于 from_lsn 的行。
to_lsn
LSN 值,它表示要包含在结果集中的 LSN 范围的高端点。to_lsn 的数据类型为 binary(10)。
结果集中仅包含 cdc.[capture_instance]_CT 更改表中 __$start_lsn 中的值小于或等于 from_lsn 或等于 to_lsn 的行。
<row_filter_option> ::= { all | all update old }
控制元数据列的内容和结果集中所返回的行的选项。
可以是下列选项之一:
all
返回指定 LSN 范围内的所有更改。对于由更新操作导致的更改,此选项只返回在应用更新之后包含新值的行。
all update old
返回指定 LSN 范围内的所有更改。对于由更新操作导致的更改,此选项将返回在更新之前包含列值的行和更新之后包含列值的行。

语法和参数

--1、cdc.fn_cdc_get_all_changes_<捕获实例> (Transact-SQL)
-- 查询某个捕获实例的最小到最大变化lsn
--  all update old 查询结果要修改前的源数据 _$operation=3 | all 只查询变化的,不带修改前的源数据玩 即查询结果中没有 _$operation=3的数据
DECLARE @from_lsn binary(10), @to_lsn binary(10)
SET @from_lsn = sys.fn_cdc_get_min_lsn(‘CDC_User_Info‘)
SET @to_lsn = sys.fn_cdc_get_max_lsn()
SELECT @from_lsn AS ‘Start‘,@from_lsn AS ‘End‘
SELECT * FROM cdc.fn_cdc_get_all_changes_CDC_User_Info
  (@from_lsn, @to_lsn, N‘all‘)--|(@from_lsn, @to_lsn, N‘all update old‘)
GO

2、通过 sys.fn_cdc_map_time_to_lsn (Transact-SQL) 函数 获取某个时间段内的数据变化

为指定的时间返回 cdc.lsn_time_mapping 系统表中 start_lsn 列中的日志序列号 (LSN) 值。可以使用此函数系统地将日期时间范围映射到基于 LSN 的范围,以供变更数据捕获枚举函数 cdc.fn_cdc_get_all_changes_<capture_instance> 和cdc.fn_cdc_get_net_changes_<capture_instance> 返回此范围内的数据更改。

语法:
sys.fn_cdc_map_time_to_lsn (‘<relational_operator>‘, tracking_time )

<relational_operator> ::=
{  largest less than
 | largest less than or equal
 | smallest greater than
 | smallest greater than or equal
}

参数:
‘<relational_operator>‘ { largest less than | largest less than or equal | smallest greater than | smallest greater than or equal }
用于标识这样的非重复 LSN 值:该值在 cdc.lsn_time_mapping 表中,且其关联的 tran_end_time 在与 tracking_time 值比较时满足关系。
relational_operator 的数据类型为 nvarchar(30)。
tracking_time
是要进行匹配的日期时间值。tracking_time 的数据类型为 datetime。

注释:
若要了解如何使用 sys.fn_cdc_map_time_lsn 将日期时间范围映射到 LSN 范围,请考虑以下情况。假定使用者希望每日提取更改数据。也就是说,使用者只需要给定日午夜之前(包括午夜)的更改。此时间范围的下限应为无限接近前一天午夜的时间点(但不包括前一天午夜)。上限应为给定日的午夜(包括午夜)。下例说明了如何使用 sys.fn_cdc_map_time_to_lsn 函数系统地将此基于时间的范围映射到基于 LSN 的范围,以供变更数据捕获枚举函数返回此范围内的所有更改之用。
DECLARE @begin_time datetime, @end_time datetime, @begin_lsn binary(10), @end_lsn binary(10);
SET @begin_time = ‘2007-01-01 12:00:00.000‘;
SET @end_time = ‘2007-01-02 12:00:00.000‘;
SELECT @begin_lsn = sys.fn_cdc_map_time_to_lsn(‘smallest greater than‘, @begin_time);
SELECT @end_lsn = sys.fn_cdc_map_time_to_lsn(‘largest less than or equal‘, @end_time);
SELECT * FROM cdc.fn_cdc_get_net_changes_HR_Department(@begin_lsn, @end_lsn, ‘all ‘);
关系运算符 ‘smallest greater than‘ 用于将更改限制为在前一天的午夜后发生的更改。如果具有不同 LSN 值的多个项共用在 cdc.lsn_time_mapping 表中标识为下限的 tran_end_time 值,则该函数将返回最小的 LSN,以确保所有项均包含在内。对于上限,关系运算符 ‘largest less than or equal to’ 用于确保该范围包含此日的所有项(包括其 tran_end_time 值为午夜的那些项)。如果具有不同 LSN 值的多个项共用标识为上限的 tran_end_time 值,则此函数将返回最大的 LSN,以确保所有项均包括在内。

语法及参数

--2、通过 sys.fn_cdc_map_time_to_lsn (Transact-SQL) 函数 获取某个时间段内的数据变化
--比如:查询 2015-02-10 15:20-15:30 这十分钟之内我所做的修改
SELECT * FROM cdc.CDC_User_Info_CT --查询这个是为了方便直观的看到两个查询结果的对比
DECLARE @begin_time datetime, @end_time datetime, @begin_lsn binary(10), @end_lsn binary(10);
SET @begin_time = ‘2015-02-10 15:20:00.000‘;
SET @end_time = ‘2015-02-10 15:30:00.000‘;
SELECT @begin_lsn = sys.fn_cdc_map_time_to_lsn(‘smallest greater than‘, @begin_time);
SELECT @end_lsn = sys.fn_cdc_map_time_to_lsn(‘largest less than or equal‘, @end_time);
SELECT * FROM cdc.fn_cdc_get_all_changes_CDC_User_Info(@begin_lsn, @end_lsn, ‘all update old‘);


很明显可以看到只有两条数据是在这十分钟内捕获到的;

3、sys.fn_cdc_map_lsn_to_time 查询变更时间:

为指定的日志序列号 (LSN) 返回 cdc.lsn_time_mapping 系统表的 tran_end_time 列中的日期和时间值。您可以使用此函数系统地将 LSN 范围映射到更改表中的日期范围。

--3、查询变更时间
SELECT  [__$operation] ,
       CASE [__$operation] WHEN 1 THEN ‘删除‘ WHEN 2 THEN ‘插入‘ WHEN 3 THEN ‘更新(捕获的列值是执行更新操作前的值)‘
       WHEN 4 THEN ‘更新(捕获的列值是执行更新操作后的值)‘ END [类型],
        sys.fn_cdc_map_lsn_to_time([__$start_lsn]) [更改时间] ,
        UserName ,
        UserInfoID
FROM    cdc.CDC_User_Info_CT

				
时间: 2024-10-05 15:06:22

CDC-更改数据捕获存储过程 (Transact-SQL)-学习的相关文章

CDC变更数据捕获

CDC变更数据捕获 (2013-03-20 15:25:52)   分类: SQL SQL Server中记录数据变更的四个方法:触发器.Output子句.变更数据捕获(Change Data Capture )功能.同步更改跟踪. 这里记录下cdc: 变更数据捕获可记录应用于 SQL Server 表的插入.更新和删除活动. 对数据库中的某张表启用变更数据捕获,例子: CREATE DATABASE test1 USE test1 CREATE TABLE [dbo].[WSTtestTBL]

CDC 变更数据捕获技术的问题及局限

现在的cdc功能仍然还是会让你失望的. 优点就不说了,就是联机丛书里面写的那些.缺点如下:1.目前为止cdc无法与日志文件关联,更多有用的信息,仍需要进行前后数据比对获取.(一般仍会使用触发器进行替代记录)2.目前为止cdc可以记录DDl的相关处理,但是更多的信息,如记录IP等用户信息仍然需要另外的代码支持. select * into PT_CUSTOMER_INFO_BAK from PT_CUSTOMER_INFO 类似oracle的create table as select * fro

SQL Server 变更数据捕获(CDC)

原文:SQL Server 变更数据捕获(CDC) 标签:SQL SERVER/MSSQL SERVER/数据库/DBA/字段/对象更改 概述 变更数据捕获用于捕获应用到 SQL Server 表中的插入.更新和删除活动,并以易于使用的关系格式提供这些变更的详细信息.变更数据捕获所使用的更改表中包含镜像所跟踪源表列结构的列,同时还包含了解所发生的变更所需的元数据. 对表开启了变更捕获之后,对该表的所有DML和DDL操作都会被记录,有助于跟踪表的变化. 测试环境: SQL SERVER 2008

SQL Server 2008新增的变更数据捕获和更改跟踪

本文主要介绍SQL Server中记录数据变更的四个方法:触发器.Output子句.SQL Server 2008中新增的变更数据捕获(Change Data Capture 即CDC)功能.同步更改跟踪.其中后两个为SQL Server 2008所新增. 一.触发器 在SQL Server的早期版本中,如果要记录某个表或视图的Insert/Update/Delete操作,我们可以借助触发器(Trigger)(http://msdn.microsoft.com/zh-cn/library/ms1

SqlServer 变更数据捕获(CDC)

变更数据捕获(Change Data Capture ,简称 CDC)记录 SQL Server 表的插入.更新和删除活动.使用变更数据捕获可以更有效跟踪表对象DML历史操作,对 ETL 等数据转移也非常有用. 变更数据捕获适用版本: SQL Server 2008 以上的 Enterprise Edition.Developer Edition 和 Evaluation Edition 变更数据捕获原理: 变更数据捕获的更改数据源为 SQL Server 事务日志.当对表启用变更数据捕获时,系

SQL Server 2008 CDC增量变更捕获详解

1 背景: 随着公司业务的成长,数据量也随之的不断增长.随之而来的问题是在做ETL的时候,时间花费也越来越长.为了节省时间开销,我们只想要更新最新的数据,不想要把公司历年所有的数据都进行处理.这种情况就被称为变更数据捕获(Change Data Capture,又名CDC).在SQLServer2008之前,对数据变更的捕获通常使用触发器把DML操作中的INSERT/UPDATE/DELETE数据记录下来,但是触发器的维护比较困难:时间戳严重依赖于数据库的设计,而且必须在业务代码中对时间字段进行

在SSIS 2012中使用CDC(数据变更捕获)

最新项目稍有空隙,开始研究SQL Server 2012和2014的一些BI特性,参照(Matt)的一个示例,我们开始体验SSIS中的CDC(Change Data Capture,变更数据捕获). 注:如果需要了解关于SQL Server 2008中的CDC,请看这里http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html),本文假定读者对CDC的工作方式已有所了解.^_^. 我们分三步完成实例: 1.准备基础数据: 2.设

Oracle 学习笔记 18 -- 存储函数和存储过程(PL/SQL子程序)

PL/SQL子程序 包括函数和过程.这里的函数指的是用户自己定义的函数,和系统函数是不同的.子程序一般是完成特定功能的PL/SQL程序块,并且具有一定的通用性,可以被不同的应用程序多次调用.Oracle提供可以把PL/SQL程序存储在数据库中,并可以再任何地方来运行它.这样就叫做存储过程或者是函数.过程和函数的唯一区别就是函数总是向调用者返回数据,而过程则不返回数据. 函数 如果用户要经常执行某些操作,并且需要返回特定的数据,那么就可以将这些操作构造成一个函数. 可以使用SQL语句定义函数. 基

SQL学习(时间,存储过程,触发器)

SQL学习 几个操作时间的函数 1 --datapart 获取时间中的年月日时分秒等部分 2 select DATEPART(year,current_timestamp); 3 select DATEPART(DAY,current_timestamp); 4 select DATEPART(MONTH,current_timestamp); 5 6 --dateadd 在相应时间上加上年月日时分秒等 7 select CURRENT_TIMESTAMP,DATEADD(DAY,10,CURR