SQL Server 中的变更数据捕获(CDC)是什么?

SQL Server 变更数据捕获(CDC)是一个内置功能,用于记录数据库表上的 INSERT、UPDATE 和 DELETE 操作。它从事务日志中异步捕获变更,并将其存储在变更表中,使应用程序能够访问增量数据而无需扫描整个表。

对于数据工程师和 DBA 来说,SQL Server 中的 CDC 通过仅跟踪已变更的数据,为数据同步、ETL 工作流和分析提供了一种高效的方式。

SQL Server CDC 捕获三种主要类型的数据变更:

  • 插入: 记录新添加的行。
  • 更新: 捕获行修改前后的数据。
  • 删除: 在行被移除之前存储其值。

例如,当某位员工的薪资从 75,000 美元变更为 80,000 美元时,CDC 会在变更表中记录更新前后的值。这使得下游系统能够识别发生了什么变更以及变更发生的时间。

SQL Server 中的变更数据捕获如何工作?

了解 SQL Server CDC 的工作原理有助于更轻松地配置和管理它。启用 CDC 后,数据变更通过一个四步过程异步捕获,对正常数据库操作的影响极小。

sql server 中变更数据捕获的工作原理

步骤 1. SQL Server 将变更记录到事务日志中

每当数据被插入、更新或删除时,SQL Server 都会将该操作记录到事务日志中。CDC 不是监控用户查询或使用触发器,而是读取这些现有的日志记录来捕获数据变更。

步骤 2. CDC 捕获作业读取事务日志

启用 CDC 后,SQL Server 会创建一个捕获作业,持续扫描事务日志以查找已提交的变更。它在后台运行,异步处理变更,对写入性能的影响极小。

步骤 3. SQL Server 将变更存储到 CDC 变更表中

捕获作业将检测到的变更写入 cdc 架构下的系统管理变更表中,例如 cdc.dbo_TableName_CT。每条记录都包含变更数据以及日志序列号(LSN)和操作类型等元数据。

步骤 4. 应用程序读取增量变更

应用程序、ETL 工具和复制服务可以从 CDC 变更表中检索增量变更。Microsoft 建议使用内置的 CDC 函数(如 fn_cdc_get_all_changesfn_cdc_get_net_changes),而不是直接查询变更表。

如何在 SQL Server 中启用变更数据捕获

启用 SQL Server 变更数据捕获(CDC)涉及三个步骤:验证前提条件、在数据库级别启用 CDC,然后为您要跟踪的表启用 CDC。

启用 CDC 之前的前提条件

在启用 CDC 之前,请确保您的环境满足以下要求:

  • SQL Server 版本: CDC 在 Developer、Enterprise 和 Standard 版本中受支持(SQL Server 2016 SP1 及更高版本)。SQL Server Express 中不可用。
  • SQL Server Agent: 捕获和清理作业依赖于 SQL Server Agent。请确保该服务正在运行。
  • 权限: 您必须对目标数据库具有 db_owner 权限或 sysadmin 服务器级权限。
  • 主键(推荐): 如果您想使用 net changes 函数,则需要主键或唯一索引。

在数据库级别启用 CDC

在您可以跟踪表变更之前,请先为数据库启用 CDC。

sql
USE YourDatabaseName;
    GO
    
    -- 检查是否已启用 CDC
    SELECT name, is_cdc_enabled
    FROM sys.databases
    WHERE name = DB_NAME();
    
    -- 启用 CDC
    EXEC sys.sp_cdc_enable_db;
    GO    

为表启用 CDC

为数据库启用 CDC 后,您可以为各个表启用它。

USE YourDatabaseName;

