跟踪数据更改 (SQL Server)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Microsoft Fabric 中的 SQL 数据库

SQL Server 提供以下两个用于在数据库中跟踪数据更改的功能:变更数据捕获更改跟踪。 这两个功能使应用程序能够确定对数据库中的用户表所做的 DML 更改(插入、更新和删除操作)。 可对同一个数据库启用变更数据捕获和更改跟踪;没有特殊的注意事项。 有关支持变更数据捕获和更改跟踪的 SQL Server 版本,请参阅 SQL Server 2022 的版本和支持的功能

使用变更数据捕获或更改跟踪的好处

对于某些注重效能的应用程序来说,查询数据库中已更改的数据的能力是一项很重要的要求。 通常,为了确定数据更改,应用程序开发人员必须在其应用程序中使用触发器、时间戳列和其他表的组合来实现自定义跟踪方法。 创建这些应用程序通常涉及多项工作,导致架构更新,并且通常带来较高的性能开销。

在应用程序中使用变更数据捕获或更改跟踪而不开发自定义解决方案来跟踪数据库中的更改具有以下好处:

  • 减少了开发时间。 由于 SQL Server 中提供了功能,因此无需开发自定义解决方案。

  • 不需要架构更改。 你无需添加列、添加触发器或创建要在其中跟踪已删除的行或存储更改跟踪信息的端表(如果无法将列添加到用户表)。

  • 具有内置清除机制。 更改跟踪的清除操作在后台自动执行。 存储在辅助表中的数据不需要进行自定义清理。

  • 提供功能的目的是获取更改信息。

  • DML 操作的开销较低。 同步变更跟踪始终会带来一定的开销。 但是,使用更改跟踪有助于使开销最小化。 开销通常会低于使用其他解决方案,对于需要使用触发器的解决方案,尤其如此。

  • 更改跟踪是基于提交的事务进行的。 更改的顺序基于事务提交时间。 这使得在存在长时间运行且相互重叠的事务时,能够获得可靠的结果。 必须设计使用时间戳值的自定义解决方案,以处理这些情况。

  • 提供可用于配置和管理的标准工具。 SQL Server 提供标准 DDL 语句、SQL Server Management Studio、目录视图及安全权限。

变更数据捕获与更改跟踪之间的功能差异

下表列出了变更数据捕获与更改跟踪之间的功能差异。 变更数据捕获中的跟踪机制涉及从事务日志中异步捕获更改,因此,可以在执行 DML 操作后获得更改信息。 更改跟踪中的跟踪机制涉及在执行 DML 操作的同时同步跟踪更改,因此,可以立即获得更改信息。

功能 变更数据捕获 更改跟踪
跟踪的更改
DML 更改
跟踪的信息
历史数据
列是否已更改
DML 类型

变更数据捕获

变更数据捕获通过捕获已发生 DML 更改这一事实以及实际被更改的数据,为用户表提供历史更改信息。 更改是使用异步进程捕获的,此进程读取事务日志,并且对系统造成的影响很小。

正如下图所示,对用户表所做的更改是在相应更改表中捕获的。 这些变更表展示了这些变更随时间推移的历史视图。 SQL Server 提供的 变更数据捕获函数函数 使更改数据能够轻松、系统地使用。

展示变更数据捕获概念的图示。

安全模型

本部分说明了变更数据捕获安全模式。

配置和管理

若要启用或禁用数据库的更改数据捕获, sys.sp_cdc_enable_dbsys.sp_cdc_disable_db 的调用方必须是固定服务器 sysadmin 角色的成员。 在表级别启用和禁用更改数据捕获需要 sys.sp_cdc_enable_tablesys.sp_cdc_disable_table 的调用方是 sysadmin 角色的成员或数据库 数据库db_owner 角色的成员。

仅限服务器 sysadmin 角色和 database db_owner 角色成员能够使用存储过程来支持变更数据捕获作业管理。

更改枚举和元数据查询

若要访问与捕获实例关联的更改数据,必须授予 SELECT 用户对关联源表的所有捕获列的访问权限。 此外,如果在创建捕获实例时指定了一个门控角色,则调用者还必须是指定门控角色的成员,并且变更数据捕获架构(cdc)必须具有对门控角色的SELECT访问权限。

其他用于访问元数据的常规变更数据捕获函数可通过公共角色访问所有数据库用户,尽管对返回的元数据的访问通常也会通过使用 SELECT 对基础源表的访问以及任何已定义限制角色的成员身份进行封闭。

对启用了变更数据捕获的源表执行的 DDL 操作

为表启用变更数据捕获后,只能由固定服务器角色 sysadmindatabase role db_owner 成员或 database role db_ddladmin 成员将 DDL 操作应用于该表。 如果用户被显式授予了对该表执行 DDL 操作的权限,则在尝试执行这些操作时将收到 22914 错误。

变更数据捕获的数据类型注意事项

所有基列类型都受变更数据捕获支持。 下表列出了几个列类型的行为和限制。

