深入浅出 SQL Server CDC 数据同步

news2024/11/18 14:01:57

简介

SQL Server 是一款老牌关系型数据库,自 1988 年由 Microsoft、Sybase 和 Ashton-Tate 三家公司共同推出,不断迭代更新至今,拥有相当广泛的用户群体。

如今,我们提到 SQL Server 通常指 Microsoft SQL Server 2000 之后的版本。

SQL Server 2008 是一个里程碑版本,加入了大量新特性,包括 新的语法更丰富的类型 以及本文所提及的 CDC 能力,这个能力让数据从 SQL Server 实时同步到外部更加方便。

本文将介绍 CloudCanal 在新版本中对于 SQL Server 数据同步更进一步的优化和实践。

SQL Server CDC 长什么样?

原始日志

常见的数据库往往存在以下两种日志

  • redo 日志
    • 记录数据的正向变更,简单来说,事务的 commit 通常先记录在这个文件,再返回应用程序成功,可确保数据 持久性
  • undo 日志
    • 用于保证事务的 原子性,如执行 rollback 命令即反向执行 undo 日志中内容以达成数据回滚

一条 DML 语句写入数据库流程如下

  • 大部分关系型数据库中,一个或多个变更会被隐式或显式包装成一个事务
  • 事务开始,数据库引擎定位到数据行所在的 文件位置 并根据已有的数据生成 前镜像后镜像
  • 后镜像 数据记录到 redo 日志中,前镜像 数据记录到 undo 日志中
  • 事务提交后,日志提交位点(检查点)向前推进,已提交的日志内容即可能被覆盖或者释放

SQL Server redo/undo 日志采用了 ldf 格式 ,文件循环使用。

  • ldf 日志文件由多个 VLF(逻辑日志) 组合在一起,这些 VLF 首尾相连形成完整的数据库日志记录
  • ldf 在逻辑日志末端到达物理日志文件末端时,新的日志记录将回到物理日志文件开始,复写旧的数据

ldf 文件即 CDC 所分析的增量日志文件。

启用 CDC

在数据库上执行 exec [console].sys.sp_cdc_enable_db 命令为 console 数据库启用 CDC 功能,这个语句实际上会创建两个作业: cdc.console_capture , cdc.console_cleanup

使用 exec sp_cdc_help_jobs 命令可查看这两个作业详细信息。

  • cdc.console_capture
    • 负责分析 ldf 日志 并解析 console 数据库事件,再将其写入到 CDC 表中
    • 间隔 5 秒钟执行一次扫描,每次扫描 10 轮,每轮扫描最多 500 个事务
  • cdc.console_cleanup
    • 负责定期清理 CDC 表中较老的数据
    • 默认保留 3 天 CDC 日志数据(4320秒)

开启 CDC 功能后,SQL Server 数据库会多出一个名称为 cdc 的 schema,里面会多出下列这些表。

  • change_tables
    • 记录每一个启用了 CDC 的 源表 及其对应的 捕获表
  • captured_columns
    • 记录对应 捕获表 中每个列的信息
  • index_columns
    • 记录 源表 含有的主键信息(如果有)
  • lsn_time_mapping
    • 记录每个事务的开始/结束时间及 LSN 位置信息
  • ddl_history
    • 记录源表发生的 增/减列 对应的 DDL 信息,除此之外的 DDL 都不会被记录

有了上述准备动作和信息,即可开始对原始表开启 change data capture(CDC),即增量数据捕获了。

捕获表变更

有如下 源表

create table [dbo].[test_table] (
  [id] [bigint] NOT NULL primary key,
  [test] [nchar](10) NULL
)

执行下列命令即可为它启用 CDC

exec [console].[sys].[sp_cdc_enable_table]
    @source_schema = [dbo],
    @source_name = [test_table],
    @role_name = NULL,
    @capture_instance = [dbo_test_table], -- 可选项
    @supports_net_changes = 0;

cdc schema 下多出一个名为 dbo_test_table_CT 的表,即 捕获表

  • 源表 [dbo].[test_table] 做若干 DML 操作,通常是 5 秒内就可在捕获表中看到变更记录
  • 源表 做一些 增/减 列 操作,对应的 DDL 会出现在 ddl_history 表中

其他表也可通过类似设置,获取到相应的增量变更。整个机制看上去相当直观和简单。

挑战是什么?

难点1:DDL 同步困难

CDC 捕获表只反馈数据的变化,无 DDL 信息

