适用范围
版本号:PanWeiDB_V2.0-dtp3.2.1_B01
迁移类型:正向增量
问题概述
当业务无法停止,且业务的数据量很大的情况下,要求做在线增量迁移,应该怎么做?
场景测试
创建测试表并插入一条数据:
如下所示,DTP迁移界面,迁移选项分为"库表结构",“全量数据”,“增量数据”:
场景1:分别将"库表结构",“全量数据”,“增量数据"依次执行;
场景2:先将"库表结构"执行,后将"全量数据”,"增量数据"全部勾选执行;
目的是测试这两种场景下,会不会丢失数据。
场景1:详细过程
1、迁移"库表结构",迁移报告如下:
2、迁移"全量数据",迁移报告如下:

如上,源、目标数据一致。
3、拉起增量前,业务依然实时在写入数据,模拟如下:
4、拉起增量
如下所示,“同步起点"只能选择"当前起点”:
运行后,模拟插入数据,id = 3 :
如上,id = 2 这条数据无法被增量捕获,无法同步到磐维目标库,丢失。
发现:场景1会导致全量结束 到 增量拉起的这段时间范围内的业务数据丢失。
场景2:详细过程
1、模拟繁忙业务写入:实现每 0.1 秒向 MySQL 的 tasks 表中插入一条数据,表结构包含自增主键 id、varchar 类型的 name 和 int 类型的 age。
#!/bin/bash
# ===================== 配置项(请根据你的实际环境修改)=====================
MYSQL_USER="root" # MySQL用户名
MYSQL_PASSWORD="******" # MySQL密码
MYSQL_HOST="127.0.0.1" # MySQL主机地址(本地填localhost)
MYSQL_PORT="3306" # MySQL端口
MYSQL_DB="test" # 存放tasks表的数据库名
INTERVAL=0.1 # 插入间隔(秒)
# ===========================================================================
# 检查mysql命令是否存在
if ! command -v mysql &> /dev/null; then
echo "错误:未找到mysql命令,请确保已安装MySQL客户端并配置环境变量"
exit 1
fi
# 循环插入数据
echo "开始向tasks表插入数据,间隔${INTERVAL}秒,按Ctrl+C停止..."
while true; do
# 生成随机name(由字母和数字组成,长度1-10)
# 使用date +%s%N获取纳秒级时间戳,结合md5sum生成随机字符串,再截取1-10位
RANDOM_NAME=$(date +%s%N | md5sum | head -c $((RANDOM % 10 + 1)))
# 生成随机age(1-100的整数)
RANDOM_AGE=$((RANDOM % 100 + 1))
# 执行MySQL插入语句
mysql -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" -D"${MYSQL_DB}" -e "INSERT INTO tasks(name, age) VALUES ('${RANDOM_NAME}', ${RANDOM_AGE});" 2>/dev/null
# 检查插入是否成功
if [ $? -eq 0 ]; then
echo "插入成功:name=${RANDOM_NAME}, age=${RANDOM_AGE}"
else
echo "插入失败:name=${RANDOM_NAME}, age=${RANDOM_AGE}"
fi
# 间隔0.1秒(sleep命令支持小数)
sleep ${INTERVAL}
done

2、运行"库表结构"迁移
对比两端数据,如下:
3、运行"全量数据","增量数据"一次性勾选;
任务已处于运行中:
4、停止业务,验证是否丢失数据
把MySQL端的脚本停止掉:
查看两端的数据:
也可以直接运行全量校验:

发现:场景2不会导致全量结束 到 增量拉起的这段时间范围内的业务数据丢失,因为起点就是全量启动的那个时刻。
结论和建议
通常情况下,如果业务可以停止,则可以在全量做完后进行全量校验,如果没问题,再拉起增量;
如果业务没法停下来做全量校验的话,那就先DDL迁移成功后再一起勾选"全量数据",“增量数据”,最后运行。但场景2的前提条件是全量DDL、DATA迁移没问题才行,建议多测试几遍全量迁移,处理好全部报错后再尝试场景2的迁移。