sql
USE YourDatabaseName;
    GO
    
    -- 如果不存在则创建示例表
    IF OBJECT_ID('dbo.Employees', 'U') IS NULL
    BEGIN
        CREATE TABLE dbo.Employees (
            EmployeeID INT IDENTITY(1,1) PRIMARY KEY,
            FirstName VARCHAR(50),
            LastName VARCHAR(50),
            Salary DECIMAL(18,2),
            LastModified DATETIME DEFAULT GETDATE()
        );
    END;
    GO
    
    -- 在表上启用 CDC
    EXEC sys.sp_cdc_enable_table
        @source_schema = N'dbo',
        @source_name = N'Employees',
        @role_name = NULL,
        @supports_net_changes = 1;
    GO    

验证 CDC 是否正常工作

运行以下查询以验证 CDC 是否已成功启用。

sql
-- 验证表是否被 CDC 跟踪
    SELECT name, is_tracked_by_cdc
    FROM sys.tables
    WHERE name = 'Employees';
    
    -- 验证捕获和清理作业是否存在
    EXEC sys.sp_cdc_help_jobs;    

如果 CDC 启用成功,is_tracked_by_cdc 返回 1,并且捕获和清理作业都会列出。

如何在 SQL Server CDC 中读取变更数据

SQL Server 提供了用于查询捕获的变更的内置函数,而不是直接访问 CDC 变更表。

了解日志序列号(LSN)

SQL Server 中的每个事务都由一个日志序列号(LSN)标识。要在特定时间范围内查询变更,请首先将开始和结束时间戳转换为 LSN 值。

DECLARE @from_lsn BINARY(10), @to_lsn BINARY(10);

    -- 将时间范围映射到 LSN 值
    SET @from_lsn = sys.fn_cdc_map_time_to_lsn(
        'smallest greater than or equal',
        '2026-07-15 08:00:00'
    );
    
    SET @to_lsn = sys.fn_cdc_map_time_to_lsn(
        'largest less than or equal',
        '2026-07-15 17:00:00'
    );    

使用 fn_cdc_get_all_changes

使用 fn_cdc_get_all_changes 返回 LSN 范围内的每个 INSERT、UPDATE 和 DELETE 操作。此函数通常用于审计和详细的变更跟踪。

sql
SELECT *
FROM cdc.fn_cdc_get_all_changes_dbo_Employees(
    @from_lsn,
    @to_lsn,
    'all'
);

使用 fn_cdc_get_net_changes

当您只需要所选 LSN 范围内每个修改行的最终状态时,请使用 fn_cdc_get_net_changes

sql
SELECT *
    FROM cdc.fn_cdc_get_net_changes_dbo_Employees(
        @from_lsn,
        @to_lsn,
        'all'
    );    

了解 CDC 操作代码

__$operation 列标识 CDC 函数返回的变更类型。

操作代码 操作类型 描述
1 删除 行已被删除。
2 插入 已插入新行。
3 更新(之前) 更新前的行值。
4 更新(之后) 更新后的行值。

SQL Server CDC vs 更改跟踪

SQL Server 提供了两个用于跟踪数据变更的内置功能:变更数据捕获(CDC)更改跟踪(CT)。虽然两者都记录数据修改,但它们的目的不同。CDC 捕获详细的变更历史,而更改跟踪仅标识哪些行发生了变更。

功能 变更数据捕获(CDC) 更改跟踪(CT)
主要目的 捕获详细的变更历史,用于审计和 ETL。 跟踪变更的行,用于数据同步。
捕获的数据 存储完整的变更行。 仅存储主键和变更信息。
新旧值 捕获变更前后的值。 不存储历史值。
性能影响 异步运行,对事务影响最小。 在事务期间跟踪变更,开销较低。
存储 存储使用量较高。 存储使用量较低。
最佳适用场景 ETL、分析、审计和数据复制。 应用程序和客户端同步。
审计能力 支持完整的变更历史。 不支持历史审计。

简而言之,当您需要详细的变更历史时选择 CDC,当您只需要高效识别变更的行时选择更改跟踪。

何时应选择 CDC?