列类型 更改表中捕获的更改 限制
稀疏列 不支持在使用列集时捕获更改。
计算列 不跟踪对计算列的更改。 该列显示在具有适当类型的更改表中,但值为 NULL.
XML 不跟踪对单个 XML 元素的更改。
时间戳 更改表中的数据类型将转换为 binary。
BLOB 数据类型 仅当 BLOB 列本身发生更改时,才会存储该列更改前的映像。

SQL Server 功能集成

本节说明下列功能如何与变更数据捕获交互:

  • 数据库镜像
  • 事务复制
  • 数据库还原或附加

数据库镜像

可以对启用变更数据捕获的数据库进行镜像。 为确保抓取和清理可在镜像服务器上自动进行,请按照以下步骤操作:

  1. 确保 SQL Server 代理正在镜像上运行。

  2. 在主体服务器因故障而转由镜像服务器接替其工作后,在镜像服务器上创建捕获作业和清除作业。 若要创建作业,请使用存储过程 sys.sp_cdc_add_job

有关数据库镜像的详细信息,请参阅数据库镜像 (SQL Server)

事务复制

变更数据捕获和事务复制可以共存于同一数据库中,但在启用这两项功能后,更改表的填充处理方式将发生变化。 变更数据捕获和事务复制始终使用相同的过程 sp_replcmds 从事务日志读取更改。 当单独启用变更数据捕获时,SQL Server 代理作业会调用 sp_replcmds。 在同一数据库中启用这两项功能时,日志读取器代理会调用 sp_replcmds。 此代理将填充更改表和 distribution 数据库表。 有关详细信息,请参阅 Replication Log Reader Agent

假设存在这样一种情况:已对 AdventureWorks2025 数据库启用变更数据捕获,并且有两个表已启用变更数据捕获。 为了填充更改表,捕获作业会调用 sp_replcmds。 该数据库已启用事务复制,并已创建发布。 此时,将为该数据库创建日志读取器代理,并删除捕获作业。 日志读取器代理继续从提交到更改表的最后一个日志序列号开始扫描日志。 这样将确保更改表中的数据一致性。 如果在此数据库中禁用事务复制,则会删除日志读取器代理,并重新创建捕获作业。

注意

当日志读取器代理同时用于变更数据捕获和事务复制时,复制的更改将首先写入 distribution 数据库。 然后,捕获的更改会写入变更表中。 两项操作将一并提交。 如果写入 distribution 数据库时存在任何延迟,则更改出现在更改表中之前会有相应的延迟。

还原或附加启用了变更数据捕获的数据库

SQL Server 使用以下逻辑确定还原或附加数据库后变更数据捕获是否继续保持启用状态:

  • 如果数据库以同一数据库名称还原到同一服务器,变更数据捕获将保持启用状态。

  • 如果数据库还原到其他服务器,默认情况下将禁用变更数据捕获,并删除所有相关的元数据。

    若要保留变更数据捕获,还原数据库时请使用 KEEP_CDC 选项。 有关此选项的详细信息,请参阅 RESTORE 语句

  • 如果数据库在分离后附加到同一服务器或其他服务器,变更数据捕获将保持启用状态。

  • 如果数据库是使用 KEEP_CDC 选项附加或还原到除标准版或企业版以外的任何版本,操作会遭阻止,因为变更数据捕获需要 SQL Server 标准版或企业版。 将显示错误消息 932:

    SQL Server cannot load database '%.*ls' because change data capture is enabled. The currently installed edition of SQL Server does not support change data capture. Either disable change data capture in the database by using a supported edition of SQL Server, or upgrade the instance to one that supports change data capture.
    

可以使用 sys.sp_cdc_disable_db 从已还原或已附加的数据库中禁用变更数据捕获。

更改跟踪

更改跟踪会记录表中的行已发生更改这一事实,但不会记录被更改的数据。 这样,应用程序就可以确定哪些行已发生更改,并直接从用户表中获取最新的行数据。 因此,与变更数据捕获相比,更改跟踪可以解答的历史问题比较有限。 但是,对于那些不需要历史信息的应用程序,由于无需捕获已更改的数据,存储开销会小得多。 它使用同步跟踪机制来跟踪更改。 此功能旨在最大限度地减少 DML 操作开销。

下图显示了从使用更改跟踪中受益的同步方案。 在此方案中,应用程序需要以下信息:在上次表同步后更改的所有表行以及仅当前行数据。 由于使用同步机制来跟踪更改,因此,应用程序可以执行双向同步,并且可靠地检测到可能发生的任何冲突。

展示更改跟踪概念的示意图。

ADO.NET 的更改跟踪和同步服务

ADO.NET 的同步服务支持数据库之间的同步,并且提供了一个直观且灵活的 API,使你能够生成面向脱机和协作应用场景的应用程序。 ADO.NET 的同步服务提供了一个 API 用于同步更改,但并不实际跟踪服务器或对等数据库中的更改。 你可以创建自定义的更改跟踪系统,但这通常会大大增加复杂性和性能开销。 要跟踪服务器或对等数据库中的更改,建议你使用 SQL Server 中的更改跟踪功能,因为它易于配置并提供高性能的跟踪操作。

有关更改跟踪和 ADO.NET 的同步服务的详细信息,请使用以下链接: