

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用微软 SQL Server 数据库作为来源 AWS DMS
<a name="CHAP_Source.SQLServer"></a>

使用迁移一个或多个 Microsoft SQL Server 数据库中的数据 AWS DMS。使用 SQL Server 数据库作为源，您可以将数据迁移到另一个 SQL Server 数据库或其他 AWS DMS 支持的数据库中。

有关 AWS DMS 支持作为源的 SQL Server 版本的信息，请参见[的来源 AWS DMS](CHAP_Introduction.Sources.md)。

源 SQL Server 数据库可安装在您网络中的任意计算机上。在与 AWS DMS一起使用时，需要 SQL Server 账户，该账户对源数据库具有与选定任务类型相对应的访问权限。有关更多信息，请参阅 [SQL Server 任务权限](#CHAP_Source.SQLServer.Permissions)。

AWS DMS 支持从 SQL Server 的命名实例迁移数据。当您创建源终端节点时，您可以在服务器名称中使用以下表示法。

```
IPAddress\InstanceName
```

例如，以下是正确的源终端节点服务器名称。在这里，名称的第一部分是服务器的 IP 地址，第二部分是 SQL Server 实例名称（在本示例中为 SQLTest）。

```
10.0.0.25\SQLTest
```

此外，请获取您的命名 SQL Server 实例监听的端口号，然后使用它来配置您的 AWS DMS 源端点。

**注意**  
端口 1433 是 Microsoft SQL Server 的默认端口。但是，也经常使用每次启动 SQL Server 时更改的动态端口，以及用于通过防火墙连接到 SQL Server 的特定静态端口号。因此，在创建 AWS DMS 源端点时，您想知道命名的 SQL Server 实例的实际端口号。

可以使用 SSL 加密 SQL Server 终端节点与复制实例之间的连接。有关将 SSL 用于 SQL Server 终端节点的更多信息，请参阅[将 SSL 与 AWS Database Migration Service](CHAP_Security.SSL.md)。

您可以使用 CDC 从 SQL Server 数据库进行持续迁移。有关为 CDC 配置源 SQL Server 数据库的信息，请参阅[捕获数据更改，以便从 SQL Server 进行持续复制](CHAP_Source.SQLServer.CDC.md)。

有关使用 SQL Server 源数据库和的更多详细信息 AWS DMS，请参阅以下内容。

**Topics**
+ [使用 SQL Server 作为源代码的限制 AWS DMS](#CHAP_Source.SQLServer.Limitations)
+ [SQL Server 任务权限](#CHAP_Source.SQLServer.Permissions)
+ [在 SQL Server 源中使用持续复制（CDC）的先决条件](#CHAP_Source.SQLServer.Prerequisites)
+ [支持的 SQL Server 压缩方法](#CHAP_Source.SQLServer.Compression)
+ [使用自行管理的 SQL Server AlwaysOn 可用性组](#CHAP_Source.SQLServer.AlwaysOn)
+ [使用 SQL Server 作为源时的端点设置 AWS DMS](#CHAP_Source.SQLServer.ConnectionAttrib)
+ [SQL Server 的源数据类型](#CHAP_Source.SQLServer.DataTypes)
+ [捕获数据更改，以便从 SQL Server 进行持续复制](CHAP_Source.SQLServer.CDC.md)

## 使用 SQL Server 作为源代码的限制 AWS DMS
<a name="CHAP_Source.SQLServer.Limitations"></a>

将 SQL Server 数据库作为 AWS DMS源时，存在以下限制：
+ 列的身份属性不迁移到目标数据库列。
+ SQL Server 端点不支持使用包含稀疏列的表。
+ 不支持 Windows 身份验证。
+ 不复制对 SQL Server 中计算字段的更改。
+ 不支持临时表。
+ 不支持 SQL Server 分区切换。
+ 使用 WRITETEXT 和 UPDATETEXT 实用程序时， AWS DMS 不会捕获应用于源数据库的事件。
+ 不支持以下数据操作语言（DML）模式。

  ```
  SELECT * INTO new_table FROM existing_table
  ```
+ 在将 SQL Server 作为源时，不支持列级别加密。
+ AWS DMS 不支持将 SQL Server 2008 或 SQL Server 2008 R2 作为来源进行服务器级审计。这是因为 SQL Server 2008 和 2008 R2 存在已知问题。例如，运行以下命令会 AWS DMS 导致失败。

  ```
  USE [master]
  GO 
  ALTER SERVER AUDIT [my_audit_test-20140710] WITH (STATE=on)
  GO
  ```
+ 使用 SQL Server 作为源时，在完全 Lob 模式下不支持几何列和地理列。应改用受限 LOB 模式，或将 `InlineLobMaxSize` 任务设置设为使用内联 LOB 模式。
+ 在复制任务中使用 Microsoft SQL Server 源数据库时，如果删除该任务，则不会删除 SQL Server Replication Publisher 定义。Microsoft SQL Server 系统管理员必须从 Microsoft SQL Server 删除这些定义。
+ 仅限满载的任务支持从架构绑定和 non-schema-bound视图迁移数据。
+ 不支持使用 sp\$1rename 重命名表（例如，`sp_rename 'Sales.SalesRegion', 'SalesReg;)`
+ 不支持使用 sp\$1rename 重命名列（例如，`sp_rename 'Sales.Sales.Region', 'RegID', 'COLUMN';`）
+ AWS DMS 不支持更改处理以设置和取消设置列默认值（使用带`ALTER TABLE`语`ALTER COLUMN SET DEFAULT`句的子句）。
+ AWS DMS 不支持通过更改处理来设置列可为空性（使用带`ALTER TABLE`语`ALTER COLUMN [SET|DROP] NOT NULL`句的子句）。
+ 在 SQL Server 2012 和 SQL Server 2014 中，将 DMS 复制与可用性组一起使用时，无法将分发数据库放入可用性组。SQL 2016 支持将分发数据库放入可用性组中，但合并、双向或 peer-to-peer复制拓扑中使用的分布数据库除外。
+ 对于分区表， AWS DMS 不支持为每个分区设置不同的数据压缩设置。
+ 将值插入 SQL Server 空间数据类型（GEOGRAPHY 和 GEOMETRY）时，可以忽略空间参考系统标识符（SRID）属性或指定其他数字。复制具有空间数据类型的表时， AWS DMS 将 SRID 替换为默认 SRID（几何为 0，地理位置为 4326）。
+ 如果您的数据库未配置 MS-REPLICATION 或 MS-CDC，您仍然可以捕获没有主键的表，但只能捕获 INSERT/DELETE DML 事件。将忽略 UPDATE 和 TRUNCATE TABLE 事件。
+ 不支持列存储索引。
+ 不支持内存优化表（使用内存中 OLTP）。
+ 当复制主键由多个列组成的表时，不支持在完全加载期间更新主键列。
+ 不支持延迟的耐久性。
+ 由于 RDS 执行备份的方式，`readBackupOnly=true` 端点设置（额外连接属性）在 RDS for SQL Server 源实例上不起作用。
+ `EXCLUSIVE_AUTOMATIC_TRUNCATION` 在 Amazon RDS SQL Server 源实例上不起作用，因为 RDS 用户无权运行 SQL Server 存储过程 `sp_repldone`。
+ AWS DMS 不捕获截断命令。
+ AWS DMS 不支持从开启了加速数据库恢复 (ADR) 的数据库进行复制。
+ AWS DMS 不支持在单个事务中捕获数据定义语言 (DDL) 和数据操作语言 (DML) 语句。
+ AWS DMS 不支持复制数据层应用程序包 (DACPAC)。
+ 当您将更改应用于目标数据库时，涉及主键或唯一索引并更新多个数据行的 UPDATE 语句可能会导致冲突。例如，当目标数据库通过 INSERT 和 DELETE 语句而不是单个 UPDATE 语句应用更新时，可能会发生这种情况。在批量优化应用模式中，该表可能会被忽略。在事务应用模式下，UPDATE 操作可能会导致违反约束。要避免出现此问题，请重新加载相关表。或者，在 Apply Exceptions 控制表（`dmslogs.awsdms_apply_exceptions`）中找到有问题的记录，然后在目标数据库中手动对其进行编辑。有关更多信息，请参阅 [更改处理优化设置](CHAP_Tasks.CustomizingTasks.TaskSettings.ChangeProcessingTuning.md)。
+ AWS DMS 不支持表和架构的复制，其中名称包含以下集合中的特殊字符。

  `\\ -- \n \" \b \r ' \t ;` 
+ 不支持数据屏蔽。 AWS DMS 在不进行屏蔽的情况下迁移被屏蔽的数据。
+ AWS DMS 最多复制 32,767 个带主键的表，每个表最多可复制 1,000 个列。这是因为 AWS DMS 会为每个复制的表创建一个 SQL Server 复制文章，而 SQL Server 复制文章有这些限制。
+ 使用更改数据捕获（CDC）时，必须将构成唯一索引的所有列定义为 `NOT NULL`。如果不满足此要求，将导致出现 SQL Server 系统错误 22838。
+ 如果 SQL Server 将事件从活动事务日志归档到备份日志，或者将其从活动事务日志中截断，则可能丢失事件。

访问备份事务日志时适用以下限制：
+ 不支持加密的备份。
+ 不支持存储在 URL 或 Windows Azure 上的备份。
+ AWS DMS doe snot 支持在文件级别直接处理备用共享文件夹中的事务日志备份。
+ 对于除适用于微软 SQL Server 的 Amazon RDS 以外的 Cloud SQL Server 源，仅 AWS DMS 支持使用活动事务日志进行持续复制 (CDC)。您不能将备份日志用于 CDC。如果 SQL Server 将事件从活动事务日志归档到备份日志，或者在 DMS 读取之前将事件从活动事务日志中截断，则可能丢失事件。
+ 对于适用于 Microsoft SQL Server 的 Amazon RDS 源， AWS DMS 3.5.2 及更低版本仅支持使用活动事务日志进行持续复制 (CDC)，因为 DMS 无法通过 CDC 访问备份日志。如果 RDS for SQL Server 将事件从活动事务日志归档到备份日志，或者在 DMS 读取之前将事件从活动事务日志中截断，则可能丢失事件。此限制不适用于 3.5.3 及更高 AWS DMS 版本。
+ AWS DMS 不支持将适用于 SQL Server 的 Amazon RDS 代理的 CDC 作为来源。
+ 如果 SQL Server 源在完全加载任务期间不可用，则即使数据迁移仍未完成， AWS DMS 也可能会在多次尝试重新连接后将任务标记为已完成。在这种情况下，目标表仅包含连接中断之前迁移的记录，这可能会在源系统和目标系统之间造成数据不一致。为确保数据的完整性，您必须完全重新启动满载任务，或者重新加载受连接中断影响的特定表。

## SQL Server 任务权限
<a name="CHAP_Source.SQLServer.Permissions"></a>

**Topics**
+ [仅完全加载任务的权限](#CHAP_Source.SQLServer.Permissions.FullLoad)
+ [持续复制任务权限](#CHAP_Source.SQLServer.Permissions.Ongoing)

### 仅完全加载任务的权限
<a name="CHAP_Source.SQLServer.Permissions.FullLoad"></a>

要执行仅完全加载的任务，需要以下权限。请注意， AWS DMS 不会创建 `dms_user` 登录角色。有关为 SQL Server 创建登录的信息，请参阅 *Microsoft 文档*中的[创建数据库用户](https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-user?view=sql-server-ver16)主题。

```
USE db_name;
                
                CREATE USER dms_user FOR LOGIN dms_user; 
                ALTER ROLE [db_datareader] ADD MEMBER dms_user; 
                GRANT VIEW DATABASE STATE to dms_user;
                GRANT VIEW DEFINITION to dms_user;
                
                USE master;
                
                GRANT VIEW SERVER STATE TO dms_user;
```

### 持续复制任务权限
<a name="CHAP_Source.SQLServer.Permissions.Ongoing"></a>

无论是否使用 `sysadmin` 角色，都可以使用 DMS 将自管理 SQL Server 实例配置为持续复制。对于无法授予 `sysadmin` 角色的 SQL Server 实例，请确保 DMS 用户具有如下所述的权限。

**从自管理 SQL Server 数据库进行持续复制所需的设置权限**

1. 使用 SQL Server Management Studio（SSMS）或如前面的[仅完全加载任务的权限](#CHAP_Source.SQLServer.Permissions.FullLoad)中所述，创建采用密码身份验证的新 SQL Server 账户，例如 `self_managed_user`。

1. 运行以下 `GRANT` 命令：

   ```
   GRANT VIEW SERVER STATE TO self_managed_user;
   
   USE msdb;
       GRANT SELECT ON msdb.dbo.backupset TO self_managed_user;
       GRANT SELECT ON msdb.dbo.backupmediafamily TO self_managed_user;
       GRANT SELECT ON msdb.dbo.backupfile TO self_managed_user;
       
   USE db_name;
       CREATE USER self_managed_user FOR LOGIN self_managed_user;
       ALTER ROLE [db_owner] ADD MEMBER self_managed_user;
       GRANT VIEW DEFINITION to self_managed_user;
   ```

1. 除上述权限外，用户还需要以下权限之一：
   + 用户必须是 `sysadmin` 固定服务器角色的成员
   + 配置和权限如[在可用性组环境中的 SQL Server 上设置持续复制：无 sysadmin 角色](CHAP_Source.SQLServer.CDC.md#CHAP_SupportScripts.SQLServer.ag)或[在独立 SQL Server 上设置持续复制：不使用 sysadmin 角色](CHAP_Source.SQLServer.CDC.md#CHAP_SupportScripts.SQLServer.standalone)中所述，具体取决于您的源配置。

#### 从云 SQL Server 数据库进行持续复制所需的设置权限
<a name="CHAP_Source.SQLServer.Permissions.Cloud"></a>

云托管的 SQL Server 实例是在 Amazon RDS for Microsoft SQL Server、Azure SQL 托管实例或 DMS 支持的任何其他托管云 SQL Server 实例上运行的实例。

使用 SQL Server Management Studio（SSMS）或如前面的[仅完全加载任务的权限](#CHAP_Source.SQLServer.Permissions.FullLoad)中所述，创建采用密码身份验证的新 SQL Server 账户，例如 `rds_user`。

运行以下授权命令。

```
GRANT VIEW SERVER STATE TO rds_user;
```

对于 Amazon RDS for Microsoft SQL Server 源，DMS 版本 3.5.3 及更高版本支持从事务日志备份中读取。为确保 DMS 能够访问日志备份，除上述权限外，还要授予 `master` 用户权限或 RDS SQL Server 源上的以下权限：

```
USE msdb;
    GRANT EXEC ON msdb.dbo.rds_dms_tlog_download TO rds_user;
    GRANT EXEC ON msdb.dbo.rds_dms_tlog_read TO rds_user;
    GRANT EXEC ON msdb.dbo.rds_dms_tlog_list_current_lsn TO rds_user;
    GRANT EXEC ON msdb.dbo.rds_task_status TO rds_user;
    
USE db_name;
    CREATE USER rds_user FOR LOGIN rds_user;
    ALTER ROLE [db_owner] ADD MEMBER rds_user;
    GRANT VIEW DEFINITION to rds_user;
```

对于 Amazon Azure SQL 托管实例，请授予以下权限：

```
GRANT SELECT ON msdb.dbo.backupset TO rds_user;
GRANT SELECT ON msdb.dbo.backupmediafamily TO rds_user;
GRANT SELECT ON msdb.dbo.backupfile TO rds_user;
```

## 在 SQL Server 源中使用持续复制（CDC）的先决条件
<a name="CHAP_Source.SQLServer.Prerequisites"></a>

您可以针对本地或 Amazon EC2 上的自管理 SQL Server 数据库、诸如 Amazon RDS 之类的云数据库或者 Microsoft Azure SQL 托管实例使用持续复制（更改数据捕获（CDC））。

尤其在对作为 AWS DMS源的 SQL Server 数据库使用持续复制时，存在以下要求：
+ 必须配置 SQL Server 进行完整备份，并且您必须在开始复制数据之前先进行一次备份。
+ 恢复模式必须设置为 **Bulk logged** 或 **Full**。
+ 不支持 SQL Server 备份到多个磁盘。如果将备份定义为将数据库备份写入不同磁盘上的多个文件，则 AWS DMS 无法读取数据， AWS DMS 任务将失败。
+ 对于自管理 SQL Server 源，在您删除任务时，DMS CDC 任务中使用的源数据库的 SQL Server Replication Publisher 定义不会被删除。SQL Server 系统管理员必须从 SQL Server 删除自管理源的这些定义。
+ 在 CDC 期间， AWS DMS 需要查找 SQL Server 事务日志备份才能读取更改。 AWS DMS 不支持使用*非*本机格式的第三方备份软件创建的 SQL Server 事务日志备份。要支持*采用*本机格式并且使用第三方备份软件创建的事务日志备份，请将 `use3rdPartyBackupDevice=Y` 连接属性添加到源端点。
+ 对于自管理 SQL Server 源，请注意，在新创建的表发布前，SQL Server 不会捕获对它们的更改。将表添加到 SQL Server 源时，会 AWS DMS 管理发布的创建。但是，该过程可能需要几分钟时间。不会将在该延迟期间对新创建的表执行的操作捕获或复制到目标中。
+ AWS DMS 更改数据捕获需要在 SQL Server 中开启完整的事务日志记录。要在 SQL Server 中启用完整事务日志记录，请启用 MS-REPLICATION 或 CHANGE DATA CAPTURE（CDC）。
+ 在 MS CDC 捕获作业处理这些更改之前，SQL Server *tlog* 条目不会被标记为可重复使用。
+ 内存优化表上不支持 CDC 操作。该限制适用于 SQL Server 2014（在此版本中首次引入该功能）及更高版本。
+ AWS DMS 默认情况下，更改数据捕获需要将 Amazon EC2 或 On-Prem SQL 服务器上的分布数据库作为源。因此，请确保在为带有主键的表配置 MS 复制时已激活分发服务器。

## 支持的 SQL Server 压缩方法
<a name="CHAP_Source.SQLServer.Compression"></a>

请注意以下有关 AWS DMS支持的 SQL Server 压缩方法的内容：
+ AWS DMS 在 SQL Server 版本 2008 及更高版本中支持 Row/Page 压缩。
+ AWS DMS 不支持 Vardecimal 存储格式。
+ AWS DMS 不支持稀疏列和列结构压缩。

## 使用自行管理的 SQL Server AlwaysOn 可用性组
<a name="CHAP_Source.SQLServer.AlwaysOn"></a>

SQL Server Always On 可用性组配有高可用性和灾难恢复解决方案，提供数据库镜像的企业级替代功能。

在中 AWS DMS，您可以从单个主可用性组或辅助可用性组副本迁移更改。

### 使用主可用性组副本
<a name="CHAP_Source.SQLServer.AlwaysOn.Primary"></a>

 

**要在中使用主可用性组作为源 AWS DMS，请执行以下操作：**

1. 为可用性副本中的所有 SQL Server 实例启用分发选项。有关更多信息，请参阅 [在自管理 SQL Server 上设置持续复制](CHAP_Source.SQLServer.CDC.md#CHAP_Source.SQLServer.CDC.MSCDC)。

1. 在 AWS DMS 控制台中，打开 SQL Server 源数据库设置。对于**服务器名称**，请指定为可用性组侦听器配置的域名服务（DNS）名称或 IP 地址。

首次启动 AWS DMS 任务时，可能需要比平时更长的时间才能启动。这种缓慢是因为可用性组服务器正在复制表项目的创建。

### 使用辅助可用性组副本
<a name="CHAP_Source.SQLServer.AlwaysOn.Secondary"></a>

**要在中使用辅助可用性组作为源 AWS DMS，请执行以下操作：**

1. 使用与 AWS DMS 源端点用户相同的凭据来连接各个副本。

1. 确保您的 AWS DMS 复制实例可以解析所有现有副本的 DNS 名称并连接到它们。您可以使用以下 SQL 查询来获取所有副本的 DNS 名称。

   ```
   select ar.replica_server_name, ar.endpoint_url from sys.availability_replicas ar
   JOIN sys.availability_databases_cluster adc
   ON adc.group_id = ar.group_id AND adc.database_name = '<source_database_name>';
   ```

1. 创建源端点时，请为端点的**服务器名称**或端点密钥的**服务器地址**指定可用性组侦听器的 DNS 名称。有关可用性组侦听器的更多信息，请参阅 SQL Server 文档中的[可用性组侦听器是什么？](https://docs.microsoft.com/en-us/sql/database-engine/availability-groups/windows/availability-group-listener-overview?view=sql-server-ver15)。

   您可以使用公有 DNS 服务器或本地 DNS 服务器来解析可用性组侦听器、主副本和辅助副本。要使用本地 DNS 服务器，请配置 Amazon Route 53 Resolver。有关更多信息，请参阅 [使用您自己的本地名称服务器](CHAP_BestPractices.md#CHAP_BestPractices.Rte53DNSResolver)。

1. 请将以下额外连接属性添加到您的源端点。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/dms/latest/userguide/CHAP_Source.SQLServer.html)

1. 在您可用性组的所有副本上启用分发选项。将所有节点添加到分发服务器列表中。有关更多信息，请参阅 [设置分发](CHAP_Source.SQLServer.CDC.md#CHAP_Source.SQLServer.CDC.MSCDC.Setup)。

1. 对主读写副本运行以下查询以启用数据库的发布。您只对数据库运行一次此查询。

   ```
   sp_replicationdboption @dbname = N'<source DB name>', @optname = N'publish', @value = N'true';
   ```



#### 限制
<a name="CHAP_Source.SQLServer.AlwaysOn.Secondary.limitations"></a>

以下是使用辅助可用性组副本的限制：
+ AWS DMS 使用只读可用性组副本作为源时，不支持 Safeguard。有关更多信息，请参阅 [使用 SQL Server 作为源时的端点设置 AWS DMS](#CHAP_Source.SQLServer.ConnectionAttrib)。
+ AWS DMS 使用只读可用性组副本作为源时，不支持`setUpMsCdcForTables`额外的连接属性。有关更多信息，请参阅 [使用 SQL Server 作为源时的端点设置 AWS DMS](#CHAP_Source.SQLServer.ConnectionAttrib)。
+ AWS DMS 从版本 3.4.7 开始，可以使用自我管理的辅助可用性组副本作为源数据库，用于持续复制（更改数据捕获或 CDC）。不支持云 SQL Server 多可用区只读副本。如果您使用早期版本的 AWS DMS，请确保使用主可用性组副本作为 CDC 的源数据库。

#### 失效转移到其他节点
<a name="CHAP_Source.SQLServer.AlwaysOn.Secondary.failover"></a>

如果您将终端节点的`ApplicationIntent`额外连接属性设置为`ReadOnly`，则您的 AWS DMS 任务将连接到只读路由优先级最高的只读节点。当优先级最高的只读节点不可用时，它会失效转移到可用性组中的其他只读节点。如果未设置`ApplicationIntent`，则您的 AWS DMS 任务将仅连接到可用性组中的主（读/写）节点。

## 使用 SQL Server 作为源时的端点设置 AWS DMS
<a name="CHAP_Source.SQLServer.ConnectionAttrib"></a>

您可以使用端点设置来配置 SQL Server 源数据库，这与使用额外连接属性类似。您可以在使用 AWS DMS 控制台创建源端点时指定设置，或者使用中带有 `--microsoft-sql-server-settings '{"EndpointSetting": "value", ...}'` JSON 语法的`create-endpoint`[AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/dms/index.html)命令来指定设置。

下表显示了将 SQL Server 作为源时您可以使用的端点设置。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/dms/latest/userguide/CHAP_Source.SQLServer.html)

## SQL Server 的源数据类型
<a name="CHAP_Source.SQLServer.DataTypes"></a>

使用 SQL Server 作为源的数据迁移 AWS DMS 支持大多数 SQL Server 数据类型。下表显示了使用时支持的 SQL Server 源数据类型 AWS DMS 以及 AWS DMS 数据类型的默认映射。

有关如何查看目标中映射的数据类型的信息，请参阅有关所使用的目标终端节点的部分。

有关 AWS DMS 数据类型的更多信息，请参见[AWS Database Migration Service 的数据类型](CHAP_Reference.DataTypes.md)。


|  SQL Server 数据类型  |  AWS DMS 数据类型  | 
| --- | --- | 
|  BIGINT  |  INT8  | 
|  BIT  |  BOOLEAN  | 
|  DECIMAL  |  NUMERIC  | 
|  INT  |  INT4  | 
|  MONEY  |  NUMERIC  | 
|  NUMERIC (p,s)  |  NUMERIC   | 
|  SMALLINT  |  INT2  | 
|  SMALLMONEY  |  NUMERIC  | 
|  TINYINT  |  UINT1  | 
|  REAL  |  REAL4  | 
|  FLOAT  |  REAL8  | 
|  DATETIME  |  DATETIME  | 
|  DATETIME2 （SQL Server 2008 及更高版本）  |  DATETIME  | 
|  SMALLDATETIME  |  DATETIME  | 
|  DATE  |  DATE  | 
|  TIME  |  TIME  | 
|  DATETIMEOFFSET  |  WSTRING  | 
|  CHAR  |  string  | 
|  VARCHAR  |  string  | 
|  VARCHAR (max)  |  CLOB TEXT 要将此数据类型与一起使用 AWS DMS，必须为特定任务启用 CLOB 数据类型。 对于 SQL Server 表， AWS DMS 即使对于不更改 SQL Server 中 LOB 列值的 UPDATE 语句，也会更新目标中的 LOB 列。 在 CDC 期间，仅在包含主键的表中 AWS DMS 支持 CLOB 数据类型。  | 
|  NCHAR  |  WSTRING  | 
|  NVARCHAR (length)  |  WSTRING  | 
|  NVARCHAR (max)  |  NCLOB NTEXT 要将此数据类型与一起使用 AWS DMS，必须 SupportLobs 为特定任务启用使用。有关启用 Lob 支持的更多信息，请参阅[在任务中为源数据库设置 LOB 支持 AWS DMS](CHAP_Tasks.LOBSupport.md)。 对于 SQL Server 表， AWS DMS 即使对于不更改 SQL Server 中 LOB 列值的 UPDATE 语句，也会更新目标中的 LOB 列。 在 CDC 期间，仅在包含主键的表中 AWS DMS 支持 CLOB 数据类型。  | 
|  BINARY  |  BYTES  | 
|  VARBINARY  |  BYTES  | 
|  VARBINARY (max)  |  BLOB IMAGE 对于 SQL Server 表， AWS DMS 即使对于不更改 SQL Server 中 LOB 列值的 UPDATE 语句，也会更新目标中的 LOB 列。 要将此数据类型与一起使用 AWS DMS，必须允许将 BLOB 数据类型用于特定任务。 AWS DMS 仅在包含主键的表中支持 BLOB 数据类型。  | 
|  TIMESTAMP  |  BYTES  | 
|  UNIQUEIDENTIFIER  |  string  | 
|  HIERARCHYID   |  在复制到 SQL Server 目标终端节点时，使用 HIERARCHYID。 在复制到所有其他目标终端节点时，使用 WSTRING (250)。  | 
|  XML  |  NCLOB 对于 SQL Server 表， AWS DMS 即使对于不更改 SQL Server 中 LOB 列值的 UPDATE 语句，也会更新目标中的 LOB 列。 要将此数据类型与一起使用 AWS DMS，必须允许将 NCLOB 数据类型用于特定任务。 在 CDC 期间，仅在包含主键的表中 AWS DMS 支持 NCLOB 数据类型。  | 
|  GEOMETRY  |  在复制到支持此数据类型的目标终端节点时，使用 GEOMETRY。 在复制到不支持此数据类型的目标终端节点时，使用 CLOB。  | 
|  GEOGRAPHY  |  在复制到支持此数据类型的目标终端节点时，使用 GEOGRAPHY。 在复制到不支持此数据类型的目标终端节点时，使用 CLOB。  | 

AWS DMS 不支持包含以下数据类型的字段的表。
+ CURSOR
+ SQL\$1VARIANT
+ TABLE

**注意**  
根据用户定义的数据类型的基类型来支持这些类型。例如，基于 DATETIME 的用户定义的数据类型将作为 DATETIME 数据类型进行处理。

# 捕获数据更改，以便从 SQL Server 进行持续复制
<a name="CHAP_Source.SQLServer.CDC"></a>

本主题介绍如何在 SQL Server 源上设置 CDC 复制。

**Topics**
+ [捕获本地或 Amazon EC2 上的自管理 SQL Server 的数据更改](#CHAP_Source.SQLServer.CDC.Selfmanaged)
+ [在云 SQL Server 数据库实例上设置持续复制](#CHAP_Source.SQLServer.Configuration)

## 捕获本地或 Amazon EC2 上的自管理 SQL Server 的数据更改
<a name="CHAP_Source.SQLServer.CDC.Selfmanaged"></a>

要从源 Microsoft SQL Server 数据库中捕获更改，请确保该数据库已配置为进行完整备份。将数据库配置为完全恢复模式或批量日志记录模式。

对于自行管理的 SQL Server 源，请 AWS DMS 使用以下内容：

**MS-Replication**  
用于捕获带主键的表的更改。您可以通过向源 SQL Server 实例上的 AWS DMS 端点用户授予系统管理员权限来自动进行配置。或者，您可以按照本节中的步骤准备源代码并使用对端点不具有 sysadmin 权限的 AWS DMS 用户。

**MS-CDC**  
用于捕获不带主键的表的更改。MS-CDC 必须在数据库级别上启用，并且为各个表分别启用。

设置 SQL Server 数据库进行持续复制（CDC）时，可以执行下列操作之一：
+ 使用 sysadmin 角色设置持续复制。
+ 将持续复制设置为不使用 sysadmin 角色。

**注意**  
您可以使用以下脚本查找所有没有主键或唯一键的表：  

```
USE [DBname]
SELECT SCHEMA_NAME(schema_id) AS schema_name, name AS table_name
FROM sys.tables
WHERE OBJECTPROPERTY(object_id, 'TableHasPrimaryKey') = 0
        AND  OBJECTPROPERTY(object_id, 'TableHasUniqueCnst') = 0
ORDER BY schema_name, table_name;
```

### 在自管理 SQL Server 上设置持续复制
<a name="CHAP_Source.SQLServer.CDC.MSCDC"></a>

本部分包含有关使用或不使用 sysadmin 角色在自管理 SQL Server 上设置持续复制的信息。

**Topics**
+ [在自管理 SQL Server 上设置持续复制：使用 sysadmin 角色](#CHAP_Source.SQLServer.CDC.MSCDC.Sysadmin)
+ [在独立 SQL Server 上设置持续复制：不使用 sysadmin 角色](#CHAP_SupportScripts.SQLServer.standalone)
+ [在可用性组环境中的 SQL Server 上设置持续复制：无 sysadmin 角色](#CHAP_SupportScripts.SQLServer.ag)

#### 在自管理 SQL Server 上设置持续复制：使用 sysadmin 角色
<a name="CHAP_Source.SQLServer.CDC.MSCDC.Sysadmin"></a>

AWS DMS SQL Server 的持续复制对带主键的表使用本机 SQL Server 复制，对没有主键的表使用更改数据捕获 (CDC)。

在设置持续复制之前，请参阅[在 SQL Server 源中使用持续复制（CDC）的先决条件](CHAP_Source.SQLServer.md#CHAP_Source.SQLServer.Prerequisites)。

对于带有主键的表，通常 AWS DMS 可以在源上配置所需的工件。但对于自管理 SQL Server 源数据库实例，必须先手动配置 SQL Server 分发。执行此操作后，具有 sysadmin 权限的 AWS DMS 源用户可以自动为具有主键的表创建发布。

要检查是否已配置分发，请运行以下命令。

```
sp_get_distributor
```

如果列分发的结果是 `NULL`，则未配置分发。请使用以下过程设置分发。<a name="CHAP_Source.SQLServer.CDC.MSCDC.Setup"></a>

**设置分发**

1. 使用 SQL Server Management Studio（SSMS）工具连接到 SQL Server 源数据库。

1. 打开**复制**文件夹的上下文（右键单击）菜单，然后选择**配置分发**。此时将显示“配置分发向导”。

1. 按照向导输入默认值并创建分发。<a name="CHAP_Source.SQLServer.CDC.MSCDC.Setup.CDC"></a>

**设置 CDC**

AWS DMS 如果您不使用只读副本，3.4.7 及更高版本可以自动为您的数据库和所有表设置 MS CDC。要使用此功能，请将 `SetUpMsCdcForTables` ECA 设置为 true。有关的信息 ECAs，请参见[端点设置](CHAP_Source.SQLServer.md#CHAP_Source.SQLServer.ConnectionAttrib)。

对于 3.4.7 AWS DMS 之前的版本或作为源的只读副本，请执行以下步骤：

1. 对于无主键的表，请为数据库设置 MS-CDC。要执行此操作，请使用分配了 sysadmin 角色的账户，然后运行以下命令。

   ```
   use [DBname]
   EXEC sys.sp_cdc_enable_db
   ```

1. 接下来，为每个源表设置 MS-CDC。对于具有唯一键但没有主键的每个表，运行以下查询来设置 MS-CDC。

   ```
   exec sys.sp_cdc_enable_table
   @source_schema = N'schema_name',
   @source_name = N'table_name',
   @index_name = N'unique_index_name',
   @role_name = NULL,
   @supports_net_changes = 1
   GO
   ```

1. 对于没有主键或唯一键的每个表，运行以下查询来设置 MS-CDC。

   ```
   exec sys.sp_cdc_enable_table
   @source_schema = N'schema_name',
   @source_name = N'table_name',
   @role_name = NULL
   GO
   ```

有关为特定表设置 MS-CDC 的更多信息，请参阅 [ SQL Server 文档](https://msdn.microsoft.com/en-us/library/cc627369.aspx)。

#### 在独立 SQL Server 上设置持续复制：不使用 sysadmin 角色
<a name="CHAP_SupportScripts.SQLServer.standalone"></a>

本节介绍如何针对 SQL Server 数据库源设置不需要用户账户具有 sysadmin 权限的持续复制。

**注意**  
运行本节中的步骤后，非 sysadmin DMS 用户将有权执行以下操作：  
从联机事务日志文件中读取更改
通过访问磁盘从事务日志备份文件中读取更改
添加或更改 DMS 使用的发布内容
向发布内容中添加文章

1. 按照[捕获数据更改，以便从 SQL Server 进行持续复制](#CHAP_Source.SQLServer.CDC)中所述设置用于复制的 Microsoft SQL Server。

1. 在源数据库上启用 MS-REPLICATION。这可以手动完成，也可以通过 sysadmin 用户身份运行一次任务来完成。

1. 使用以下脚本，在源数据库上创建 `awsdms` 架构：

   ```
   use master
   go
   create schema awsdms
   go
   
   
   -- Create the table valued function [awsdms].[split_partition_list] on the Master database, as follows:
   USE [master]
   GO
   
   set ansi_nulls on
   go
   
   set quoted_identifier on
   go
   
   if (object_id('[awsdms].[split_partition_list]','TF')) is not null
   
   drop function [awsdms].[split_partition_list];
   
   go
   
   create function [awsdms].[split_partition_list]
   
   (
   
   @plist varchar(8000), --A delimited list of partitions
   
   @dlm nvarchar(1) --Delimiting character
   
   )
   
   returns @partitionsTable table --Table holding the BIGINT values of the string fragments
   
   (
   
   pid bigint primary key
   
   )   
   
   as
   
   begin
   
   declare @partition_id bigint;
   
   declare @dlm_pos integer;
   
   declare @dlm_len integer;
   
   set @dlm_len = len(@dlm);
   
   while (charindex(@dlm,@plist)>0)
   
   begin
   
   set @dlm_pos = charindex(@dlm,@plist);
   
   set @partition_id = cast( ltrim(rtrim(substring(@plist,1,@dlm_pos-1))) as bigint);
   
   insert into @partitionsTable (pid) values (@partition_id)
   
   set @plist = substring(@plist,@dlm_pos+@dlm_len,len(@plist));
   
   end
   
   set @partition_id = cast (ltrim(rtrim(@plist)) as bigint);
   
   insert into @partitionsTable (pid) values ( @partition_id );
   
   return
   
   end
   
   GO
   ```

1. 使用以下脚本，在 Master 数据库上创建 `[awsdms].[rtm_dump_dblog]` 过程：

   ```
   use [MASTER]
   
   go
   
   if (object_id('[awsdms].[rtm_dump_dblog]','P')) is not null drop procedure [awsdms].[rtm_dump_dblog];
   go
   
   
   set ansi_nulls on
   go
   
   set quoted_identifier on
   GO
   
   
   
   CREATE procedure [awsdms].[rtm_dump_dblog]
   
   (
   
   @start_lsn varchar(32),
   
   @seqno integer,
   
   @filename varchar(260),
   
   @partition_list varchar(8000), -- A comma delimited list: P1,P2,... Pn
   
   @programmed_filtering integer,
   
   @minPartition bigint,
   
   @maxPartition bigint
   
   )
   
   as begin
   
   declare @start_lsn_cmp varchar(32); -- Stands against the GT comparator
   
   SET NOCOUNT ON -- – Disable "rows affected display"
   
   set @start_lsn_cmp = @start_lsn;
   
   if (@start_lsn_cmp) is null
   
   set @start_lsn_cmp = '00000000:00000000:0000';
   
   if (@partition_list is null)
   
   begin
   
   RAISERROR ('Null partition list waspassed',16,1);
   
   return
   
   end
   
   if (@start_lsn) is not null
   
   set @start_lsn = '0x'+@start_lsn;
   
   if (@programmed_filtering=0)
   
   
   
   SELECT
   
   [Current LSN],
   
   [operation],
   
   [Context],
   
   [Transaction ID],
   
   [Transaction Name],
   
   [Begin Time],
   
   [End Time],
   
   [Flag Bits],
   
   [PartitionID],
   
   [Page ID],
   
   [Slot ID],
   
   [RowLog Contents 0],
   
   [Log Record],
   
   [RowLog Contents 1]
   
   FROM
   
   fn_dump_dblog (
   
   @start_lsn, NULL, N'DISK', @seqno, @filename,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default)
   
   where [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS
   
   and
   
   (
   
   ( [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') )
   
   or
   
   ( [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW')
   
   and
   
   ( ( [context] in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX' and (datalength([RowLog Contents 0]) in (0,1))))
   
   and [PartitionID] in ( select * from master.awsdms.split_partition_list (@partition_list,','))
   
   )
   
   or
   
   ([operation] = 'LOP_HOBT_DDL')
   
   )
   
   
   else
   
   
   SELECT
   
   [Current LSN],
   
   [operation],
   
   [Context],
   
   [Transaction ID],
   
   [Transaction Name],
   
   [Begin Time],
   
   [End Time],
   
   [Flag Bits],
   
   [PartitionID],
   
   [Page ID],
   
   [Slot ID],
   
   [RowLog Contents 0],
   
   [Log Record],
   
   [RowLog Contents 1] -- After Image
   
   FROM
   
   fn_dump_dblog (
   
   @start_lsn, NULL, N'DISK', @seqno, @filename,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default,
   
   default, default, default, default, default, default, default)
   
   where [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS
   
   and
   
   (
   
   ( [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') )
   
   or
   
   ( [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW')
   
   and
   
   ( ( [context] in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX' and (datalength([RowLog Contents 0]) in (0,1))))
   
   and ([PartitionID] is not null) and ([PartitionID] >= @minPartition and [PartitionID]<=@maxPartition)
   
   )
   
   or
   
   ([operation] = 'LOP_HOBT_DDL')
   
   )
   
   
   
   SET NOCOUNT OFF -- Re-enable "rows affected display"
   
   end
   
   GO
   ```

1. 使用以下脚本，在 Master 数据库上创建证书：

   ```
   Use [master]
   Go
   
   CREATE CERTIFICATE [awsdms_rtm_dump_dblog_cert] ENCRYPTION BY PASSWORD = N'@5trongpassword'
   
   WITH SUBJECT = N'Certificate for FN_DUMP_DBLOG Permissions';
   ```

1. 使用以下脚本，从证书创建登录名：

   ```
   Use [master]
   Go
   
   CREATE LOGIN awsdms_rtm_dump_dblog_login FROM CERTIFICATE [awsdms_rtm_dump_dblog_cert];
   ```

1. 使用以下脚本，将登录名添加到 sysadmin 服务器角色：

   ```
   ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_dump_dblog_login];
   ```

1. 通过以下脚本，使用证书将签名添加到 [master].[awsdms].[rtm\$1dump\$1dblog]。

   ```
   Use [master]
   GO
   ADD SIGNATURE
   TO [master].[awsdms].[rtm_dump_dblog] BY CERTIFICATE [awsdms_rtm_dump_dblog_cert] WITH PASSWORD = '@5trongpassword';
   ```
**注意**  
如果重新创建存储过程，您需要再次添加签名。

1. 使用以下脚本在 Master 数据库上创建 [awsdms].[rtm\$1position\$11st\$1timestamp]：

   ```
   use [master]
       if object_id('[awsdms].[rtm_position_1st_timestamp]','P') is not null
       DROP PROCEDURE [awsdms].[rtm_position_1st_timestamp];
       go
       create procedure [awsdms].[rtm_position_1st_timestamp]
       (
       @dbname                sysname,      -- Database name
       @seqno                 integer,      -- Backup set sequence/position number within file
       @filename              varchar(260), -- The backup filename
       @1stTimeStamp          varchar(40)   -- The timestamp to position by
       ) 
       as begin
   
       SET NOCOUNT ON       -- Disable "rows affected display"
   
       declare @firstMatching table
       (
       cLsn varchar(32),
       bTim datetime
       )
   
       declare @sql nvarchar(4000)
       declare @nl                       char(2)
       declare @tb                       char(2)
       declare @fnameVar                 nvarchar(254) = 'NULL'
   
       set @nl  = char(10); -- New line
       set @tb  = char(9)   -- Tab separator
   
       if (@filename is not null)
       set @fnameVar = ''''+@filename +''''
   
       set @sql='use ['+@dbname+'];'+@nl+
       'select top 1 [Current LSN],[Begin Time]'+@nl+
       'FROM fn_dump_dblog (NULL, NULL, NULL, '+ cast(@seqno as varchar(10))+','+ @fnameVar+','+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default,'+@nl+
       @tb+'default, default, default, default, default, default, default)'+@nl+
       'where operation=''LOP_BEGIN_XACT''' +@nl+
       'and [Begin Time]>= cast('+''''+@1stTimeStamp+''''+' as datetime)'+@nl
   
       --print @sql
       delete from  @firstMatching 
       insert into @firstMatching  exec sp_executesql @sql    -- Get them all
   
       select top 1 cLsn as [matching LSN],convert(varchar,bTim,121) as [matching Timestamp] from @firstMatching;
   
       SET NOCOUNT OFF      -- Re-enable "rows affected display"
   
       end
       GO
   ```

1. 使用以下脚本，在 Master 数据库上创建证书：

   ```
   Use [master]
   Go
   CREATE CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert]
   ENCRYPTION BY PASSWORD = '@5trongpassword'
   WITH SUBJECT = N'Certificate for FN_POSITION_1st_TIMESTAMP Permissions';
   ```

1. 使用以下脚本，从证书创建登录名：

   ```
   Use [master]
   Go
   CREATE LOGIN awsdms_rtm_position_1st_timestamp_login FROM CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert];
   ```

1. 使用以下脚本，将登录名添加到 sysadmin 角色：

   ```
   ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_position_1st_timestamp_login];
   ```

1. 通过以下脚本，使用证书将签名添加到 [master].[awsdms].[rtm\$1position\$11st\$1timestamp]：

   ```
   Use [master]
       GO
       ADD SIGNATURE
       TO [master].[awsdms].[rtm_position_1st_timestamp]
       BY CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert]
       WITH PASSWORD = '@5trongpassword';
   ```

1. 使用以下脚本向 DMS 用户授予对新存储过程的执行访问权限：

   ```
   use master
   go
   GRANT execute on [awsdms].[rtm_position_1st_timestamp] to dms_user;
   ```

1. 在以下每个数据库中，创建具有以下权限和角色的用户：
**注意**  
您应该在每个副本上使用相同的 SID 创建 dmsnosysadmin 用户账户。以下 SQL 查询可以帮助验证每个副本上的 dmsnosysadmin 账户 SID 值。有关创建用户的更多信息，请参阅 [Microsoft SQL Server 文档](https://learn.microsoft.com/en-us/sql/)中的 [CREATE USER（Transact-SQL）](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-user-transact-sql)。有关为 Azure SQL 数据库创建 SQL 用户账户的更多信息，请参阅[活动异地复制](https://learn.microsoft.com/en-us/azure/azure-sql/database/active-geo-replication-overview)。

   ```
   use master
   go
   grant select on sys.fn_dblog to [DMS_user]
   grant view any definition to [DMS_user]
   grant view server state to [DMS_user]--(should be granted to the login).
   grant execute on sp_repldone to [DMS_user]
   grant execute on sp_replincrementlsn to [DMS_user]
   grant execute on sp_addpublication to [DMS_user]
   grant execute on sp_addarticle to [DMS_user]
   grant execute on sp_articlefilter to [DMS_user]
   grant select on [awsdms].[split_partition_list] to [DMS_user]
   grant execute on [awsdms].[rtm_dump_dblog] to [DMS_user]
   ```

   ```
   use msdb
   go
   grant select on msdb.dbo.backupset to self_managed_user
   grant select on msdb.dbo.backupmediafamily to self_managed_user
   grant select on msdb.dbo.backupfile to self_managed_user
   ```

   在源数据库上运行以下脚本：

   ```
   use Source_DB
       Go
       EXEC sp_addrolemember N'db_owner', N'DMS_user'
   ```

1. 最后，向源 SQL Server 端点添加额外连接属性（ECA）：

   ```
   enableNonSysadminWrapper=true;
   ```

#### 在可用性组环境中的 SQL Server 上设置持续复制：无 sysadmin 角色
<a name="CHAP_SupportScripts.SQLServer.ag"></a>

本节介绍如何在不需要用户账户具有 sysadmin 权限的可用性组环境中为 SQL Server 数据库源设置持续复制。

**注意**  
运行本节中的步骤后，非 sysadmin DMS 用户将有权执行以下操作：  
从联机事务日志文件中读取更改
通过访问磁盘从事务日志备份文件中读取更改
添加或更改 DMS 使用的发布内容
向发布内容中添加文章

**在可用性组环境中设置持续复制而不使用 sysadmin 用户**

1. 按照[捕获数据更改，以便从 SQL Server 进行持续复制](#CHAP_Source.SQLServer.CDC)中所述设置用于复制的 Microsoft SQL Server。

1. 在源数据库上启用 MS-REPLICATION。这可以手动完成，也可以使用 sysadmin 用户身份运行一次任务来完成。
**注意**  
您应该将 MS-REPLICATION 分发服务器配置为本地分发服务器，或者配置为允许非 sysadmin 用户通过关联的链接服务器进行访问。

1. 如果启用**在单个任务中独占使用 sp\$1repldone** 端点选项，请停止 MS-REPLICATION 日志读取器作业。

1. 在每个副本上，执行以下步骤：

   1. 在 Master 数据库中创建 `[awsdms]`[awsdms] 架构：

      ```
      CREATE SCHEMA [awsdms]
      ```

   1. 在 Master 数据库中创建 `[awsdms].[split_partition_list]` 表值函数：

      ```
      USE [master]
      GO
      
      SET ansi_nulls on
      GO
        
      SET quoted_identifier on
      GO
      
      IF (object_id('[awsdms].[split_partition_list]','TF')) is not null
        DROP FUNCTION [awsdms].[split_partition_list];
      GO
      
      CREATE FUNCTION [awsdms].[split_partition_list] 
      ( 
        @plist varchar(8000),    --A delimited list of partitions    
        @dlm nvarchar(1)    --Delimiting character
      ) 
      RETURNS @partitionsTable table --Table holding the BIGINT values of the string fragments
      (
        pid bigint primary key
      ) 
      AS 
      BEGIN
        DECLARE @partition_id bigint;
        DECLARE @dlm_pos integer;
        DECLARE @dlm_len integer;  
        SET @dlm_len = len(@dlm);
        WHILE (charindex(@dlm,@plist)>0)
        BEGIN 
          SET @dlm_pos = charindex(@dlm,@plist);
          SET @partition_id = cast( ltrim(rtrim(substring(@plist,1,@dlm_pos-1))) as bigint);
          INSERT into @partitionsTable (pid) values (@partition_id)
          SET @plist = substring(@plist,@dlm_pos+@dlm_len,len(@plist));
        END 
        SET @partition_id = cast (ltrim(rtrim(@plist)) as bigint);
        INSERT into @partitionsTable (pid) values (  @partition_id  );
        RETURN
      END
      GO
      ```

   1. 在 Master 数据库中创建 `[awsdms].[rtm_dump_dblog]` 过程：

      ```
      USE [MASTER] 
      GO
      
      IF (object_id('[awsdms].[rtm_dump_dblog]','P')) is not null
        DROP PROCEDURE [awsdms].[rtm_dump_dblog]; 
      GO
      
      SET ansi_nulls on
      GO 
      
      SET quoted_identifier on 
      GO
                                          
      CREATE PROCEDURE [awsdms].[rtm_dump_dblog]
      (
        @start_lsn            varchar(32),
        @seqno                integer,
        @filename             varchar(260),
        @partition_list       varchar(8000), -- A comma delimited list: P1,P2,... Pn
        @programmed_filtering integer,
        @minPartition         bigint,
        @maxPartition         bigint
      ) 
      AS 
      BEGIN
      
        DECLARE @start_lsn_cmp varchar(32); -- Stands against the GT comparator
      
        SET NOCOUNT ON  -- Disable "rows affected display"
      
        SET @start_lsn_cmp = @start_lsn;
        IF (@start_lsn_cmp) is null
          SET @start_lsn_cmp = '00000000:00000000:0000';
      
        IF (@partition_list is null)
          BEGIN
            RAISERROR ('Null partition list was passed',16,1);
            return
            --set @partition_list = '0,';    -- A dummy which is never matched
          END
      
        IF (@start_lsn) is not null
          SET @start_lsn = '0x'+@start_lsn;
      
        IF (@programmed_filtering=0)
          SELECT
            [Current LSN],
            [operation],
            [Context],
            [Transaction ID],
            [Transaction Name],
            [Begin Time],
            [End Time],
            [Flag Bits],
            [PartitionID],
            [Page ID],
            [Slot ID],
            [RowLog Contents 0],
            [Log Record],
            [RowLog Contents 1] -- After Image
          FROM
            fn_dump_dblog (
              @start_lsn, NULL, N'DISK', @seqno, @filename,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default,
              default, default, default, default, default, default, default)
          WHERE 
            [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS -- This aims for implementing FN_DBLOG based on GT comparator.
            AND
            (
              (  [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') )
              OR
              (  [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW')
                AND
                ( ( [context]   in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX') )
                AND       
                [PartitionID] in ( select * from master.awsdms.split_partition_list (@partition_list,','))
              )
            OR
            ([operation] = 'LOP_HOBT_DDL')
          )
          ELSE
            SELECT
              [Current LSN],
              [operation],
              [Context],
              [Transaction ID],
              [Transaction Name],
              [Begin Time],
              [End Time],
              [Flag Bits],
              [PartitionID],
              [Page ID],
              [Slot ID],
              [RowLog Contents 0],
              [Log Record],
              [RowLog Contents 1] -- After Image
            FROM
              fn_dump_dblog (
                @start_lsn, NULL, N'DISK', @seqno, @filename,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default,
                default, default, default, default, default, default, default)
            WHERE [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS -- This aims for implementing FN_DBLOG based on GT comparator.
            AND
            (
              (  [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') )
              OR
              (  [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW')
                AND
                ( ( [context]   in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX') )
                AND ([PartitionID] is not null) and ([PartitionID] >= @minPartition and [PartitionID]<=@maxPartition)
              )
              OR
              ([operation] = 'LOP_HOBT_DDL')
            )
            SET NOCOUNT OFF -- Re-enable "rows affected display"
      END
      GO
      ```

   1. 在 Master 数据库上创建证书：

      ```
      USE [master]
      GO
      CREATE CERTIFICATE [awsdms_rtm_dump_dblog_cert]
        ENCRYPTION BY PASSWORD = N'@hardpassword1'
        WITH SUBJECT = N'Certificate for FN_DUMP_DBLOG Permissions'
      ```

   1. 从证书创建登录名：

      ```
      USE [master]
      GO
      CREATE LOGIN awsdms_rtm_dump_dblog_login FROM CERTIFICATE
        [awsdms_rtm_dump_dblog_cert];
      ```

   1. 将登录名添加到 sysadmin 服务器角色：

      ```
      ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_dump_dblog_login];
      ```

   1. 使用证书将签名添加到 [master].[awsdms].[rtm\$1dump\$1dblog] 过程：

      ```
      USE [master]
      GO
      
      ADD SIGNATURE
        TO [master].[awsdms].[rtm_dump_dblog]
        BY CERTIFICATE [awsdms_rtm_dump_dblog_cert]
        WITH PASSWORD = '@hardpassword1';
      ```
**注意**  
如果重新创建存储过程，您需要再次添加签名。

   1. 在 Master 数据库中创建 `[awsdms].[rtm_position_1st_timestamp]` 过程：

      ```
      USE [master]
      IF object_id('[awsdms].[rtm_position_1st_timestamp]','P') is not null
        DROP PROCEDURE [awsdms].[rtm_position_1st_timestamp];
      GO
      CREATE PROCEDURE [awsdms].[rtm_position_1st_timestamp]
      (
        @dbname                sysname,      -- Database name
        @seqno                 integer,      -- Backup set sequence/position number within file
        @filename              varchar(260), -- The backup filename
        @1stTimeStamp          varchar(40)   -- The timestamp to position by
      ) 
      AS 
      BEGIN
        SET NOCOUNT ON       -- Disable "rows affected display"
      
        DECLARE @firstMatching table
        (
          cLsn varchar(32),
          bTim datetime
        )
        DECLARE @sql nvarchar(4000)
        DECLARE @nl                       char(2)
        DECLARE @tb                       char(2)
        DECLARE @fnameVar                 sysname = 'NULL'
      
        SET @nl  = char(10); -- New line
        SET @tb  = char(9)   -- Tab separator
      
        IF (@filename is not null)
          SET @fnameVar = ''''+@filename +''''
        SET @filename = ''''+@filename +''''
        SET @sql='use ['+@dbname+'];'+@nl+
          'SELECT TOP 1 [Current LSN],[Begin Time]'+@nl+
          'FROM fn_dump_dblog (NULL, NULL, NULL, '+ cast(@seqno as varchar(10))+','+ @filename +','+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default,'+@nl+
          @tb+'default, default, default, default, default, default, default)'+@nl+
          'WHERE operation=''LOP_BEGIN_XACT''' +@nl+
          'AND [Begin Time]>= cast('+''''+@1stTimeStamp+''''+' as datetime)'+@nl
      
          --print @sql
          DELETE FROM @firstMatching 
          INSERT INTO @firstMatching  exec sp_executesql @sql    -- Get them all
          SELECT TOP 1 cLsn as [matching LSN],convert(varchar,bTim,121) AS[matching Timestamp] FROM @firstMatching;
      
          SET NOCOUNT OFF      -- Re-enable "rows affected display"
      
      END
      GO
      ```

   1. 在 Master 数据库上创建证书：

      ```
      USE [master]
      GO
      CREATE CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert]
        ENCRYPTION BY PASSWORD = N'@hardpassword1'
        WITH SUBJECT = N'Certificate for FN_POSITION_1st_TIMESTAMP Permissions';
      ```

   1. 从证书创建登录名：

      ```
      USE [master]
      GO
      CREATE LOGIN awsdms_rtm_position_1st_timestamp_login FROM CERTIFICATE
        [awsdms_rtm_position_1st_timestamp_cert];
      ```

   1. 将登录名添加到 sysadmin 服务器角色：

      ```
      ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_position_1st_timestamp_login];
      ```

   1. 使用证书将签名添加到 `[master].[awsdms].[rtm_position_1st_timestamp]` 过程：

      ```
      USE [master]
      GO
      ADD SIGNATURE
        TO [master].[awsdms].[rtm_position_1st_timestamp]
        BY CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert]
        WITH PASSWORD = '@hardpassword1';
      ```
**注意**  
如果重新创建存储过程，您需要再次添加签名。

   1. 在以下每个数据库 permissions/roles 中创建具有以下内容的用户：
**注意**  
您应该在每个副本上使用相同的 SID 创建 dmsnosysadmin 用户账户。以下 SQL 查询可以帮助验证每个副本上的 dmsnosysadmin 账户 SID 值。有关创建用户的更多信息，请参阅 [Microsoft SQL Server 文档](https://learn.microsoft.com/en-us/sql/)中的 [CREATE USER（Transact-SQL）](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-user-transact-sql)。有关为 Azure SQL 数据库创建 SQL 用户账户的更多信息，请参阅[活动异地复制](https://learn.microsoft.com/en-us/azure/azure-sql/database/active-geo-replication-overview)。

      ```
      SELECT @@servername servername, name, sid, create_date, modify_date
        FROM sys.server_principals
        WHERE name = 'dmsnosysadmin';
      ```

   1. 在每个副本上授予对 Master 数据库的权限：

      ```
      USE master
      GO 
      
      GRANT select on sys.fn_dblog to dmsnosysadmin;
      GRANT view any definition to dmsnosysadmin;
      GRANT view server state to dmsnosysadmin -- (should be granted to the login).
      GRANT execute on sp_repldone to dmsnosysadmin;
      GRANT execute on sp_replincrementlsn to dmsnosysadmin;
      GRANT execute on sp_addpublication to dmsnosysadmin;
      GRANT execute on sp_addarticle to dmsnosysadmin;
      GRANT execute on sp_articlefilter to dmsnosysadmin;
      GRANT select on [awsdms].[split_partition_list] to dmsnosysadmin;
      GRANT execute on [awsdms].[rtm_dump_dblog] to dmsnosysadmin;
      GRANT execute on [awsdms].[rtm_position_1st_timestamp] to dmsnosysadmin;
      ```

   1. 在每个副本上授予对 MSDB 数据库的权限：

      ```
      USE msdb
      GO
      GRANT select on msdb.dbo.backupset TO self_managed_user
      GRANT select on msdb.dbo.backupmediafamily TO self_managed_user
      GRANT select on msdb.dbo.backupfile TO self_managed_user
      ```

   1. 在源数据库上将 `db_owner` 角色添加到 `dmsnosysadmin`。由于数据库已同步，您只能在主副本上添加角色。

      ```
      use <source DB>
      GO 
      EXEC sp_addrolemember N'db_owner', N'dmsnosysadmin'
      ```

## 在云 SQL Server 数据库实例上设置持续复制
<a name="CHAP_Source.SQLServer.Configuration"></a>

此部分介绍如何在云托管 SQL Server 数据库实例上设置 CDC。云托管的 SQL 服务器实例是在 Amazon RDS for SQL Server、Azure SQL 托管实例或任何其他托管云 SQL Server 实例上运行的实例。有关每种数据库类型的持续复制限制的信息，请参阅[使用 SQL Server 作为源代码的限制 AWS DMS](CHAP_Source.SQLServer.md#CHAP_Source.SQLServer.Limitations)。

在设置持续复制之前，请参阅[在 SQL Server 源中使用持续复制（CDC）的先决条件](CHAP_Source.SQLServer.md#CHAP_Source.SQLServer.Prerequisites)。

不同于自管理 Microsoft SQL Server 源，Amazon RDS for SQL Server 不支持 MS-Replication。因此， AWS DMS 需要对带或不带主键的表使用 MS-CDC。

Amazon RDS 不授予系统管理员设置用于源 SQL Server 实例中持续更改的复制项目的权限。 AWS DMS 请确保在以下过程中使用主用户权限为 Amazon RDS 实例启用 MS-CDC。

**在云 SQL Server 数据库实例上启用 MS-CDC**

1. 在数据库级别运行以下查询之一。

   对于 RDS for SQL Server 数据库实例，请使用此查询。

   ```
   exec msdb.dbo.rds_cdc_enable_db 'DB_name'
   ```

   对于 Azure SQL 托管数据库实例，请使用此查询。

   ```
   USE DB_name 
   GO 
   EXEC sys.sp_cdc_enable_db 
   GO
   ```

1. 对于带主键的每个表，运行以下查询来启用 MS-CDC。

   ```
   exec sys.sp_cdc_enable_table
   @source_schema = N'schema_name',
   @source_name = N'table_name',
   @role_name = NULL,
   @supports_net_changes = 1
   GO
   ```

   对于有唯一键但没有主键的每个表，运行以下查询来启用 MS-CDC。

   ```
   exec sys.sp_cdc_enable_table
   @source_schema = N'schema_name',
   @source_name = N'table_name',
   @index_name = N'unique_index_name',
   @role_name = NULL,
   @supports_net_changes = 1
   GO
   ```

    对于既没有主键又没有唯一键的每个表，运行以下查询来启用 MS-CDC。

   ```
   exec sys.sp_cdc_enable_table
   @source_schema = N'schema_name',
   @source_name = N'table_name',
   @role_name = NULL
   GO
   ```

1. 设置保留期：
   + 对于使用 DMS 版本 3.5.3 及更高版本进行复制的 RDS for SQL Server 实例，请确保将保留期设置为 5 秒（默认值）。如果要从 DMS 3.5.2 及更低版本升级或迁移到 DMS 3.5.3 及更高版本，当任务在新实例或升级后的实例上运行后，请更改轮询间隔值。以下脚本将保留期设置为 5 秒：

     ```
     use dbname
     EXEC sys.sp_cdc_change_job @job_type = 'capture' ,@pollinginterval = 5
     exec sp_cdc_stop_job 'capture'
     exec sp_cdc_start_job 'capture'
     ```
   + 参数 `@pollinginterval` 按秒计，建议值设置为 86399。当该参数为 `@pollinginterval = 86399` 时，这意味着事务日志将更改保留 86399 秒（一天）。过程 `exec sp_cdc_start_job 'capture'` 启动这些设置。
**注意**  
对于某些 SQL Server 版本，如果 `pollinginterval` 的值设置为超过 3599 秒，该值将重置为默认的五秒。发生这种情况时，T-Log 条目会在读取之前 AWS DMS 被清除。要确定哪些 SQL Server 版本受到此已知问题的影响，请参阅[这篇 Microsoft 知识库文章](https://support.microsoft.com/en-us/topic/kb4459220-fix-incorrect-results-occur-when-you-convert-pollinginterval-parameter-from-seconds-to-hours-in-sys-sp-cdc-scan-in-sql-server-dac8aefe-b60b-7745-f987-582dda2cfa78)。

     如果您使用带有多可用区的 Amazon RDS，请确保也设置辅助项，以便在失效转移时具有正确的值。

     ```
     exec rdsadmin..rds_set_configuration 'cdc_capture_pollinginterval' , <5 or preferred value>
     ```

**在 AWS DMS 复制任务停止超过一小时时保持保留期**
**注意**  
使用 DMS 3.5.3 及更高版本复制 RDS for SQL Server 源时无需执行以下步骤。

1. 使用以下命令停止截断事务日志的作业。

   ```
   exec sp_cdc_stop_job 'capture'
   ```

1. 在 AWS DMS 控制台上找到您的任务并继续执行任务。

1. 选择**监控**选项卡，然后勾选 `CDCLatencySource` 指标。

1. 如果 `CDCLatencySource` 指标等于 0（零）并保持不变，请使用以下命令重新启动截断事务日志的作业。

   ```
   exec sp_cdc_start_job 'capture'
   ```

记得启动截断 SQL Server 事务日志的作业。否则，您的 SQL Server 实例上的存储空间可能会被填满。

### 使用适用于 SQL Server 的 RDS 作为来源时的推荐设置 AWS DMS
<a name="CHAP_Source.SQLServer.Configuration.Settings"></a>

#### 适用于 AWS DMS 3.5.3 及更高版本
<a name="CHAP_Source.SQLServer.Configuration.Settings.353"></a>

**注意**  
对于在 DMS 版本 3.5.3 发布之后创建或修改的端点，默认启用 RDS for SQL Server 日志备份特征的初始版本。要将此特征用于现有端点，请在不进行任何更改的情况下修改端点。

AWS DMS 版本 3.5.3 引入了对从日志备份中读取的支持。DMS 主要依靠从活动事务日志中读取数据来复制事件。如果在 DMS 可以从活动日志中读取事务之前对事务进行了备份，则该任务将按需访问 RDS 备份并从后续备份日志中读取数据，直到赶上活动事务日志的步伐。为确保 DMS 可以访问日志备份，请将 RDS 自动备份保留期设置为至少一天。有关设置自动备份保留期的信息，请参阅《Amazon RDS 用户指南》**中的[备份保留期](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ManagingAutomatedBackups.html#USER_WorkingWithAutomatedBackups.BackupRetention)。

访问日志备份的 DMS 任务会使用 RDS 实例上的存储空间。请注意，该任务仅访问复制所需的日志备份。Amazon RDS 会在几小时内删除这些下载的备份。此删除不会影响保留在 Amazon S3 中的 Amazon RDS 备份，也不会影响 Amazon RDS `RESTORE DATABASE` 功能。如果您打算使用 DMS 进行复制，建议在 RDS for SQL Server 源上分配额外的存储空间。估算所需存储量的一种方法是确定 DMS 将从哪个备份开始或恢复复制，然后使用 RDS `tlog backup` 元数据函数将所有后续备份的文件大小相加。有关 `tlog backup` 函数的更多信息，请参阅《Amazon RDS 用户指南》**中的[列出可用的事务日志备份](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER.SQLServer.AddlFeat.TransactionLogAccess.html#USER.SQLServer.AddlFeat.TransactionLogAccess.Listing)。

或者，您可以根据您的 Amazon RDS 实例的 CloudWatch `FreeStorageSpace`指标选择启用存储自动扩展和/或触发存储扩展。

强烈建议您不要从事务日志备份中太远的位置开始或恢复，因为这可能会导致 SQL Server 实例上的存储空间被填满。在这种情况下，建议启动完全加载。从事务日志备份中复制比从活动事务日志中读取要慢。有关更多信息，请参阅 [针对 RDS for SQL Server 的事务日志备份处理](CHAP_Troubleshooting_Latency_Source_SQLServer.md#CHAP_Troubleshooting_Latency_Source_SQLServer_backup)。

请注意，访问日志备份需要额外的权限。有关更多信息，请参阅[从云 SQL Server 数据库进行持续复制所需的设置权限](CHAP_Source.SQLServer.md#CHAP_Source.SQLServer.Permissions.Cloud)中的详细说明。确保在任务开始复制之前授予这些权限。

#### 适用于 AWS DMS 3.5.2 及更低版本
<a name="CHAP_Source.SQLServer.Configuration.Settings.352"></a>

当您使用 Amazon RDS for SQL Server 作为源时，MS-CDC 捕获作业依赖于参数 `maxscans` 和 `maxtrans`。这些参数控制 MS-CDC 捕获对事务日志执行的最大扫描次数以及每次扫描处理的事务数。

对于事务数大于 `maxtrans*maxscans` 的数据库，增加其 `polling_interval` 值可能会导致活动事务日志记录的累积。这种累积反过来又会导致事务日志的大小增加。

请注意，这 AWS DMS 并不依赖于 MS-CDC 捕获作业。MS-CDC 捕获作业将事务日志条目标记为已处理。这样可允许事务日志备份作业从事务日志中删除条目。

我们建议您监控事务日志的大小和 MS-CDC 作业是否成功。如果 MS-CDC 作业失败，事务日志可能会过度增长并导致 AWS DMS 复制失败。您可以使用源数据库中的 `sys.dm_cdc_errors` 动态管理视图来监控 MS-CDC 捕获作业错误。您可以使用 `DBCC SQLPERF(LOGSPACE)` 管理命令来监控事务日志的大小。

**解决由 MS-CDC 引起的事务日志增加问题**

1. 检查数据库是否 AWS DMS 正在从中复制，并验证它是否持续增加。`Log Space Used %`

   ```
   DBCC SQLPERF(LOGSPACE)
   ```

1. 确定阻碍事务日志备份过程的原因。

   ```
   Select log_reuse_wait, log_reuse_wait_desc, name from sys.databases where name = db_name();
   ```

   如果 `log_reuse_wait_desc` 值等于 `REPLICATION`，则说明日志备份保留是 MS-CDC 中的延迟所导致。

1. 通过增加 `maxtrans` 和 `maxscans` 参数值来增加捕获作业处理的事件数。

   ```
   EXEC sys.sp_cdc_change_job @job_type = 'capture' ,@maxtrans = 5000, @maxscans = 20 
   exec sp_cdc_stop_job 'capture'
   exec sp_cdc_start_job 'capture'
   ```

要解决此问题，请将`maxscans`和`maxtrans`的值设置`maxtrans*maxscans`为等于每天为从源数据库 AWS DMS 复制的表生成的事件的平均数。

如果将这些参数设置为高于建议值，则捕获作业会处理事务日志中的所有事件。如果将这些参数设置为低于建议值，则 MS-CDC 延迟会增加，事务日志也会增加。

为 `maxscans` 和 `maxtrans` 确定合适的值可能很困难，因为工作负载的变化会产生不同数量的事件。在这种情况下，建议您对 MS-CDC 延迟设置监控。有关更多信息，请参阅 SQL Server 文档中的[监控流程](https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/administer-and-monitor-change-data-capture-sql-server?view=sql-server-ver15#Monitor)。然后根据监控结果动态配置 `maxtrans` 和 `maxscans`。

如果 AWS DMS 任务找不到恢复或继续任务所需的日志序列号 (LSNs)，则该任务可能会失败并需要完全重新加载。

**注意**  
使用 AWS DMS 从 RDS for SQL Server 源复制数据时，在 Amazon RDS 实例的停止启动事件之后尝试恢复复制时，您可能会遇到错误。这是由于 SQL Server Agent 进程在停止启动事件后重新启动时，会重新启动捕获作业进程。这绕过了 MS-CDC 轮询间隔。  
因此，在事务量低于 MS-CDC 捕获作业处理的数据库上，这可能会导致数据在从停止位置恢复之前 AWS DMS 被处理或标记为已复制和备份，从而导致以下错误：  

```
[SOURCE_CAPTURE ]E: Failed to access LSN '0000dbd9:0006f9ad:0003' in the backup log sets since BACKUP/LOG-s are not available. [1020465] (sqlserver_endpoint_capture.c:764)
```
要缓解此问题，请按照之前的建议设置 `maxtrans` 和 `maxscans` 值。