如何使用 SQL Server CDC 重新加载增量数据?

How do you reload incremental data using SQL Server CDC?

我无法找到 documentation/an 关于如何在带有 SSIS 的 SQL Server 2014 中使用更改数据捕获 (CDC) 重新加载增量数据的解释。

基本上,在给定的一天,如果您的 SSIS 增量处理失败并且您需要重新开始。如何重新暂存最近更改的记录?

我想这取决于你对数据做了什么,嗯? :) 不过,在一般情况下,您可以将其分为三种情况:

  1. 插入 - 检查该行是否存在。如果是,请跳过它。如果没有,插入它。
  2. 删除 - 假设您不重复使用主键,只需再次 运行 删除。它要么找到要删除的行,要么找不到,但最终结果是删除后具有该 PK 的行将不存在。
  3. 更新 - 有点像删除场景。如果您重新处理更新,这并不是什么大问题(假设您的 CDC 进程是唯一使目的地保持最新状态并且不存在覆盖 someone/something 其他更改的危险)。

假设您正在使用新的 CDC SSIS 2012 组件,特别是包开头和结尾的 CDC 控制任务。然后,如果包在包末尾运行 CDC 控制任务之前由于任何原因失败,那些 LSN(日志序列号)将不会被标记为已处理,因此您可以在解决问题后从顶部重新启动 SSIS 包,并且它只会再次重新处理这些记录。您必须使用 CDC 控制任务来完成这项工作,或者自己跟踪 LSN(在 SSIS 2012 之前,这是唯一的方法)。

Matt Masson(MSFT SQL 服务器团队的高级项目经理)在这方面有很好的 post 分步演练:CDC in SSIS for SQL Server 2012

另请参阅 Bradley Schacht 的 post:Understanding the CDC state Value

所以我确实弄清楚了如何在 SSIS 中执行此操作。

每当我的 SSIS 包在我的数据仓库中的 table 中运行时,我都会记录最小和最大 LSN 编号。

如果我想从 CDC 源重新加载一组数据到暂存,在 SSIS 包中我需要使用 CDC 控制任务并将其设置为 "Mark CDC Start" 并在标记为 [= 的文本框中23=] 我将要使用的 LSN 值作为起点。

我还没有想出如何设置终点,但我可以进入暂存阶段 table 并删除任何 LSN 值 > 然后是我的终点的数据。

您只能对尚未 'cleaned up' 的 CDC 更改执行此操作 - 因此只能对最近 3 天内更改的数据执行此操作。

顺便说一句,我还把 lsn_time_mapping table 带到了我的数据仓库,因为我发现这些信息在历史上很有用,并且它在源代码中每 4 天获取一次 'cleaned up'数据库。

要重新加载相同的更改,您可以使用以下方法。

方法#1:将 [cdc_states] table 中的 TFEND 标记存储在另一个 table 或变量中。将标记从 "saved" 值重新加载回您的 [cdc_states] 以再次处理相同的范围。但是,此方法允许您从相同的 LSN 开始处理,但如果同时您更改 table 获得更多更改,这些更改也会被捕获。因此,您可能会获得在执行第一次数据捕获后发生的更多更改。

方法二:为了捕获指定范围,记录范围处理前后的TFEND标记。现在,您可以将 OLEDB 源连接 (SSIS) 与以下 cdc 函数结合使用。然后像往常一样使用 CDC Splitter 来直接插入、更新和删除。

DECLARE @start_lsn binary(10);
DECLARE @end_lsn binary(10);
SET @start_lsn = 0x004EE38E921A01000001;-- TFEND (1) -- if null then sys.fn_cdc_get_min_lsn('YourCapture') to start from the beginnig of _CT table
SET @end_lsn = 0x004EE38EE3BB01000001;  -- TFEND (2)
    SELECT * FROM [cdc].[fn_cdc_get_net_changes_YOURTABLECAPTURE](
     @start_lsn
    ,@end_lsn
    ,N'all' -- { all | all with mask | all with merge }
    --,N'all with mask' -- shows values in "__$update_mask" column
    --,N'all with merge' -- merges inserts and updates together. It's meant for processing the results using T-SQL MERGE statement
    )
ORDER BY __$start_lsn;