

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

# 使用 PostgreSQL 数据库作为目标 AWS Database Migration Service
<a name="CHAP_Target.PostgreSQL"></a>

您可以使用将数据从另一个 PostgreSQ AWS DMS L 数据库或其他支持的数据库迁移到 PostgreSQL 数据库。

有关支持作为目标的 PostgreSQL 版本的信息 AWS DMS ，请参阅。[的目标 AWS DMS](CHAP_Introduction.Targets.md)

**注意**  
Amazon Aurora Serverless 可作为与 PostgreSQL 兼容的 Amazon Aurora 的目标。有关 Amazon Aurora Serverless 的更多信息，请参阅《Amazon Aurora 用户指南》**中的[使用 Amazon Aurora Serverless v2](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.html)。
Aurora Serverless 数据库集群只能从 Amazon VPC 访问，不能使用[公有 IP 地址](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.requirements.html)。因此，如果您要在不同于 Aurora PostgreSQL Serverless 的其他区域创建复制实例，则必须配置 [VPC 对等连接](https://docs.aws.amazon.com//dms/latest/userguide/CHAP_ReplicationInstance.VPC.html#CHAP_ReplicationInstance.VPC.Configurations.ScenarioVPCPeer)。否则，请检查 Aurora PostgreSQL Serverless [区域](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/Concepts.AuroraFeaturesRegionsDBEngines.grids.html#Concepts.Aurora_Fea_Regions_DB-eng.Feature.Serverless)的可用性，并决定将其中一个区域用于 Aurora PostgreSQL Serverless 和您的复制实例。
Babelfish 功能内置在 Amazon Aurora 中，无需支付额外费用。有关更多信息，请参阅[将适用于 Aurora PostgreSQL 的 Babelfish 作为 AWS Database Migration Service的目标](#CHAP_Target.PostgreSQL.Babelfish)。

AWS DMS 在满载阶段将数据从源迁移到目标时 table-by-table采用了一种方法。无法在完全加载阶段保证表顺序。在完全加载阶段以及应用各个表的缓存事务时，表将不同步。因此，活动引用完整性约束可能会导致任务在完全加载阶段失败。

在 PostgreSQL 中，将使用触发器实施外键 (引用完整性约束)。在满载阶段，每次 AWS DMS 加载一个表。强烈建议您在完全加载期间使用以下方法之一禁用外键约束：
+ 从实例中临时禁用所有触发器并完成完全加载。
+ 在 PostgreSQL 中使用 `session_replication_role`参数。

在任何给定时间，触发器可能处于以下状态之一：`origin`、`replica`、`always` 或 `disabled`。在将 `session_replication_role` 参数设置为 `replica` 时，只有处于 `replica` 状态的触发器是活动触发器，并且它们在被调用时触发。否则，触发器保持非活动状态。

PostgreSQL 具有故障保护机制以防止截断表，即使设置了 `session_replication_role`。您可以将该机制作为禁用触发器的替代方法，以帮助完成完全加载运行。为此，请将目标表准备模式设置为 `DO_NOTHING`。否则，在具有外键约束时，DROP 和 TRUNCATE 操作将失败。

在 Amazon RDS 中，可以使用参数组控制该参数的设置。对于在 Amazon EC2 上运行的 PostgreSQL 实例，可以直接设置该参数。



有关使用 PostgreSQL 数据库作为目标的更多详细信息， AWS DMS请参阅以下各节：

**Topics**
+ [使用 PostgreSQL 作为目标的限制 AWS Database Migration Service](#CHAP_Target.PostgreSQL.Limitations)
+ [使用亚马逊 Aurora PostgreSQL Limitless 作为目标的限制 AWS Database Migration Service](#CHAP_Target.PostgreSQL.Aurora.Limitations)
+ [使用 PostgreSQL 数据库作为目标时的安全要求 AWS Database Migration Service](#CHAP_Target.PostgreSQL.Security)
+ [使用 PostgreSQL 作为ECAs目标时的端点设置和额外连接属性 () AWS DMS](#CHAP_Target.PostgreSQL.ConnectionAttrib)
+ [PostgreSQL 的目标数据类型](#CHAP_Target.PostgreSQL.DataTypes)
+ [使用 Babelfish for Aurora PostgreSQL 作为目标 AWS Database Migration Service](#CHAP_Target.PostgreSQL.Babelfish)

## 使用 PostgreSQL 作为目标的限制 AWS Database Migration Service
<a name="CHAP_Target.PostgreSQL.Limitations"></a>

将 PostgreSQL 数据库作为 AWS DMS的目标时，存在以下限制：
+ 对于异构迁移，JSON 数据类型将在内部转换为原生 CLOB 数据类型。
+ 在 Oracle 到 PostgreSQL 的迁移中，如果 Oracle 中的一列包含空字符（十六进制值 U\$10000） AWS DMS ，则将空字符转换为空格（十六进制值 U\$10020）。这是出于 PostgreSQL 限制的原因。
+ AWS DMS 不支持复制到使用合并函数创建的具有唯一索引的表。
+ 如果您的表使用序列，则在停止从源数据库`NEXTVAL`进行复制后，请更新目标数据库中每个序列的值。 AWS DMS 复制源数据库中的数据，但在正在进行的复制过程中不会将序列迁移到目标数据库。

## 使用亚马逊 Aurora PostgreSQL Limitless 作为目标的限制 AWS Database Migration Service
<a name="CHAP_Target.PostgreSQL.Aurora.Limitations"></a>

使用 Amazon Aurora PostgreSQL Limitless 作为目标时，以下限制适用： AWS DMS
+ AWS DMS 数据验证不支持 Amazon Aurora PostgreSQL Limitless。
+ AWS DMS 将源表迁移为标准表，这些表不是分布式的。迁移后，您可以按照官方转换指南将这些标准表转换为 Limitless 表。

## 使用 PostgreSQL 数据库作为目标时的安全要求 AWS Database Migration Service
<a name="CHAP_Target.PostgreSQL.Security"></a>

出于安全目的，用于数据迁移的用户账户，必须是您作为目标的任意 PostgreSQL 数据库中的注册用户。

您的 PostgreSQL 目标端点需要最低的用户权限才能运行迁移，请参阅以下示 AWS DMS 例。

```
    CREATE USER newuser WITH PASSWORD 'your-password';
    ALTER SCHEMA schema_name OWNER TO newuser;
```

或者，

```
    GRANT USAGE ON SCHEMA schema_name TO myuser;
    GRANT CONNECT ON DATABASE postgres to myuser;
    GRANT CREATE ON DATABASE postgres TO myuser;
    GRANT CREATE ON SCHEMA schema_name TO myuser;
    GRANT UPDATE, INSERT, SELECT, DELETE, TRUNCATE ON ALL TABLES IN SCHEMA schema_name TO myuser;
    GRANT TRUNCATE ON schema_name."BasicFeed" TO myuser;
```

## 使用 PostgreSQL 作为ECAs目标时的端点设置和额外连接属性 () AWS DMS
<a name="CHAP_Target.PostgreSQL.ConnectionAttrib"></a>

您可以使用端点设置和额外连接属性 (ECAs) 来配置您的 PostgreSQL 目标数据库。

您可以在使用 AWS DMS 控制台创建目标端点时指定设置，或者使用中的`create-endpoint`命令和 `--postgre-sql-settings '{"EndpointSetting": "value", ...}'` JSON 语法。[AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/dms/index.html)

您可以使用终端节点的`ExtraConnectionAttributes`参数进行指定 ECAs 。

下表显示了您可以使用 PostgreSQL 作为目标的端点设置。

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

## PostgreSQL 的目标数据类型
<a name="CHAP_Target.PostgreSQL.DataTypes"></a>

的 PostgreSQL 数据库端点 AWS DMS 支持大多数 PostgreSQL 数据库数据类型。下表显示了 AWS DMS 使用时支持的 PostgreSQL 数据库目标数据类型以及数据类型的默认映射 AWS DMS 。

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


|  AWS DMS 数据类型  |  PostgreSQL 数据类型  | 
| --- | --- | 
|  BOOLEAN  |  BOOLEAN  | 
|  BLOB  |  BYTEA  | 
|  BYTES  |  BYTEA  | 
|  DATE  |  DATE  | 
|  TIME  |  TIME  | 
|  DATETIME  |  如果小数位数介于 0 和 6 之间，请使用 TIMESTAMP。 如果小数位数介于 7 和 9 之间，请使用 VARCHAR (37)。  | 
|  INT1  |  SMALLINT  | 
|  INT2  |  SMALLINT  | 
|  INT4  |  INTEGER  | 
|  INT8  |  BIGINT  | 
|  NUMERIC   |  DECIMAL (P,S)  | 
|  REAL4  |  FLOAT4  | 
|  REAL8  |  FLOAT8  | 
|  string  |  如果长度介于 1 和 21845 之间，请使用 VARCHAR（以字节为单位的长度）。 如果长度介于 21846 和 2147483647 之间，请使用 VARCHAR (65535)。  | 
|  UINT1  |  SMALLINT  | 
|  UINT2  |  INTEGER  | 
|  UINT4  |  BIGINT  | 
|  UINT8  |  BIGINT  | 
|  WSTRING  |  如果长度介于 1 和 21845 之间，请使用 VARCHAR（以字节为单位的长度）。 如果长度介于 21846 和 2147483647 之间，请使用 VARCHAR (65535)。  | 
|  NCLOB  |  TEXT  | 
|  CLOB  |  TEXT  | 

**注意**  
从 PostgreSQL 源进行复制时 AWS DMS ，除了具有用户定义数据类型的列之外，会为所有列创建具有相同数据类型的目标表。在此类情况下，在目标中创建数据类型作为“可变字符”。

## 使用 Babelfish for Aurora PostgreSQL 作为目标 AWS Database Migration Service
<a name="CHAP_Target.PostgreSQL.Babelfish"></a>

可以使用 AWS Database Migration Service将 SQL Server 源表迁移到适用于 Amazon Aurora PostgreSQL 的 Babelfish 目标。有了 Babelfish，Aurora PostgreSQL 可以理解 Microsoft SQL Server 的专有 SQL 语言 T-SQL，并支持相同的通信协议。因此，为 SQL Server 编写的应用程序现在只需更改更少的代码，即可与 Aurora 配合使用。Babelfish 功能内置在 Amazon Aurora 中，无需支付额外费用。可以通过 Amazon RDS 控制台在 Amazon Aurora 集群上激活 Babelfish。

**使用 AWS DMS 控制台、API 或 CLI 命令创建 AWS DMS 目标终端节点时，将目标引擎指定为 **Amazon Aurora PostgreSQL**，并将数据库命名为 babelfish\$1db。**在**端点设置**部分，添加相关设置以将 `DatabaseMode` 设置为 `Babelfish`，并将 `BabelfishDatabaseName` 设置为 Babelfish T-SQL 数据库的名称。

### 向迁移任务添加转换规则
<a name="CHAP_Target.PostgreSQL.Babelfish.transform"></a>

在为 Babelfish 目标定义迁移任务时，需要包含转换规则，以确保 DMS 使用目标数据库中预先创建的 T-SQL Babelfish 表。

首先，在迁移任务中添加一个转换规则，使所有表名都变为小写。Babelfish 将您使用 T-SQL 创建的表的名称以小写形式存储在 PostgreSQL `pg_class` 目录中。但是，当您的 SQL Server 表具有大小写混合的名称时，DMS 会使用 PostgreSQL 原生数据类型而不是与 T-SQL 兼容的数据类型来创建表。因此，请务必添加一个转换规则，使所有表名都变为小写。请注意，不应将列名称转换为小写。

接下来，如果您在定义集群时使用了多数据库迁移模式，请添加重命名原始 SQL Server 架构的转换规则。务必重命名 SQL Server 架构名称，使之包含 T-SQL 数据库的名称。例如，如果原始 SQL Server 架构名称为 dbo，而您的 T-SQL 数据库名称为 dbo，则使用转换规则将架构重命名为 mydb\$1dbo。

**注意**  
使用适用于 Aurora PostgreSQL 的 Babelfish 16 或更高版本时，默认迁移模式为“多数据库”。运行 DMS 迁移任务时，请务必查看迁移模式参数并在需要时更新转换规则。

如果您使用单数据库模式，则不需要转换规则即可重命名架构名称。架构名称与 Babelf one-to-one ish 中的目标 T-SQL 数据库存在映射。

以下转换规则示例将所有表名设置为小写，并将原始 SQL Server 架构名称从 `dbo` 重命名为 `mydb_dbo`。

```
{
   "rules": [
   {
      "rule-type": "transformation",
      "rule-id": "566251737",
      "rule-name": "566251737",
      "rule-target": "schema",
      "object-locator": {
         "schema-name": "dbo"
      },
      "rule-action": "rename",
      "value": "mydb_dbo",
      "old-value": null
   },
   {
      "rule-type": "transformation",
      "rule-id": "566139410",
      "rule-name": "566139410",
      "rule-target": "table",
      "object-locator": {
         "schema-name": "%",
         "table-name": "%"
      },
      "rule-action": "convert-lowercase",
      "value": null,
      "old-value": null
   },
   {
      "rule-type": "selection",
      "rule-id": "566111704",
      "rule-name": "566111704",
      "object-locator": {
         "schema-name": "dbo",
         "table-name": "%"
      },
      "rule-action": "include",
      "filters": []
   }
]
}
```

### 使用包含 Babelfish 表的 PostgreSQL 目标端点的限制
<a name="CHAP_Target.PostgreSQL.Babelfish.limitations"></a>

使用包含 Babelfish 表的 PostgreSQL 目标端点时，存在以下限制：
+ 对于**目标表准备**模式，仅使用**不执行任何操作**或**截断**模式。不要使用**删除目标中的表**模式。在该模式下，DMS 会将这些表创建为 T-SQL 可能无法识别的 PostgreSQL 表。
+ AWS DMS 不支持 sql\$1variant 数据类型。
+ Postgres 端点下的 Babelfish 不支持 `HEIRARCHYID`、`GEOMETRY`（3.5.4 之前版本）和 `GEOGRAPHY`（3.5.4 之前版本）数据类型。要迁移这些数据类型，您可以添加转换规则以将数据类型转换为 wstring(250)。
+ Babelfish 仅支持使用 `BYTEA` 数据类型迁移 `BINARY`、`VARBINARY` 和 `IMAGE` 数据类型。对于早期版本的 Aurora PostgreSQL，可以使用 DMS 将这些表迁移到 [Babelfish 目标端点](CHAP_Target.Babelfish.md)。您不必为 `BYTEA` 数据类型指定长度，如以下示例所示。

  ```
  [Picture] [VARBINARY](max) NULL
  ```

  将前面的 T-SQL 数据类型更改为 T-SQL 支持的 `BYTEA` 数据类型。

  ```
  [Picture] BYTEA NULL
  ```
+ 对于早期版本的 Aurora PostgreSQL Babelfish，如果您使用 PostgreSQL 目标端点创建用于从 SQL Server 持续复制到 Babelfish 的迁移任务，则需要为任何使用 `IDENTITY` 列的表分配 `SERIAL` 数据类型。从 Aurora PostgreSQL（版本 15.3/14.8 及更高版本）和 Babelfish（版本 3.2.0 及更高版本）开始，支持标识列，并且不再需要分配 SERIAL 数据类型。有关更多信息，请参阅《SQL Server 到 Aurora PostgreSQL 迁移行动手册》**的“序列和标识”部分中的 [SERIAL 使用情况](https://docs.aws.amazon.com/dms/latest/sql-server-to-aurora-postgresql-migration-playbook/chap-sql-server-aurora-pg.tsql.sequences..html)。然后，当您在 Babelfish 中创建表时，需修改如下的列定义。

  ```
      [IDCol] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY
  ```

  将前面的内容改为以下内容。

  ```
      [IDCol] SERIAL PRIMARY KEY
  ```

  兼容 Babelfish 的 Aurora PostgreSQL 使用默认配置创建序列并向该列添加 `NOT NULL` 约束。新创建的序列的行为类似于常规序列（以 1 为增量），并且没有复合 `SERIAL` 选项。
+ 使用包含 `IDENTITY` 列或 `SERIAL` 数据类型的表迁移数据后，根据列的最大值重置基于 PostgreSQL 的序列对象。对表执行完全加载后，使用以下 T-SQL 查询生成语句以便设置关联序列对象的种子。

  ```
  DECLARE @schema_prefix NVARCHAR(200) = ''
  
  IF current_setting('babelfishpg_tsql.migration_mode') = 'multi-db'
          SET @schema_prefix = db_name() + '_'
  
  SELECT 'SELECT setval(pg_get_serial_sequence(''' + @schema_prefix + schema_name(tables.schema_id) + '.' + tables.name + ''', ''' + columns.name + ''')
                 ,(select max(' + columns.name + ') from ' + schema_name(tables.schema_id) + '.' + tables.name + '));'
  FROM sys.tables tables
  JOIN sys.columns columns ON tables.object_id = columns.object_id
  WHERE columns.is_identity = 1
  
  UNION ALL
  
  SELECT 'SELECT setval(pg_get_serial_sequence(''' + @schema_prefix + table_schema + '.' + table_name + ''', 
  ''' + column_name + '''),(select max(' + column_name + ') from ' + table_schema + '.' + table_name + '));'
  FROM information_schema.columns
  WHERE column_default LIKE 'nextval(%';
  ```

  该查询会生成一系列 SELECT 语句，您可以执行这些语句来更新 IDENTITY 和 SERIAL 的最大值。
+ 对于 3.2 之前的 Babelfish 版本，**完整 LOB 模式**可能会导致表错误。如果发生这种情况，请为加载失败的表创建一个单独任务。然后，使用**受限 LOB 模式**为**最大 LOB 大小（KB）** 指定相应的值。另一种选择是设置 SQL Server 端点连接属性设置 `ForceFullLob=True`。
+ 对于 3.2 之前的 Babelfish 版本，如果对不使用基于整数的主键的 Babelfish 表执行数据验证，则会生成一条消息，指出找不到合适的唯一键。从 Aurora PostgreSQL（版本 15.3/14.8 及更高版本）和 Babelfish（版本 3.2.0 及更高版本）开始，支持对非整数主键进行数据验证。
+ 由于秒的小数位数存在精度差异，DMS 会报告使用 `DATETIME` 数据类型的 Babelfish 表的数据验证失败。为避免出现这类失败，可以为 `DATETIME` 数据类型添加以下验证规则类型。

  ```
  {
           "rule-type": "validation",
           "rule-id": "3",
           "rule-name": "3",
           "rule-target": "column",
           "object-locator": {
               "schema-name": "dbo",
               "table-name": "%",
               "column-name": "%",
               "data-type": "datetime"
           },
           "rule-action": "override-validation-function",
           "source-function": "case when ${column-name} is NULL then NULL else 0 end",
           "target-function": "case when ${column-name} is NULL then NULL else 0 end"
       }
  ```