# **背景**
Amazon Database Migration Service (Amazon DMS) 是一项 Web 服务,您可以使用此服务将本地部署的数据库、位于 Amazon Relational Database Service ([Amazon RDS](https://aws.amazon.com/cn/rds/?trk=cndc-detail)) 数据库实例上的数据库或位于 Amazon Elastic Compute Cloud (Amazon EC2) 实例上的数据库中的数据迁移到 Amazon 服务上的数据库。这些服务可以包括 [Amazon RDS](https://aws.amazon.com/cn/rds/?trk=cndc-detail) 上的数据库或 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例上的数据库。您还可以将数据库从 Amazon 服务迁移到本地部署数据库。您可在使用相同数据库引擎的源和目标终端节点之间迁移,例如从 Oracle 数据库到 Oracle 数据库。也可在使用不同数据库引擎的源和目标终端节点之间迁移,例如从 Oracle 数据库到 PostgreSQL 数据库。
本篇文章将介绍在使用 Amazon DMS 进行数据迁移过程中的实践。通过对失败的 Amazon DMS 任务进行邮件告警并无限次尝试自动恢复,提高任务可用性、降低数据延迟风险及人工修复成本。通过对持续迁移的 MS SQL Server 源表临时删除发布(或禁用 CDC),实现用户对数据归档或截断的需求,降低源表的维护成本。
## **Amazon DMS 任务失败自动尝试恢复**
Amazon DMS 任务失败的原因主要有如下:
1、源数据库类故障(包括数据库服务中断、网络通信故障)
2、数据类错误,如转换错误、截断等
对于因源数据库故障导致的 Amazon DMS 任务失败,可以使用 [Amazon EventBridge](https://aws.amazon.com/cn/eventbridge/?trk=cndc-detail) 接收 Amazon DMS 任务事件(需升级 Amazon DMS 复制实例到3.4.6或更高版本),并与预先定义的 Event Pattern 进行匹配。如果匹配,使用 [Amazon Simple Notification Service](https://aws.amazon.com/cn/sns/?trk=cndc-detail) ([Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail)) 提供通知服务(比如邮件告警),同时发送事件到 Amazon Step Functions 状态机,自动尝试对 Amazon DMS 任务恢复。
下面架构图展示了方案架构设计:
![image.png](https://dev-media.amazoncloud.cn/617cdd59f3c2446f99738ce23c32e47a_image.png "image.png")
1、[Amazon EventBridge](https://aws.amazon.com/cn/eventbridge/?trk=cndc-detail) 从 Amazon DMS 接收事件(任务或复制实例)
2、对于匹配预先定义的 Event Pattern 的事件,使用 [Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail) 通知服务以邮件进行告警
3、对于匹配预先定义的 Event Pattern 的事件,使用 Amazon Step Functions 状态机尝试恢复任务运行
下面将详细介绍 EventBridge 规则配置、状态机流程和代码示例。
[Amazon EventBridge](https://aws.amazon.com/cn/eventbridge/?trk=cndc-detail) Event Pattern 定义如下:
```
{
"source": ["aws.dms"],
"resources": ["your-task-arn"],
"detail": {
"type": ["REPLICATION_TASK"],
"category": ["Failure", "StateChange"],
"eventType": ["REPLICATION_TASK_FAILED", "REPLICATION_TASK_STOPPED"]
}
}
```
Amazon Step Functions 状态机图如下:
```
{
"Comment": "A description of my state machine",
"StartAt": "检查DMS任务状态",
"States": {
"检查DMS任务状态": {
"Type": "Task",
"Next": "任务状态判断和处理",
"Parameters": {
"Filters": [
{
"Name": "replication-task-arn",
"Values.\$": "\$.replication-task-arn"
}
]
},
"Resource": "arn:aws-cn:states:::aws-sdk:databasemigration:describeReplicationTasks",
"ResultSelector": {
"ReplicationTasks.\$": "\$.ReplicationTasks"
},
```
完善任务 arn 使用 Amazon Lambda 函数将 Amazon DMS 任务的 arn 转化为数组,示例代码如下:
```
\$ helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
\$ helm repo update
\$ helm upgrade -i nvdp nvdp/nvidia-device-plugin \\
--namespace nvidia-device-plugin \\
--create-namespace -f nvdp.yaml
```
## **Amazon DMS 任务对源数据归档的支持**
用户在使用 Amazon DMS 对源 MS SQL Server 数据库表数据进行持续迁移到 Amazon 服务上的数据库(包括 [Amazon RDS](https://aws.amazon.com/cn/rds/?trk=cndc-detail) 上的数据库或 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例上的数据库)的过程中,对于有大量数据的源表(比如机器设备生成的数据、日志数据等,每日增量数千万条,大小数十个 GB 左右),因源 MS SQL Server 数据库存储容量限制或内部策略,需要每日对前一日表数据进行归档或截断。
对于处于持续迁移中的 MS SQL Server 源表,在进行归档(重命名、交换分区)或截断操作时存在一些限制。
下面是两种解决方案介绍,操作期间无需对 Amazon DMS 任务进行任何修改:
1、使用 insert into…select…配合 delete 方案实现对 MS SQL Server 源表数据归档。该方案中因 delete 操作是按行加锁并执行删除,性能较低,且 delete 操作产生的事务日志也会被应用到迁移目的地 Amazon 服务上的数据库中。
2、在 MS SQL Server 源表上临时删除发布或禁用 CDC(基于不同源表类型选择),对源表交换分区或截断,最后重新添加发布或启用 CDC。该方案直接对源表元数据操作,提高了数据归档或截断性能,对迁移目的地 Amazon 服务上的数据库数据无任何影响。通过将所有操作置于事务中,避免操作期间新增数据无法被迁移。
下面是对方案2的详细介绍:
对于有主键的源表,使用 MS-Replication 进行数据持续迁移,可按如下步骤进行数据分区切换或截断操作,将相关操作置于事务中。如下示例脚本:
1、显示开启事务
`BEGIN TRAN`
2、删除 article
`exec sp_droparticle @publication = N'pub-testrepl-repl', @article = N'TestTable', @force_invalidate_snapshot = 1`
3、归档或截断数据表
`ALTER TABLE dbo.TestTable SWITCH TO dbo.TestTable_BAK;`
或者如果历史数据不再需要,直接截断即可。
`TRUNCATE TABLE dbo.TestTable`
4、添加 article
```
exec sp_addarticle @publication = N'pub-testrepl-repl', @article = N'TestTable', @source_owner = N'dbo', @source_object = N'TestTable', @type = N'logbased', @description = null, @creation_script = null, @pre_creation_cmd = N'drop', @schema_option = 0x000000000803509F, @identityrangemanagementoption = N'manual', @destination_table = N'TestTable', @destination_owner = N'dbo', @vertical_partition = N'false', @ins_cmd = N'CALL sp_MSins_dboTestTable', @del_cmd = N'CALL sp_MSdel_dboTestTable', @upd_cmd = N'SCALL sp_MSupd_dboTestTable'
```
5、提交事务
`COMMIT TRAN`
对于没有主键,有唯一索引的源表,可直接进行交换分区以将数据进行归档,但是不能直接进行截断。
对于没有主键,有唯一索引的源表,需要进行截断时,可先在表上禁用 CDC,其次执行截断,最后在表上开启 CDC,将相关操作置于事务中。如下示例脚本:
1、显示开启事务
`BEGIN TRAN`
2、禁用 CDC
`EXECUTE sys.sp_cdc_disable_table @source_schema = N'dbo',@source_name = N'TestTable',@capture_instance = N'dbo_TestTable';`
3、截断数据表
`TRUNCATE TABLE dbo.TestTable;`
4、启用 CDC
`EXEC sys.sp_cdc_enable_table @source_schema = N'dbo',@source_name = N'TestTable',@index_name = N'AK_ID',@role_name = NULL,@supports_net_changes = 1;`
5、提交事务
`COMMIT TRAN`
对于没有主键及唯一索引的源表,可直接进行交换分区以将数据进行归档,但是不能直接进行截断。
对于没有主键及唯一索引的源表,需要进行截断时,可先在表上禁用 CDC,其次执行截断,最后在表上启用 CDC,将相关操作置于事务中。如下示例脚本:
1、显示开启事务
`BEGIN TRAN`
2、禁用 CDC
`EXECUTE sys.sp_cdc_disable_table @source_schema = N'dbo',@source_name = N'TestTable',@capture_instance = N'dbo_TestTable';`
3、截断数据表
`TRUNCATE TABLE dbo.TestTable;`
4、启用 CDC
`EXEC sys.sp_cdc_enable_table @source_schema = N'dbo',@source_name = N'TestTable',@role_name = NULL`
5、提交事务
`COMMIT TRAN`
# **总结**
本篇文章总结了在使用 Amazon DMS 进行数据持续迁移过程中的实践。在提高任务可用性方面,对源数据库类故障导致的 DMS 任务失败,通过对 Amazon DMS 失败任务邮件告警及无限次尝试自动恢复,降低数据迁移延迟风险和人工修复成本。对于数据类错误,除了配置错误处理任务设置外,仍需用户响应告警邮件并修复错误。同时,对于来自 MS SQL Server 的大表数据持续迁移,在数据归档或截断的需求方面,提出了解决方案。
配置错误处理任务设置:
https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Tasks.CustomizingTasks.TaskSettings.ErrorHandling.html
**本篇作者**
![image.png](https://dev-media.amazoncloud.cn/671d8d9403124f8d985b3b446197da43_image.png "image.png")
**Chris Fan**
*亚马逊云科技专业服务团队大数据顾问。他帮助客户设计和构建现代化数据平台解决方案,提供专家技术咨询和基于亚马逊云科技平台实施服务。在数据平台架构、处理、管道、建模等方面拥有丰富经验。*