简述
SQL Server 是一个值得信赖的老牌数据库系统,自从 1988 年由 Microsoft、Sybase 和 Ashton-Tate 三家公司共同推出之后就一直不断迭代更新。
而如今我们提到 SQL Server 通常是指 Microsoft 从 SQL Server 2000 之后的版本。至今 SQL Server 家族产品已经非常丰富,涵盖了 云上(Azure SQL Server)、IoT 设备(边缘 SQL Server)、以及经典版本(本地 SQL Server)。
在 CloudCanal 中要想使用 SQL Server 的实时数据同步则必须要用到它的 CDC 功能,这个功能是从 2008 版本才开始支持。因此本文主要也是基于 SQL Server 2008 版本介绍如何使用 CloudCanal 快速构建一条稳定高效运行的 SQL Server 到 MySQL 数据同步链路。
技术点
基于 SQL Server 的 CDC

作业执行用到 SQL Server 代理,该组件如果处于非启动状态,则生成任何可消费的变更数据。通常,我们可以在 Windows 对象资源管理器中查看是否已经开启了 SQL Server 代理。

由于 SQL Server 执行作业时无法设置起始位置,因此对于一个表的变更记录我们最早只能追溯到表启用 CDC 的那个时间点。具体的起始位点可以在 “cdc.change_tables” 表中查询得到。
还需要注意的另外一个细节是 CDC 表也是一张普通的表它和用户共享同一个数据空间。为了防止 CDC 表数据无限膨胀 SQL Server 会每天定时执行清理作业,清理过期的数据(具体时间视数据库配置而定)。
SQL Server -> MySQL 的数据类型支持
CloudCanal 从 2021 年开始支持 SQL Server 同步后就不断地丰富它的对端数据源,支持 SQL Server 到 MySQL 是一个非常重要的同步链路。目前 CloudCanal 已经可以支持的类型和映射关系如下:
| SQL Server 类型 | MySQL 类型 | 备注 |
| BIT | BIT | |
| DECIMAL | DECIMAL | |
| NUMERIC | DECIMAL | |
| SMALLINT | SMALLINT | |
| TINYINT | TINYINT | 映射为 tinyint unsigned |
| INT | INT | |
| BIGINT | BIGINT | |
| SMALLMONEY | FLOAT | |
| MONEY | FLOAT | |
| FLOAT | FLOAT | |
| REAL | DOUBLE | |
| DATE | DATE | |
| DATETIMEOFFSET | DATETIME | 由于 MySQL 类型限制,会丢弃时区信息同时最多保留 6 位精度 |
| DATETIME2 | DATETIME | 由于 MySQL 类型限制,会保留最多 6 位精度 |
| SMALLDATETIME | DATETIME | |
| DATETIME | DATETIME | 由于 MySQL 类型限制,会保留最多 6 位精度 |
| TIME | TIME | 由于 MySQL 类型限制,会保留最多 6 位精度 |
| CHAR | CHAR | |
| VARCHAR | VARCHAR | 源端 SQL Server 如果为 VARCHAR(MAX),则按照 TEXT 来处理 |
| TEXT | TEXT | |
| NCHAR | CHAR | |
| NVARCHAR | VARCHAR | 源端 SQL Server 如果为 NVARCHAR(MAX),则按照 NTEXT 来处理 |
| NTEXT | TEXT | |
| BINARY | BINARY | |
| VARBINARY | VARBINARY | 源端 SQL Server 如果为 VARBINARY(MAX),则按照 IMAGE 来处理 |
| IMAGE | BLOB | |
| TIMESTAMP | BIGINT | 会映射为 bigint unsigned |
| ROWVERSION | BIGINT | 会映射为 bigint unsigned |
| HIERARCHYID | -- | 暂不支持 |
| UNIQUEIDENTIFIER | VARCHAR(36) | |
| SQL_VARIANT | -- | 暂不支持 |
| XML | TEXT | |
| GEOMETRY | -- | 暂不支持 |
| GEOGRAPHY | -- | 暂不支持 |
| SYSNAME | VARCHAR(128) |
操作示例
前置条件
• 登入 CloudCanal SaaS版,使用参见快速上手文档
• 准备一个 SQL Server 数据库,和 MySQL 实例(本例分别使用自建 SQL Server 2008 和 MySQL 8.0)
• 登录 CloudCanal 平台 ,添加 SQL Server 和 MySQL

• 创建一条 SQL Server -> MySQL 链路作为增量数据来源
任务创建
• 任务管理 -> 任务创建
• 测试链接并选择 源 和 目标 数据库
• 点击下一步

• 选择 数据同步,并勾选 全量数据初始化,其他选项默认

• 此时如果 SQL Server 上数据库还没有启用 CDC 功能,则会在点击下一步的时候提示如何启用 CDC。只要按照提示的参考语句执行后再继续任务创建即可。

• 选择需要迁移同步的表和列


• 确认创建任务

• 任务自动做结构迁移、全量迁移、增量同步

校验数据
• 程序造数据, SQL Server -> MySQL,在源端以 1:1:1 的比例随机执行Insert、Update、Delete 三种类型语句。使用 20 个线程并发写入变更。

• 任务正常运行一段时间后,停止造数据
• 点击 SQLServer -> MySQL 任务详情,功能列表 -> 创建相似任务,在创建任务的第二步选择数据校验

• 数据校验 OK
• 下面这个是校验结果。如果我们对端和源端一旦出现数据不一致就会像下面这样非常醒目的提示给用户,有多少数据不一致,有多少数据丢失。

常见问题
支持什么版本的 SQL Server 和 MySQL ?
• 目前源端 SQL Server 2008 及以上版本皆可使用 CloudCanal 进行迁移同步(推荐使用 SQL Server 2016 或 SQL Server 2008)
• 对端 MySQL 支持 5.6、5.7、8.0 版本,也可以选用 阿里云 RDS for MySQL 对应的版本,或者其它云服务商的 MySQL 版本
数据不同步了都有哪些情况?
• SQL Server CDC 需要依赖 SQL Server 代理,首先要确定 SQL Server 代理服务是否启动
• 表在启动 CDC 的时候会确定要捕获的列清单,此时如果修改列的类型可能会导致 CDC 中断。目前解决办法只能重建任务。
• 增/减 同一个列名的列,对一个列删除后再增加。虽然 CDC 表中字段依然存在但是也会导致整个 CDC 中断。
什么情况下会影响稳定的数据同步?
• 如果任务在同步期间出现了异常导致任务延迟。这时候需要格外注意,如果过长时间的延迟,即便是修复了延迟的问题(比如对端数据库长时间出现不可用)在后续数据同步上也可能存在丢失数据的风险。
• SQL Server 为了防止 CDC 表数据无限膨胀 SQL Server 会每天定时执行清理作业,清理超过 3天的数据。
• 为了增加延迟的容忍度可以执行这以下SQL 来增加 CDC 数据的保存时间,代价是这些数据需要存放到数据库表中,如果每日数据变更很多对磁盘开销会有额外的要求。msdb.dbo.cdc_jobs表中保存了具体捕获任务的数据保存时间。
总结
本文简单介绍了如何使用 CloudCanal 进行 SQL Server -> MySQL 数据迁移同步。各位读者朋友,如果你觉得还不错,请点赞、评论加转发吧。
execute sys.sp_cdc_change_job @job_type = n'cleanup', @retention = 4320




