官网文档:什么是变更数据捕获 (CDC)? - SQL Server | Microsoft Learn
变更数据捕获(Change Data Capture ,简称 CDC)记录 SQL Server 表的插入、更新和删除活动。使用变更数据捕获可以更有效跟踪表对象DML历史操作,对 ETL 等数据转移也非常有用。
变更数据捕获适用版本:
SQL Server 2008 以上的 Enterprise Edition、Developer Edition 和 Evaluation Edition
变更数据捕获原理:
变更数据捕获的更改数据源为 SQL Server 事务日志。当对表启用变更数据捕获时,系统将生成一个与该表结构类似的副本。当对源表进行插入、更新和删除 时,在事务日志会记录相关操作信息。变更数据捕获代理使用异步进程读取事务日志,将相关操作结果应用到副本表(捕获实例表)中,这样就完成了对源表操作的记录跟踪。
其他用途:
CDC不单单用于同步数据,在数据记录上也有很大的作用,增删改查,修改时候会记录修改前修改后的值
确保你的 SQL Server 版本支持 CDC。CDC 在不同版本的 SQL Server 中可用性可能有所不同,因此请确保你正在使用支持 CDC 功能的版本。
官网文档:sys.sp_cdc_enable_db (Transact-SQL) - SQL Server | Microsoft Learn
在目标数据库上启用 CDC。你可以使用下面的 T-SQL 语句来启用 CDC:
USE [Libby];
EXEC sys.sp_cdc_enable_db;
EXEC sys.sp_cdc_enable_db 是启用 SQL Server 的 CDC(Change Data Capture)功能的存储过程,执行该存储过程会在数据库中创建以下表格(表格在系统表中查看):
这些表和函数的作用是:
保存 CDC 表的元数据信息,包括表名、列名、索引信息等。
保存捕获的变更数据,包括操作类型、操作时间、操作用户等。
提供查询 CDC 表变更数据的接口,支持检索历史变更记录和最新变更记录。
总之,这些表和函数是 CDC 功能的核心组件,它们帮助我们捕获、存储和查询数据库表的变更信息,提供了高效的数据库审计和追踪功能。
选择要启用 CDC 的表选择要启用 CDC 的表。你可以使用下面的 T-SQL 语句来启用特定表的 CDC:
官网文档:sys.sp_cdc_enable_table (Transact-SQL) - SQL Server | Microsoft Learn
sql创建了两个作业[cdc.Libby_capture][cdc.Libby_cleanup]
USE [Libby];
EXEC sys.sp_cdc_enable_table @source_schema = N'dbo',
@source_name = N'CdcTest_TableName',
@role_name = NULL,
@supports_net_changes = 1;
这将在指定的表上启用 CDC,并创建用于存储更改数据的 CDC 表和函数。
执行 sys.sp_cdc_enable_table 存储过程。该存储过程将使用以下参数:
配置 CDC 选项。你可以使用下面的 T-SQL 语句来配置 CDC 的选项,例如保留期限、日志清理等:
官网文档:sys.sp_cdc_change_job (Transact-SQL) - SQL Server | Microsoft Learn
USE [Libby]
EXEC sys.sp_cdc_change_job @job_type = 'cleanup', @retention = 4320;
这将设置 CDC 清理作业的保留期限为 4320 分钟(3 天)。
开始捕获更改数据。CDC 将自动开始捕获启用了 CDC 的表的更改数据,并将其存储在 CDC 相关的表中。
你可以使用 CDC 提供的系统函数和视图来查询和分析更改数据。
请注意,启用 CDC 会增加数据库的负载和存储需求,因此在启用之前,请确保你的环境能够承受这些额外开销。
这个时候[dbo].[CdcTest]的增删改操作都会被记录到这个[cdc].[dbo_CdcTest_CT]表中
通过[cdc].[dbo_CdcTest_CT]就可以查看了
__$start_lsn 列标识为更改指定的提交日志序列号 (LSN)。 提交 LSN 不仅标识在同一事务中提交的更改,而且还对这些事务进行排序。 可以使用
__$seqval 列对同一事务中进行的其他更改进行排序。
__$operation 列记录与更改关联的操作:1 = 删除,2 = 插入,3 = 更新(旧值),4 = 更新(新值)。
__$update_mask 列是一个可变的位掩码,每个捕获列都有一个对应的定义位。 对于插入和删除项,更新掩码始终设置所有位。 但是,更新行仅设置与更改列对应的那些位。
官网文档:启用和禁用“变更数据捕获” - SQL Server | Microsoft Learn
USE [Libby]
GO
EXEC sys.sp_cdc_disable_db
GO
USE [Libby]
GO
EXEC sys.sp_cdc_enable_table
@source_schema = N'dbo',
@source_name = N'CdcTest',
@role_name = N'MyRole',
@filegroup_name = N'MyDB_CT',
@supports_net_changes = 1
GO
USE [Libby]
GO
EXEC sys.sp_cdc_enable_table
@source_schema = N'dbo',
@source_name = N'CdcTest',
@role_name = NULL,
@supports_net_changes = 1
GO
命令执行后,CDC日志表直接删除
USE [Libby]
GO
EXEC sys.sp_cdc_disable_table
@source_schema = N'dbo',
@source_name = N'CdcTest',
@capture_instance = N'dbo_CdcTest'
GO
--查询数据库是否开启CDC
SELECT name,is_cdc_enabled FROM sys.databases
--查询表是否开启CDC
SELECT name,is_tracked_by_cdc FROM sys.tables
如果被监控表执行了DDL操作,CDC日志表是不会随之改变的,举例增删了列或者删除了列,CDC只会忽略变更的列,如果是新增,CDC不会记录新增列,如果是删除列,CDC会把NULL插入到此列,如果想同步这个变更列需要进行以下操作
需要注意的是,如果CDC日志表有数据,会被删除掉,此方案只适用于没有变更记录的情况下,或者能接受变更记录丢失的情况
USE [Libby];
GO
EXEC sys.sp_cdc_disable_table @source_schema = N'dbo',
@source_name = N'CdcTest',
@capture_instance = N'dbo_CdcTest';
GO
USE [Libby];
EXEC sys.sp_cdc_enable_table @source_schema = N'dbo',
@source_name = N'CdcTest',
@role_name = NULL,
@supports_net_changes = 1;
GO
错误信息如下:
消息 22830,级别 16,状态 1,过程 sp_cdc_enable_db_internal,行 193 [批起始行 0] 无法更新元数据来指示已对数据库 SDP_Kelun 启用了变更数据捕获。执行命令 'SetCDCTracked(Value = 1)' 时失败。返回的错误为 15517: '无法作为数据库主体执行,因为主体 "dbo" 不存在、无法模拟这种类型的主体,或您没有所需的权限。'。请使用此操作和错误来确定失败的原因并重新提交请求。
解决方案:
错误原因是因为dbo架构原因导致的,需要调整权限,根据以下方式看看自己属于哪个问题,这里都以sa账户举例:
15517错误码官网文档:MSSQLSERVER_15517 - SQL Server | Microsoft Learn
①检查这里是不是sa账户
②检查架构是否存在
解决方案脚本:
①分配权限
GRANT ALTER ANY SCHEMA TO sa;
GRANT CONTROL TO sa;
②修改数据库归属,将 dbo 更改为有效用户
ALTER AUTHORIZATION ON DATABASE::SDP_Kelun TO [sa];