Sql server数据同步2种方式 CDC(Change Data Capture )和CT (Change Tracking)(附详细操作流程)

一.Sql server

为了应对数据库中DML(insert/update/delete)操作引起的数据变化,Sql server提供CT和CDC 2种方式进行数据同步。

二.特征以及优点:

为了确定数据变更,研发人员通常使用触发器,时间戳等实现自定义追踪的方法。需要大量的工作且会带来高性能开销。

CDC通过捕获发生的DML操作和变更的实际数据,提供历史变更信息。通过使用异步进程来捕获变更数据,进程读取事务日志,对系统的影响很小。

CT只记录变化后的数据,而不记录发生变化,通过传递上次同步的版本号来获取从上次同步到现在的变化记录。每隔一定时间获取数据表中的变化记录,然后根据变化记录中的主键来获取更新过的数据。CT通过对要执行的DML语句的分析获取变化记录,而不是去读取日志。DML语句提交执行时CT便已可用,而不需要等待DML完成后事务日志写入时才可用。

因此CT的响应比CDC快。CT记录的数据比CDC少,对服务器性能的影响小。

三.CDC

Cdc操作的来源是SQLServer transaction log,将插入,更新和删除的信息添加到追踪表变更的关联表中。
在这里插入图片描述

在追踪表变更之前,为数据库启用CDC,即使用存储过程 sys.sp_cdc_enable_db。
启用此存储过程之后,将创建对应的新的实例—CDC实例----以记录在源表中发生的更改。

(1)源表的元数据保留在cdc实例元数据表cdc.change_tables,cdc.index_columns和cdc.captured_columns中

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(2)默认情况下,记录数据变更的表名称为源表的<模式名_表名>。通过将_CT附加到创建的cdc实例中命名关联的更改表。
在这里插入图片描述

(3) fn_cdc_get_all_changes_以及fn_cdc_get_net_changes_ 查询
在这里插入图片描述

四.CDC操作步骤

(1)开启代理服务(Agent服务)

查询是否开启

EXEC master.dbo.xp_servicecontrol N'QUERYSTATE', N'SQLSERVERAGENT';

在这里插入图片描述

若没有开启,在linux系统中

sudo /opt/mssql/bin/mssql-conf set sqlagent.enabled true

重新启动SQL Server

sudo systemctl restart mssql-server

Linux 上创建和运行 SQL Server 代理

(2)配置额外的磁盘空间

(3)开启数据库级别的cdc (di 为数据库)

use di;
if exists(select 1 from sys.databases where name='di' and is_cdc_enabled=0)
 begin
exec sys.sp_cdc_enable_db
end;

select is_cdc_enabled from sys.databases where name='di';   --查询是否开启

在这里插入图片描述

注意:

A.关闭数据库级别cdc命令:

EXEC sys.sp_cdc_disable_db
GO                   --关闭CDC
select is_cdc_enabled from sys.databases where name='di';

B.如果在禁用cdc时为数据库定义许多实例,则长时间运行事务可能导致 sys.sp_cdc_disable_db 的执行失败。通过在运行 sys.sp_cdc_disable_db 之前使用 sys.sp_cdc_disable_table 禁用单个捕获实例,可避免此问题:

USE di; 
GO 

execute sys.sp_cdc_help_change_data_capture;  --查询capture_instance

EXECUTE sys.sp_cdc_disable_table 
@source_schema = N'test', 
@source_name = N'name', 
@capture_instance = N'test_name';

(4)添加cdc专用的文件组和文件

 --查询某个库的物理文件:
SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID('di');

在这里插入图片描述

/*添加文件组:*/
ALTER DATABASE di ADD FILEGROUP CDC;
/* 将新增文件,并映射到文件组:*/
ALTER DATABASE di
    ADD FILE
        (
            NAME= 'di_CDC',
            FILENAME = '/var/opt/mssql/data/di_CDC.ndf'
            )
        TO FILEGROUP CDC;
/*验证:*/
SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID('di');

在这里插入图片描述

(5)开启表级别的cdc

--CDC是数据库文件组的名称
IF EXISTS(SELECT 1 FROM sys.tables WHERE name='name' AND is_tracked_by_cdc = 0)
    BEGIN
        EXEC sys.sp_cdc_enable_table
             @source_schema = 'test', -- source_schema
             @source_name = 'name', -- table_name
             @capture_instance = NULL, -- capture_instance
             @supports_net_changes = 1, -- supports_net_changes
             @role_name = NULL, -- role_name
             @index_name = NULL, -- index_name
             @captured_column_list = NULL, -- captured_column_list
             @filegroup_name = 'CDC' -- filegroup_name
    END;

SELECT is_tracked_by_cdc FROM sys.tables WHERE name='name';  --验证

在这里插入图片描述

注意:
在生产中有多个表进行设置可考虑使用游标批量设置。

DECLARE @tableName nvarchar(36)  -- 声明变量
DECLARE My_Cursor CURSOR --定义游标
    FOR (SELECT * FROM SysObjects Where XType='U' ORDER BY Name) --查出需要的集合放到游标中
OPEN My_Cursor; --打开游标
FETCH NEXT FROM My_Cursor INTO @tableName;
WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC sys.sp_cdc_enable_table
         @source_schema = 'test', -- source_schema
         @source_name = @tableName, -- table_name
         @capture_instance = NULL, -- capture_instance
         @supports_net_changes = 1, -- supports_net_changes
         @role_name = NULL, -- role_name
         @index_name = NULL, -- index_name
         @captured_column_list = NULL, -- captured_column_list
         @filegroup_name = 'CDC' -- filegroup_name;

    FETCH NEXT FROM My_Cursor INTO @tableName;
END
CLOSE My_Cursor; --关闭游标
DEALLOCATE My_Cursor; --释放游标

/* 查询开启了哪些表被开启了CDC功能:*/

select name,type,create_date,modify_date,is_tracked_by_cdc from sys.tables where is_tracked_by_cdc = 1;

在这里插入图片描述

五.CDC展示

(1)cdc表结构说明

源表

在这里插入图片描述
CDC表
在这里插入图片描述

__ $ start_lsn:标识分配给更改的提交日志序列号(LSN)。提交LSN既标识在同一事务中提交的更改,又对事务进行排序。
__ $ seqval:可用于订购同一事务中发生的更多更改
__ $ operation:记录与更改关联的操作:1 =删除,2 =插入,3 =更新(在映像之前)和4 =更新(在映像之后)。
__ $ update_mask:是一个可变位掩码,每个列都有一个定义的位。对于插入和删除条目,更新掩码将始终设置所有位。但是,更新行将仅设置与更改的列相对应的那些位。

(2)展示:

insert:
在这里插入图片描述
在这里插入图片描述

delete:
在这里插入图片描述
update(产生2条记录):
在这里插入图片描述
在这里插入图片描述

六. todo 从sql server 实时同步到不同类型数据库 oracle mysql postgresql的方案以及CT后面有时间再写

从sql server 实时同步到不同类型数据库 oracle mysql postgresql:
项目中的思路: 设置偏移,根据操作的类型写入Record的头信息中,然后把数据写入data中,把数据提交到对应类型数据库的处理步骤。

猜你喜欢

转载自blog.csdn.net/javahelpyou/article/details/109403870