DDL 需额外获取即和 DML 的顺序关系要额外处理

解决这个问题,需要通过执行以下的 SQL 将 DDL 和 DML 事件混合到一起并保证顺序,但是实际使用中会面临严重的性能问题。

select * from (
	select __$start_lsn lsn,__$operation oper,__$update_mask mask, null ddl ,id data_id,test data_test 
	from [console].[cdc].[dbo_test_table_CT]
	union
	select ddl_lsn lsn, -1 oper,null mask,  ddl_command ddl ,null data_id,null data_test 
	from [console].[cdc].[ddl_history]
) t order by lsn

难点2:无法获取新增列数据

CDC 捕获表的结构并不会随着 DDL 事件的发生而变化,这意味着无法获取新增列的数据

难点3:数据库限制

使用 CDC 功能本身也会产生一些硬性的限制,大致可以分为两类

硬性限制

  • 已经启用 CDC 捕获的源表上不能执行 truncate table 语句,执行即报错

  • CDC 捕获表本质上也是一个普通的表,大量订阅会导致整库表的数量扩大

  • 依赖 SQL Server 代理,如没启动或作业运行失败,捕获表中不会有任何新数据写入

  • 一张表只能创建 2 张对应的 CDC 捕获表,即无法做超过 2 个以上的增量订阅

  • 一张表的 CDC 捕获只能设置启动和禁止,即不能通过重建 CDC 并指定 LSN 来获取新数据

软性限制

  • CDC 捕获表中的数据存留时间默认 3 天

  • 在插入或更新超大字段时默认 CDC 只会处理最大 64KB 个字节的数据

    • 数据内容如果超过这个限制会导致 CDC 捕获任务报错并停止工作
    • 受影响的类型有 7 个:textntextvarchar(max)nvarchar(max)varbinary(max)xmlimage

CloudCanal 的解决方法

CloudCanal SQL Server 增量消费基础处理模型如下所述,保证单个表的数据变更顺序,满足大部分场景

  • 根据 change_tables 表确定一个工作队列
  • 确定起始位点,对于捕获表的增量数据扫描从起始位点开始
  • 并发处理工作队列上的事件
  • 每个 Worker 会根据起始 LSN 扫描自身要处理的 CDC 捕获表
  • 每个 Worker 扫描都会维护自身的 LSN 进度

解决难点1:DML/DDL重排序

CDC 捕获表中的每一条记录都有一个 LSN 信息,ddl_history 表也有 LSN 信息。因此可以借助 插值 的思想将 DDL 事件插入到正常的 DML 事件序列中去,原理如下图:

  1. ddl_history 表进行预查询,获取到的 DDL 事件在稍后的处理中会进行位点比对处理
  2. 查询 dbo_test_table_CT 数据捕获表
  3. 处理每一条的捕获表的数据时检测 DDL 事件是否可以被插入
  4. 形成完整的事件流

解决难点2:反查补充缺失数据

SQL Server CDC 捕获表最多只能创建 2 张是硬性限制,但刚好能解决这个问题,在 DDL 发生后创建第二个 CDC 捕获表可以感知到 DDL 对数据的变化

  1. 创建第一个 CDC 捕获表 dbo_test_table_1_CT
  2. 在两次数据插入的中间增加一个新的列
  3. 创建第二个 CDC 捕获表 dbo_test_table_2_CT
  4. 在插入一条新数据

通过上图可看到 dbo_test_table_2_CT 相比 dbo_test_table_1_CT 已经可以感知到新增的列数据

遗憾的是 DDL 发生后到第二个 CDC 捕获表创建出来之前这中间的数据仍然是缺失的

上面的例子如下图所示(灰色的 Event 表示事件或者数据有缺损)

以 DDL 发生的 LSN 为分界点

  • 在 DDL 发生之前 dbo_test_table_1_CT 表中的数据是完全可信的
  • 在 DDL 发生之后由于 dbo_test_table_1_CT 表中并没有新列字段,因此它的数据是残缺的,不能完全信任
  • dbo_test_table_2_CT 是由于在 DDL 发生后才被创建出来,因此相比较 dbo_test_table_1_CT 它的数据是缺失的
  • 此外 dbo_test_table_1_CTdbo_test_table_2_CT 之间还存在一个盲区导致这个 INSERT 事件两个表都不可信

CloudCanal 解决办法是在此基础上将两张表都缺损的位点 反向使用 PK 从源表中补齐 的方式解决这个问题(上图中深灰色部分)