当您需要完整的数据变更历史而不仅仅是最新状态时,请选择 SQL Server CDC。它非常适合 ETL 管道、数据仓库、实时分析和流平台,在这些场景中需要捕获每个 INSERT、UPDATE 和 DELETE。

何时更适合选择更改跟踪?

当您只需要知道自上次同步以来哪些行发生了变更时,请选择更改跟踪。由于它存储的信息比 CDC 少,因此使用更少的存储空间,更适合应用程序与 SQL Server 之间的轻量级同步。

与 CDC 不同,更改跟踪不保留历史更新。如果在同步之前一行被多次更新,只有其最新状态可用。

SQL Server CDC 的常见限制

尽管 SQL Server CDC 是一个强大的功能,但在生产环境中使用之前应考虑其几个限制。

依赖 SQL Server Agent

CDC 依赖 SQL Server Agent 来运行捕获和清理作业。如果该服务停止,变更将不再被处理,这可能阻止事务日志被截断并导致其随时间增长。

CDC 存储增长

CDC 将变更数据的副本存储在 cdc 架构下的系统变更表中。在频繁更新或包含大列的数据库中,这些表可能快速增长,因此应规划足够的存储空间。

数据保留期限

默认情况下,捕获的变更在清理作业将其移除之前保留 72 小时(3 天)

如果下游应用程序或 ETL 流程在此期限内未读取变更,数据将被永久删除。您可以增加保留期限,但这也会增加存储使用量。

不支持的操作

某些架构变更不会被 CDC 自动处理,可能需要额外配置。

  • 重命名列
  • 更改列数据类型或大小
  • 内存优化表(In-Memory OLTP)

权限要求

启用和管理 CDC 需要 sysadmindb_owner 权限。启用 CDC 时,可以通过配置门禁角色来限制对捕获数据的访问。

SQL Server 版本和版本注意事项

CDC 在 SQL Server Developer、Enterprise 和 Standard 版本中受支持(SQL Server 2016 SP1 及更高版本)。它在 SQL Server Express 中不可用。

从变更数据捕获到实时数据复制

CDC 是为在单个数据库内跟踪变更而构建的,而不是为实时同步两个数据库而设计的。其捕获作业按计划运行,这意味着变更发生与该变更出现在变更表中之间始终存在一些延迟。对于审计或 ETL 管道来说,这种延迟是可以接受的。但对于灾难恢复、跨数据库同步或需要新鲜数据的报告系统来说,它就成了一个限制。

这就是像 i2Stream 这样的专用数据库复制工具发挥作用的地方。i2Stream 不是定期将变更捕获到同一数据库中的表中,而是直接读取事务日志并将这些变更实时流式传输到目标数据库,无论该目标位于同一平台还是完全不同的平台。

i2Stream 提供了多项功能,正好填补了 CDC 留下的空白:

  • 毫秒级同步与事务级一致性: i2Stream 直接解析数据库日志,以毫秒级延迟复制变更,即使在高并发下也是如此,因此目标数据库保持最新状态,而不是等待计划的捕获作业。
  • 跨平台和跨版本复制: 与仅限 SQL Server 的 CDC 不同,i2Stream 支持 40 多种数据库环境,包括 SQL Server、Oracle、MySQL 和 PostgreSQL,因此您可以复制到不同的数据库引擎或版本,而无需重建变更跟踪逻辑。
  • 集成的 DDL 和 DML 同步: i2Stream 在数据变更的同时捕获架构变更,这避免了管理每个启用 CDC 的表时手动跟踪架构的开销。
  • 无代理部署: i2Stream 无需在生产数据库上安装软件即可运行,因此不会给源系统增加负载——这是 CDC 的捕获和清理作业与生产工作负载竞争时的常见问题。
  • 从特定 SCN 进行时间点恢复: 对于需要超出 CDC 保留窗口的恢复精度的团队,i2Stream 支持恢复到特定时间点,而无需完整的数据库镜像。

