一、背景
当DMS配置为Full Load + CDC(又名Ongoing replication)或者配置为CDC Only后,在传输过程中,可能因为网络等原因中断,包括主动断网、被动断网等。这时候需要重新启动任务继续传输。那么此时DMS能否实现“断点续传”,也就是从停止下来的地方继续开始、而不会触发全表复制?
答案是可以的,本文档模拟环境如下。
二、准备环境
1、创建目标库和源库
分别创建源库和目标库。DMS支持源库类型广泛,可以是其他云或者IDC的各种数据库。
本文为了模拟简便,采用AWS RDS MySQL 8.0作为源库。如果是测试场景,只需要选择很小规格的db.t3.small(2vCPU/2GB)
即可。不需要打开多AZ功能,但是注意要打开自动备份,且设置备份保留周期大于1天。这是因为自动备份功能是和BINLOG功能绑定在一起的,要使用BINLOG,则必须打开自动备份,且设置备份保留周期大于1天。如下截图。
2、创建DMS复制实例
创建DMS实例。本文是测试环境,选择t3.medium即可。软件版本选择列表中看得见的数字最大的、最新的版本。
关于机型,如果是生产环境,数据量小建议选c6i.large(2vCPU/4GB)
,数据量较大建议选择r6i.xlarge(4vCPU/32GB)
。DMS复制实例的类型可以是Public也可以是Private。如果要复制的源数据库在别的云且通过互联网访问,那么需要选择Public。如果是通过专线/VPN从内网访问源数据库,那么选择Private即可。生产环境还可以打开多AZ支持,如果是测试环境,只需要单AZ即可。
创建完毕如下截图。
3、创建DMS Endpoint并验证连接
在DMS的Endpoint下,分别创建两个Endpoint,名为Source和Target。如下截图。
创建时候,可点击Test
按钮测试能否连接到源库。
这里需要注意,创建时候,无论是否能连接成功,Endpoint都会被自动创建出来。如果之前测试连接没有成功,那么创建Endpoint后,还需要回到Endpoint配置界面,继续测试联通。如果Endpoint无法联通,后续复制就无法正常进行。因此必须要在Endpoint界面测试成功。如下截图。
当Source和Target两个Endpoint都测试连接成功后,可开始下一步。
4、源库开启binlog
如前文所述,AWS RDS MySQL作为被复制的源库时候,要打开BINLOG,必须打开自动备份,且设置备份保留周期大于1天。如果不打开,那么BINLOG是关闭的,且执行各种命令都无法打开。如果之前没有打开,那么编辑RDS源库设置,打开自动备份并设置保留周期后,要重启立刻数据库才能生效。
重启后登录的到源库,运行如下SQL命令可验证验证binlog打开。
show variables where Variable_name like 'log_bin';
返回结果:
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.09 sec)
确认打开完毕。
5、调整binlog参数
首先新建一个RDS参数组(Parameter Groups),选择基于MySQL 8的模版创建。
创建完毕后,编辑这个参数组。修改binlog_format
参数为ROW
,修binlog_checksum
为NONE
。如下截图。
其他需要配置的参数,请参考本文末尾的《配置源库准备》文档。
配置参数组完成后,修改源库使用的参数组。从默认的default的修改为新创建的参数组,需要重启RDS才能生效。从如下入口进入编辑,修改参数组。如下截图。
修改参数组后,提示是否立刻重启,还是等到下一个维护窗口才能生效。此时要选择立刻重启。
至此源库准备完毕。
三、开始CDC持续复制
1、数据准备之源库建表
源库上执行:
create database demo1;
use demo1;
CREATE TABLE cdcdata (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME,
data TEXT
);
目标库上执行:
create database demo1;
use demo1;
CREATE TABLE cdcdata (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME,
data TEXT
);
2、在EC2上运行数据生成脚本对源库施加压力
使用一台EC2,在本VPC内网,连接到源库做验证是否连接成功。成功后,在本EC2上编辑如下脚本并命名为test.sh
。内容如下:
#!/bin/bash
# Function to generate a timestamp
generate_timestamp() {
date +"%Y-%m-%d %H:%M:%S"
}
# MySQL database configuration
DB_HOST="source.abcdedfghik.ap-southeast-1.rds.amazonaws.com"
DB_USER="admin"
DB_PASSWORD="12kl3jsd89fy"
DB_NAME="demo1"
TABLE_NAME="cdcdata"
# Main loop
while true; do
# Generate and insert 5 sample data items with timestamps into MySQL
for ((i=1; i<=1; i++)); do
timestamp=$(generate_timestamp)
data_item="Sample data item $i - $timestamp"
# Insert data into MySQL
mysql -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASSWORD" -D"$DB_NAME" -e "INSERT INTO $TABLE_NAME (timestamp, data) VALUES ('$timestamp', '$data_item');"
echo "Inserted: $data_item"
done
# Slee
sleep 5
done
以上脚本中,调整for循环的变量i
可调整每次插入数据行数,调整sleep可调整重复运行频率。
保存后执行:
chmod 700 test.sh
./test.sh
测试数据每秒插入1条,ID为自增ID,更直观的方便对比时间戳。返回结果如下截图。
表示数据插入成功。
3、创建CDC复制任务
确认本任务是包含CDC持续复制的,可以是Full load + CDC类型,也可以是CDC Only。稍后的测试,我们将验证中断的任务续传。无论是Full load + CDC类型还是CDC Only,都不会从头开始复制,都会从中断任务的地方开始。
创建DMS任务时候请注意,在Table mappings
位置选择Wizard
向导编辑模式,然后点击Add new selection rule
按钮添加新的映射规则。在数据库Schema位置要输入被复制的源数据库名称demo1
,表的名字位置使用%
表示通配符复制所有表。
这一步很重要,如果数据库名字也使用通配符%
,那么DMS会复制源数据库上的系统库(包括mysql库等系统库),这时候因为目标库的mysql系统库不让读写,将会直接报错。因此这里务必显式声明要复制的数据库。如下截图。
创建任务完成。选择立刻开始。如下截图。
至此数据复制进行中。
4、查看目标库数据效果的脚本
不要停止生成数据的脚本,保持继续运行。
新开一个SSH窗口,在EC2上用另一个脚本检查目标库数据是否同步成功。脚本check.sh
内容如下:
#!/bin/bash
# Function to generate a timestamp
generate_timestamp() {
date +"%Y-%m-%d %H:%M:%S"
}
# MySQL database configuration
DB_HOST="target.abcdefghijkl.ap-southeast-1.rds.amazonaws.com"
DB_USER="admin"
DB_PASSWORD="10lksjdfjsdg678"
DB_NAME="demo1"
TABLE_NAME="cdcdata"
# Main loop
while true; do
timestamp=$(generate_timestamp)
echo $timestamp
# Insert data into MySQL
mysql -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASSWORD" -D"$DB_NAME" -e "select * from cdcdata order by id desc limit 10;"
# Sleep
echo ""
echo ""
sleep 10
done
保存后执行:
chmod 700 test.sh
./check.sh
这样此脚本会显示目标库内的表最新的几行(倒排序)。通过对比ID和时间戳,可看到DMS持续复制工作正常。
四、人为中断任务后的重启任务测试
1、停止任务
选择当前DMS任务,从下拉框中选择Stop
停止。如下截图。
等待数秒后,任务停止完成。如下截图。
2、确认任务停止时候的数据截止位置
在EC2上观察检查目标库数据结果的脚本check.sh
运行情况。这个脚本持续运行,每隔几秒做一次查询,但可以看到其显示的数据已经固定不变了。
通过间隔数秒的多次执行查询,可看到最后任务停留在ID=3924(自增ID),时间戳停留在08:57:15(UTC时间戳)。如下截图。
稍后我们将检查数据是否能接续传输。
3、重新开始DMS任务
点恢复/重启按钮。如下截图。
注意选择Resume恢复按钮。这里千万别选错了,选Resume。如下截图。
如果是中文界面,注意选择“恢复”。这里千万别选错了,选恢复。如下截图。
由此任务重启完成。
4、检查目标库的续传的恢复时间点
在EC2上观察检查目标库数据结果的脚本check.sh
运行情况。可以看到数据复制任务已经恢复,屏幕上不断的每隔几秒就打印出来复制过来的数据。
如何检查数据传输是连续的呢?在目标库上运行如下SQL脚本,查询中断时候的ID和时间戳,以此来判断是否连续。
select * from cdcdata where id > 3924 order by id asc limit 20;
按前文的断点ID 3924查询,查询结果可以看到,数据的复制是接续的,原始数据是每秒插入一条,插入时候带有时间戳。复制过来的结果看,时间戳是连续的。如下截图。
由此证明DMS续传任务成功。
5、确认DMS续传任务没有复制初始数据(可选)
如何验证在按下Resume按钮之后,DMS从中断的地方开始复制而不是从头开始全量复制了呢?重复上述实验,流程调整如下:
- 确保复制正常,目标库延迟很小即可看到源库数据
- 手工停止DMS任务
- 在目标库上执行
truncate cdcdata;
命令,可清空目标库上的已有的数据 - 继续DMS任务,选择
Resume
按钮 - 在EC2上使用上一步的方法,确认DMS任务接续进行
- 在目标库上执行
select count(*) from cdcdata
命令,统计全表行数
执行truncate命令,如下截图。
执行count命令后,如下截图。
由于DMS任务恢复使用的是Resume方式,因此可以观察到count(*)
统计的数据只有恢复任务以来的这些168行,不会包括任务停止之前CDC复制的数万行。因此可以确认,Resume任务方式不会从头复制数据。
至此DMS任务Resume接续复制的实验完成。
五、关于重启DMS任务(Restart)的测试说明(可选实验)
前文提到重启DMS时候,必须选Resume不能选Restart。
那么如果错误的选择了Restart,会发生什么呢?结论是任务从之前CDC Native Start节点开始重新复制。从这里做下模拟测试。
1、停止任务确认时间点
首先停止任务,可看到任务ID停止在6989(自增ID),时间戳是9:49:47(UTC时间)。如下截图。
2、清空目标库
现在对目标库发起truncate操作,执行truncate cdcdata;
命令清空这张表。
3、重启任务
清空完毕后,重新发起DMS任务,选择Restart任务。如下截图。
4、确认数据被从头复制
可看到数据从2291行开始复制,一直复制到任务中断的6989行,然后继续向下复制。如下截图。
由此看到,选择Restart任务时候,数据会从头复制,而不是从之前中断的位置复制。这里为和从2291行开始呢?请看下一个标题分析任务类型。
5、关于数据复制起始点的说明
刚才的实验中,选择Restart之后,数据从原始库的ID=2291开始复制。既不是刚才人工停止的时间点,也不是原始表的第一行。
这个起始点,是源库打开binlog的第一行,也就是CDC复制任务会从binlog的起始位置开始复制。之前的id=1
到id=2290
是在没有打开binlog时候写入的记录,因此这些记录是不会被DMS CDC Only任务复制的。由于本实验运行的DMS任务的类型是On-going replication only
,因此是从binlog的第一条记录id=2291
开始复制。
如果您的实验环境创建DMS时候,选择的是Full load + CDC
模式,那么这个时候Restart任务,就不是从有binlog的第一行id=2291
开始复制了,就是从本表的第一行id=1
开始复制了。
在很多场景下,由于任务失效或者配置错误,可能需要从特定位置开始复制。此时可以编辑DMS任务,选择自定义起始位置,然后可以选择按时间戳、按binlog日志序号、按Recovery point三种方式之一,从特定位置接续开始。如下截图。
如果希望按按时间戳、按binlog日志序号、按Recovery point三种方式之一的位置开始,那么重启DMS任务时候就必须选择Restart按钮。当选择Resume按钮时候是不能自定义的,DMS在Resume只会从之前的断点继续传输。
由此,介绍了DMS恢复任务的Resume/Restart选项用法,更多信息请参考本文末尾的参考文档。
六、小结
通过以上实验可以看到,当人为的手工停止DMS任务后,无论任务是Full load + CDC
模式还是CDC/Ongoing replication only
模式,都只需要选择Resume任务,即可实现从停止的地方接续传输。
七、参考文档
配置AWS RDS MySQL上的BINLOG二进制日志
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.Binarylog.html
配置源库准备
https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MySQL.html
如何选择Resume或者Restart一个手工停止/遇到错误自动停止的DMS任务(英文)
https://repost.aws/knowledge-center/dms-restart-resume-failed-task