有一个极端情况是在第二张 CDC 捕获表创建过程中发生了新的 DDL ,这会导致新创建的捕获表也不可靠,因此需要重新创建第二个 CDC 捕获表,并且扩大中间需要反查补齐的数据范围(下图中深灰色部分)

CloudCanal 正是基于上述一系列机制才解决了 DDL 事件导致无法获取增量数据的难题

解决难点3:提供专业优化方案

对于硬性限制,CloudCanal 没有正面解决的方案,而是后续提供更多样的方式(如 trigger,定时增量扫描,新版本SQL Server CDC方案 等)进行补充。

软性限制,可通过以下方式优化

  • 通过以下命令中的 retention 参数来设置 CDC 捕获表中的数据存留时间

    exec console.sys.sp_cdc_change_job 
        @job_type = 'cleanup',
        @retention=4320 -- 单位:秒
    
  • 通过以下命令调整 CDC 处理的最大数据字节

    exec sp_configure 'show advanced options', 1 ;   
    reconfigure;
    exec sp_configure 'max text repl size', -1; -- -1 表示不限制
    reconfigure;
    

总结

本文简单介绍了 SQL Server CDC 技术,然后基于此能力,CloudCanal 是如何实现稳定的增量 DML + DDL 同步, 并且解决了其中遇到的难题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/563251.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件测试的7个级别,做到3级已经超越80%测试人!

有人说:软件测试就是最low的点点点工作。 有人说:测试工作职位薪水到一定程度只能原地踏步无法提升 也有人说:测试行业相对于开发来说技术性很低,容易被取代。 这其实是对测试行业最大的误解。测试可深可浅,可窄可广…

linux嵌入式学习

https://www.runoob.com/linux/linux-comm-ls.html https://www.bilibili.com/video/BV1w4411B7a4?p19&spm_id_frompageDriver&vd_sourcee7d12c9f66ab8294c87125a95510dac9 1 eMMC eMMC(embedded MultiMediaCard)是一种集成电路,用…

vue2+wangeditor富文本域

vue2wangeditor富文本域 效果图安装依赖初始化简约模式自定义模式图片设置只允许 base64 方式支持图片服务器 更多配置项目依赖项目代码 效果图 安装依赖 npm i wangeditor/editor wangeditor/editor-for-vue初始化 <template><div class"editor-box">…

IIS 日志解析,增强 IIS 服务器安全性

企业严重依赖 Microsoft Internet 信息服务 &#xff08;IIS&#xff09; 服务器来托管其网页和 Web 应用程序&#xff0c;以及存储其文件。请务必妥善保护您的 IIS 服务器&#xff08;包括 Web 和 FTP&#xff09;。 什么是 IIS 日志 IIS 日志是 Microsoft IIS Web 服务器上…

柔顺机构学读书笔记1:悬臂梁变形

题目&#xff1a; 如图考虑悬臂梁&#xff0c;材料各向同性&#xff0c;即各个方向上的弹性模量和强度都相同。如果在x方向上作用一个可使最大应力等于屈服强度 S S S的力 F x F_x Fx​时&#xff0c; x x x轴方向的变形为多少&#xff0c;书上给出了答案&#xff1a; 我们来验…

网易有道财报:网易有道2023财年收入将强劲增长,亏损将减少?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 预计2023年收入增长强劲&#xff0c;净亏损收窄 猛兽财经认为网易有道&#xff08;DAO&#xff09;今年是有能力实现更多的收入增长和减少亏损的。具体来说&#xff0c;我们预计网易有道的收入将在2023财年增长至少20%&am…

Semantic Kernel VS LangChain

每当向他人介绍 Semantic Kernel&#xff0c;会得到的第一个问题就是 Semantic Kernel 类似于 LangChain 吗&#xff1f;或者是 C# 版本的 LangChain 吗&#xff1f;因此我总结了这篇文章。 微软MVP实验室研究员 张善友 深圳友浩达 CTO & 首席架构师&#xff0c;微软最有价…

进程间通信-system V共享内存

文章目录 1. system V共享内存1.1 共享内存示意图 2. 共享内存函数2.1 shmget函数2.2 代码实现2.2.1 shmat2.2.2 shmdt 3. 信息量 1. system V共享内存 system V的意思是一套标准&#xff0c;共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff…

AI遇上建筑设计,是出圈还是翻车?