如果您的使用场景更接近于持续同步两个数据库——无论是用于灾难恢复、迁移还是自动故障切换——i2Stream 扩展了 CDC 的功能,将定期变更捕获转变为持续的跨平台复制。

Info2Soft 还根据您要保护的内容提供其他数据韧性解决方案。i2Backup 处理跨数据库、VM 和物理服务器的集中式备份,而 i2Availability 提供专为高可用性故障切换场景构建的实时复制。

SQL Server CDC 最佳实践

遵循一些最佳实践有助于提高生产环境中 SQL Server CDC 的性能、可靠性和可维护性。

  • 仅为需要的表启用 CDC: 仅为需要变更跟踪的表启用 CDC。除非必要,避免在临时表或高变动表上启用它。如果您只需要捕获特定列,请使用 @captured_column_list 参数来减小变更表的大小。
  • 监控捕获和清理作业: CDC 依赖捕获和清理作业来处理和移除变更数据。监控这些 SQL Server Agent 作业并配置告警,以便快速检测和解决故障。
  • 配置适当的保留期限: 默认情况下,CDC 将捕获的变更保留 4320 分钟(3 天)。根据下游应用程序消费变更数据的频率调整保留期限。
sql
EXEC sys.sp_cdc_change_job
    @job_type = N'cleanup',
    @retention = 5760;
GO

EXEC sys.sp_cdc_stop_job @job_type = N'cleanup';
EXEC sys.sp_cdc_start_job @job_type = N'cleanup';
GO
  • 避免直接查询变更表: 虽然可以直接查询 CDC 变更表,但 Microsoft 建议使用内置函数,如 fn_cdc_get_all_changesfn_cdc_get_net_changes。这些函数提供了一种在指定的 LSN 范围内检索变更的一致方式。
  • 归档历史变更数据: 如果出于审计或合规原因需要长期保留,请将捕获的变更归档到单独的历史数据库或数据湖中,而不是延长实时的 CDC 保留期限。这有助于控制存储增长并保持数据库性能。
  • 定期监控捕获延迟: 在写入密集型环境中,定期监控捕获作业以确保其能跟上传入的事务。
sql
SELECT
    session_id,
    start_time,
    end_time,
    duration,
    scan_phase,
    log_record_count,
    latency
FROM sys.dm_cdc_log_scan_sessions;

如果捕获延迟持续增加,请考虑调整捕获作业的 @maxtrans@maxscans 设置,以便在每次扫描中处理更多事务。

提示:定期检查您的 CDC 配置,确保保留设置、存储使用情况和捕获性能持续满足您的工作负载要求。

结论

变更数据捕获为 SQL Server 提供了一种内置方式来跟踪行级变更,用于审计、ETL 和增量同步,而无需构建自定义触发器或时间戳逻辑。启用它只需几个步骤,但要充分利用它,需要了解其保留限制、存储影响以及它与更改跟踪的区别。

如果您的需求超出了捕获变更的范围,而是需要在不同平台之间持续同步数据库,那么值得进一步探索像 英方软件 的 i2Stream 这样的实时复制工具。

博客分类底部

准备好构建企业数据韧性了吗?

立即开启 60 天免费试用,或预约产品演示,了解英方软件如何为您的核心业务提供「零中断、零丢失」的数据保护。

请先完成图形验证

验  证  码:

英方官网验证码
第三方二维码 第三方二维码
英方公告铃铛图标
英方公告铃铛图标

公告

英方侧边栏向右箭头
英方高亮提示圆点
英方软件公告
各位求职者、合作伙伴:
近期有第三方冒用英方名义发布虚假招聘、不实业务信息。我司正规招聘全程零收费,非官网渠道信息均不作数。
信息核验热线:400-0078-655
遇诈骗请保留证据,及时联系我们并报警
英方软件
2026 年 6 月 23 日
英方邮件咨询图标
英方邮件咨询图标

邮件

英方销售支持图标
英方销售支持图标

销售

英方侧边栏向右箭头
联系销售:400-0078-655 转 1