文章目录
一.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
(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中,把数据提交到对应类型数据库的处理步骤。