DMS停止服务后Resume续传的测试

一、背景

当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_checksumNONE。如下截图。

其他需要配置的参数,请参考本文末尾的《配置源库准备》文档。

配置参数组完成后,修改源库使用的参数组。从默认的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=1id=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