AIGC 落地&#xff0c;始于场景&#xff0c;终于价值。 去年以来出现了 AIGC 热潮&#xff0c;引发了 AIGC 及其应用话题的爆发性增长&#xff0c;不少人感慨强人工智能的时代已经离我们不那么遥远了。但是在热潮的另一面&#xff0c;我们看到真正能落地的场景依然是凤毛麟角&a…

【C语言】结构体指针

结构体指针 结构体基础知识注意对于成员的赋值 结构体指针指向结构体变量的指针结构体指针与结构体成员指针用结构体指针引用结构体成员 结构体 基础知识 初识结构体&#xff0c;可以先看这篇浅显易懂的文章结构体–基础篇 所谓结构体&#xff0c;是一组类型可以不同的相关变…

部署输配电线路火灾隐患排查治理

输电线路防山火在线监测装置 一、产品描述&#xff1a; 电力设施为了远离人们的生活区域选择部分扎根在森林里面&#xff0c;减少发生触电事故的发生。但是提到森林就不得不说其中一个山火问题&#xff0c;山火灾害对建设在森林的电力设施造成的损害不可预估&#xff0c;为保障…

CodeForces.1806A .平面移动.[简单][判断可达范围][找步数规律]

题目描述&#xff1a; 题目解读&#xff1a; 给定移动规则以及起始点&#xff0c;终点&#xff1b;分析终点是否可达&#xff0c;可达则输出最小步数。 解题思路&#xff1a; 首先要判定是否可达。画图可知&#xff0c;对于题目给定的移动规则&#xff0c;只能到达起始点(a,b…

Go 开发实践:手把手教你搭建一个登录功能

本文首发自「慕课网」 &#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注"慕课网"及“慕课网公众号”&#xff01; 作者&#xff1a;Codey|慕课网讲师 用 Go 语言搭建简易登录功能 如果你最近刚学习Go 语言基础特性&#xff0c;对 …

《深入理解BigDecimal:揭秘钱财计算的核心技术》

文章目录 《深入理解BigDecimal:揭秘钱财计算的核心技术》***\*一、BigDecimal概述\*******\*二、BigDecimal常用构造函数\****2.1、常用构造函数2.2、使用问题分析***\*三、BigDecimal常用方法详解\****3.1、常用方法3.2、BigDecimal大小比较***\*四、BigDecimal格式化\*****…

【正点原子STM32连载】 第二十章 基本定时器实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十…

字符串匹配算法--KMP算法--BM算法

该算法解决的是字符串匹配问题&#xff0c;即查看字符串中是否含有完整的匹配字符串。如在java的string的contains方法匹配问题最简单的就是暴力破解了。在java的contains也是这么实现的&#xff0c;效率是低一点的。如果想要更快的速度可以自己写KMP算法。 代码实现体验 还未…

chatgpt赋能Python-python_numpy怎么用

Python与Numpy&#xff1a;简介 Python是一种高级编程语言&#xff0c;它具有简洁的语法和广泛的应用领域。Numpy是一个为Python提供高效数学库的开源库&#xff0c;它允许进行高速数值计算和数据处理。 对于那些正在开始使用Python和Numpy的初学者&#xff0c;这篇文章将向您…

CANoe使用教程

目录 1.CAN IG使用 2.Visual Sequence 自动发送报文序列&#xff0c;可以设置多个visual sequence&#xff0c;可用于重复的网络模拟和write窗口输出&#xff0c;比IG灵活&#xff0c;比CAPL简单 3.CANoe中的系统变量和环境变量都是一种用于存储和传递数据的变量&#xff0c;…

linux部署yolov5

Linux配置 LibTorch 和 OpenCV LibTorch 下载地址&#xff1a;https://pytorch.org/get-started/locally/ 直接解压即可 OpenCV 下载地址&#xff1a;https://opencv.org/releases/ 需要配置ffmpeg环境 export LD_LIBRARY_PATH$LD_LIBRARY_PATH:/home/workspace/dengzr/li…

嵌入式Linux应用开发笔记:GPIO编程

文章目录 目的基础说明代码示例数字输出数字输入外部中断 总结 目的 GPIO嵌入式设备中最基础的外设&#xff0c;使用上也是非常频繁的。这篇文章将记录下应用程序中GPIO操作相关内容。 这篇文章中内容均在下面的开发板上进行测试&#xff1a; 《新唐NUC980使用记录&#xff1…