

# 将数据导入 Amazon RDS 上的 PostgreSQL
<a name="PostgreSQL.Procedural.Importing"></a>

假设您要将现有的 PostgreSQL 部署移动到 Amazon RDS 中。任务的复杂性取决于数据库大小以及要传输的数据库对象类型。例如，考虑包含 GB 级别数据集以及存储过程和触发器的数据库。相比只有几个 MB 测试数据并且没有触发器或存储过程的简单数据库，此类数据库要复杂得多。

我们建议您在以下条件下使用本机 PostgreSQL 数据库迁移工具：
+ 您具有一个同类迁移，其中，您正在从一个具有与目标数据库相同的数据库引擎的数据库中迁移。
+ 您正在迁移整个数据库。
+ 利用这些本机工具，您可以在最少的停机时间下迁移您的系统。

在其他大多数情况下，使用 AWS Database Migration Service（AWS DMS）是最佳方法。AWSDMS 可以在不停机的情况下迁移数据库，对于许多数据库引擎，将继续进行持续复制，直到您已准备好切换到目标数据库。您可以使用 AWS DMS 迁移到相同的数据库引擎或其他数据库引擎。如果要迁移到与源数据库不同的数据库引擎，您可以使用 AWS Schema Conversion Tool (AWS SCT)。您可以使用 AWS SCT 迁移 AWS DMS 未迁移的架构对象。有关 AWS DMS 的更多信息，请参阅[什么是 AWS Database Migration Service？](https://docs.aws.amazon.com/dms/latest/userguide/Welcome.html)。

修改数据库参数组以包括以下*仅供您导入* 的设置。您应测试参数设置以查找对数据库实例最有效的设置：在导入完成后，您需要将这些参数还原为生产值。

对数据库实例设置进行以下修改：
+ 禁用数据库实例备份 (将 backup\$1retention 设置为 0)。
+ 禁用多可用区。

修改数据库参数组以包括以下设置。您只应在导入数据时使用这些设置。您应测试参数设置以查找对数据库实例最有效的设置：在导入完成后，您需要将这些参数还原为生产值。


| 参数 | 导入时的建议值 | 描述 | 
| --- | --- | --- | 
|  `maintenance_work_mem`  |  524288、1048576、2097152 或 4194304 (KB)。这些设置相当于 512 MB、1 GB、2 GB 和 4 GB。  |  此设置的只取决于您主机的大小。该参数在 CREATE INDEX 语句中使用，每个并行命令可以使用这个数量的内存。计算最佳值，这样就不会将该值设置得过高而出现内存不足的情况。  | 
|  `max_wal_size`  |  256（适用于 9.6 版本）、4096（适用于 10 及更高版本）  |  允许 WAL 在自动检查点期间增长的最大大小。增大此参数会增加崩溃恢复所需的时间。对于 PostgreSQL 9.6 及更高版本，此参数替代 `checkpoint_segments`。 对于 PostgreSQL 9.6，此值的单位为 16 MB。对于更高版本，此值单位为 1 MB。例如，在 9.6 版本中，128 表示 128 个块，每个块大小为 16 MB。在 12.4 版本中，2048 代表 2048 个块，每个块大小为 1 MB。  | 
|  `checkpoint_timeout`  |  1800  |  此设置的值可以减少 WAL 轮换的频率。  | 
|  `synchronous_commit`  |  Off  |  禁用此设置可加快写入。禁用此参数会在服务器崩溃时增加数据丢失的风险（不禁用 FSYNC）。  | 
|  `wal_buffers`  |   8192  |  该值以 8 KB 为单位。这也有助于您的 WAL 生成速度  | 
|  `autovacuum`  |  0  |  在您加载数据时禁用 PostgreSQL auto vacuum 参数，这样它就不使用资源  | 

将 `pg_dump -Fc` (压缩) 或 `pg_restore -j` (并行) 命令与这些设置结合使用。

**注意**  
PostgreSQL 命令 `pg_dumpall` 所需要的 super\$1user 权限在创建数据库实例时并不授予，因此，无法使用该命令导入数据。

**Topics**
+ [从 Amazon EC2 实例导入 PostgreSQL 数据库](PostgreSQL.Procedural.Importing.EC2.md)
+ [使用 \$1copy 命令将数据导入 PostgreSQL 数据库实例上的表](PostgreSQL.Procedural.Importing.Copy.md)
+ [将 Amazon S3 中的数据导入到 RDS for PostgreSQL 数据库实例](USER_PostgreSQL.S3Import.md)
+ [在数据库实例之间传输 PostgreSQL 数据库](PostgreSQL.TransportableDB.md)

# 从 Amazon EC2 实例导入 PostgreSQL 数据库
<a name="PostgreSQL.Procedural.Importing.EC2"></a>

如果您在 Amazon EC2 实例上的 PostgreSQL 服务器中有数据，并要将其移至 PostgreSQL 数据库实例，则可以按照此过程迁移数据。

1. 使用 pg\$1dump 创建一个文件，其中包含要加载的数据

1. 创建目标数据库实例

1. 使用 *psql* 在数据库实例上创建数据库，然后加载数据

1. 创建该数据库实例的数据库快照

以下各节提供了上述每个步骤的更多详细信息。

## 步骤 1：使用包含要加载的数据的 pg\$1dump 创建文件
<a name="PostgreSQL.Procedural.Importing.EC2.Step1"></a>

`pg_dump` 实用程序使用 COPY 命令创建 PostgreSQL 数据库的架构和数据转储。`pg_dump` 生成的转储脚本将数据加载到一个同名的数据库中，然后重新创建表、索引和外键。您可以使用 `pg_restore` 命令和 `-d` 参数将数据恢复到具有不同的名称的数据库。

在创建数据转储之前，应查询要转储的表以获取行数，以使您可确认目标数据库实例上的数量。

 以下命令为一个名为 mydb2 的数据库创建一个名为 mydb2dump.sql 的转储文件。

```
prompt>pg_dump dbname=mydb2 -f mydb2dump.sql 
```

## 步骤 2：创建目标数据库实例
<a name="PostgreSQL.Procedural.Importing.EC2.Step2"></a>

使用 Amazon RDS 控制台、AWS CLI 或 API 创建目标 PostgreSQL 数据库实例。在备份保留设置为 0 的情况下创建该实例，然后禁用多可用区。这样做可更快地导入数据。您必须先在该实例上创建一个数据库，然后才能转储数据。数据库可以与包含转储数据的数据库具有相同名称。或者，您可以使用其他名称创建数据库。在这种情况下，您使用 `pg_restore` 命令和 `-d` 参数将数据还原到新命名的数据库中。

例如，以下命令可用于转储、还原和重命名数据库。

```
pg_dump -Fc -v -h [endpoint of instance] -U [master username] [database] > [database].dump
createdb [new database name]
pg_restore -v -h [endpoint of instance] -U [master username] -d [new database name] [database].dump
```

## 步骤 3：使用 psql 在数据库实例上创建数据库，然后加载数据
<a name="PostgreSQL.Procedural.Importing.EC2.Step3"></a>

可使用用于运行 pg\$1dump 命令的同一连接，连接到目标数据库实例并重新创建数据库。使用 *psql* 时，可使用主用户名和主密码在数据库实例上创建数据库

以下示例使用 *psql* 和一个名为 mydb2dump.sql 的转储文件，在一个名为 mypginstance 的 PostgreSQL 数据库实例上创建一个名为 mydb2 的数据库：

对于 Linux、macOS 或 Unix：

```
psql \
   -f mydb2dump.sql \
   --host mypginstance.555555555555.aws-region.rds.amazonaws.com \
   --port 8199 \
   --username myawsuser \
   --password password \
   --dbname mydb2
```

对于：Windows

```
psql ^
   -f mydb2dump.sql ^
   --host mypginstance.555555555555.aws-region.rds.amazonaws.com ^
   --port 8199 ^
   --username myawsuser ^
   --password password ^
   --dbname mydb2
```

**注意**  
作为安全最佳实践，请指定除此处所示提示以外的密码。

## 步骤 4：创建数据库实例的数据库快照
<a name="PostgreSQL.Procedural.Importing.EC2.Step4"></a>

确认已将数据加载到数据库实例中后，建议创建目标 PostgreSQL 数据库实例的数据库快照。数据库快照是数据库实例的完整备份，可用于将数据库实例还原到已知状态。通过使用在加载后立即创建的数据库快照，您可以在遇到问题时不必再次加载数据。您也可以使用此类快照创建新的数据库实例。有关创建数据库快照的更多信息，请参阅[为 Amazon RDS 的单可用区数据库实例创建数据库快照](USER_CreateSnapshot.md)。

# 使用 \$1copy 命令将数据导入 PostgreSQL 数据库实例上的表
<a name="PostgreSQL.Procedural.Importing.Copy"></a>

PostgreSQL `\copy` 命令是可从 `psql` 交互式客户端工具获取的元命令，。您可以使用 `\copy` 将数据导入 RDS for PostgreSQL 数据库实例上的表中。若想使用 `\copy` 命令，您需要先在目标数据库实例上创建表结构，以便 `\copy` 具有待复制数据的目标。

您可以使用 `\copy` 从逗号分隔值 (CSV) 文件（如已导出并保存到客户端工作站的文件）中加载数据。

要将 CSV 数据导入目标 RDS for PostgreSQL 数据库实例，请先使用 `psql` 连接至目标数据库实例。

```
psql --host=db-instance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=target-db
```

然后使用以下参数运行 `\copy` 命令来标识数据目标及其格式。
+ `target_table`：应接收从 CSV 文件复制的数据的表名称。
+ `column_list`：表的列规范。
+ `'filename'`：本地工作站上 CSV 文件的完整路径。

```
 \copy target_table from '/path/to/local/filename.csv' WITH DELIMITER ',' CSV;
```

如果 CSV 文件包含列标题信息，则可以使用此版本的命令和参数。

```
\copy target_table (column-1, column-2, column-3, ...)
    from '/path/to/local/filename.csv' WITH DELIMITER ',' CSV HEADER;
```

 如果 `\copy` 命令失败，PostgreSQL 会输出错误消息。

使用 `\copy` 元命令，在数据库预览环境中通过 `psql` 命令创建新的数据库实例，如以下示例所示。该示例使用 *source-table* 作为源表名称，使用 *source-table.csv* 作为 .csv 文件，使用 *target-db* 作为目标数据库：

对于 Linux、macOS 或 Unix：

```
$psql target-db \
    -U <admin user> \
    -p <port> \
    -h <DB instance name> \
    -c "\copy source-table from 'source-table.csv' with DELIMITER ','"
```

对于：Windows

```
$psql target-db ^
    -U <admin user> ^
    -p <port> ^
    -h <DB instance name> ^
    -c "\copy source-table from 'source-table.csv' with DELIMITER ','"
```

有关 `\copy` 命令的完整详细信息，请参阅 PostgreSQL 文档中 *psql* 页面内的[元命令](http://www.postgresql.org/docs/current/static/app-psql.html)部分。

# 将 Amazon S3 中的数据导入到 RDS for PostgreSQL 数据库实例
<a name="USER_PostgreSQL.S3Import"></a>

您可以将已使用 Amazon Simple Storage Service 存储的数据导入到 RDS for PostgreSQL 数据库实例上的表中。为此，您首先要安装 RDS for PostgreSQL `aws_s3` 扩展。该扩展提供用于从 AmazonS3 桶导入数据的函数。*桶* 是用于存储对象和文件的 Amazon S3 容器。数据可以位于逗号分隔值（CSV）文件、文本文件或压缩（gzip）文件中。接下来，您可以了解如何安装扩展以及如何将数据从 Amazon S3 导入到表中。

要从 Amazon S3 导入到 RDS for PostgreSQL，您的数据库必须运行 PostgreSQL 版本 10.7 或更高版本。。

如果您没有将数据存储在 Amazon S3 上，则需要先创建桶并存储数据。有关更多信息，请参阅《Amazon Simple Storage Service 用户指南》中的以下主题。
+ [创建存储桶](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html#creating-bucket)
+ [向存储桶添加对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html#uploading-an-object-bucket) 

支持从 Amazon S3 跨账户导入。有关更多信息，请参阅《Amazon Simple Storage Service 用户指南》**中的[授予跨账户权限](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-walkthroughs-managing-access-example2.html)。

从 S3 导入数据时，您可以使用客户托管式密钥进行加密。有关更多信息，请参阅《Amazon Simple Storage Service 用户指南》**中的 [AWS KMS 中存储的 KMS 密钥](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html)。

**Topics**
+ [安装 aws\$1s3 扩展名](USER_PostgreSQL.S3Import.InstallExtension.md)
+ [从 Amazon S3 数据导入数据概述](USER_PostgreSQL.S3Import.Overview.md)
+ [设置 Amazon S3 存储桶的访问权限](USER_PostgreSQL.S3Import.AccessPermission.md)
+ [将数据从 Amazon S3 导入到 RDS for PostgreSQL 数据库实例](USER_PostgreSQL.S3Import.FileFormats.md)
+ [函数参考](USER_PostgreSQL.S3Import.Reference.md)

# 安装 aws\$1s3 扩展名
<a name="USER_PostgreSQL.S3Import.InstallExtension"></a>

在将 Amazon S3 用于 RDS for PostgreSQL 数据库实例之前，您需要安装 `aws_s3` 扩展。此扩展提供从 Amazon S3 导入数据的函数。它还提供将数据从 RDS for PostgreSQL 数据库实例中导出到 Amazon S3 桶的函数。有关更多信息，请参阅 [将数据从 RDS for PostgreSQL 数据库实例导出到 Amazon S3](postgresql-s3-export.md)。`aws_s3` 扩展依赖于 `aws_commons` 扩展（需要时自动安装）中的一些帮助程序函数。

**安装 `aws_s3` 扩展**

1. 使用 psql（或 pgAdmin）以具有 `rds_superuser` 权限的用户身份，连接到 RDS for PostgreSQL 数据库实例。如果您在设置过程中保留原定设置名称，则以 `postgres` 进行连接。

   ```
   psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

1. 要安装扩展，请运行以下命令。

   ```
   postgres=> CREATE EXTENSION aws_s3 CASCADE;
   NOTICE: installing required extension "aws_commons"
   CREATE EXTENSION
   ```

1. 要验证扩展是否已安装，可以使用 psql `\dx` 元命令。

   ```
   postgres=> \dx
          List of installed extensions
       Name     | Version |   Schema   |                 Description
   -------------+---------+------------+---------------------------------------------
    aws_commons | 1.2     | public     | Common data types across AWS services
    aws_s3      | 1.1     | public     | AWS S3 extension for importing data from S3
    plpgsql     | 1.0     | pg_catalog | PL/pgSQL procedural language
   (3 rows)
   ```

从 Amazon S3 导入数据和将数据导出到 Amazon S3 的函数现在可供使用。

# 从 Amazon S3 数据导入数据概述
<a name="USER_PostgreSQL.S3Import.Overview"></a>

**将 S3 数据导入到 Amazon RDS**

首先，收集您需要为该函数提供的详细信息。其中包括 RDS for PostgreSQL 数据库实例上的表名称、桶名称、文件路径、文件类型以及存储 Amazon S3 数据的 AWS 区域。有关更多信息，请参阅《Amazon Simple Storage Service 用户指南》**中的[查看对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/OpeningAnObject.html)。
**注意**  
目前不支持从 Amazon S3 导入分段数据。

1. 获取 `aws_s3.table_import_from_s3` 函数要向其中导入数据的表的名称。例如，以下命令创建表 `t1`，供在后面的步骤中使用。

   ```
   postgres=> CREATE TABLE t1 
       (col1 varchar(80), 
       col2 varchar(80), 
       col3 varchar(80));
   ```

1. 获取有关 Amazon S3 桶和要导入的数据的详细信息。为此，请通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)，然后选择 **Buckets**（桶）。在列表中找到包含您的数据的桶。选择桶，打开其 Object overview（对象概述）页面，然后选择 Properties（属性）。

   记下桶名称、路径、AWS 区域和文件类型。您稍后需要提供 Amazon 资源名称（ARN），以便通过 IAM 角色设置对 Amazon S3 的访问权限。有关更多信息，请参阅[设置 Amazon S3 存储桶的访问权限](USER_PostgreSQL.S3Import.AccessPermission.md)。下图显示了一个示例。  
![\[Amazon S3 桶中的文件对象的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/aws_s3_import-export_s3_bucket-info.png)

1. 您可以使用 AWS CLI 命令 `aws s3 cp` 验证 AmazonS3 桶上数据的路径。如果该信息正确无误，该命令将下载 Amazon S3 文件的副本。

   ```
   aws s3 cp s3://amzn-s3-demo-bucket/sample_file_path ./ 
   ```

1. 在 RDS for PostgreSQL 数据库实例上设置权限，以允许访问 Amazon S3 桶中的文件。为此，您可以使用 AWS Identity and Access Management（IAM）角色或安全凭证。有关更多信息，请参阅 [设置 Amazon S3 存储桶的访问权限](USER_PostgreSQL.S3Import.AccessPermission.md)。

1. 将收集的路径和其他 Amazon S3 对象详细信息（请参阅步骤 2）提供给用于构造 Amazon S3 URI 对象的 `create_s3_uri` 函数。要了解有关此函数的更多信息，请参阅[aws\$1commons.create\$1s3\$1uri](USER_PostgreSQL.S3Import.Reference.md#USER_PostgreSQL.S3Import.create_s3_uri)。以下是在 psql 会话期间构造此对象的示例。

   ```
   postgres=> SELECT aws_commons.create_s3_uri(
      'docs-lab-store-for-rpg',
      'versions_and_jdks_listing.csv',
      'us-west-1'
   ) AS s3_uri \gset
   ```

   在下一步中，您将此对象（`aws_commons._s3_uri_1`）传递到 `aws_s3.table_import_from_s3` 函数，以便将数据导入表中。

1. 调用 `aws_s3.table_import_from_s3` 函数，以将数据从 Amazon S3 导入到您的表中。有关参考信息，请参阅[aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3)。有关示例，请参阅 [将数据从 Amazon S3 导入到 RDS for PostgreSQL 数据库实例](USER_PostgreSQL.S3Import.FileFormats.md)。

# 设置 Amazon S3 存储桶的访问权限
<a name="USER_PostgreSQL.S3Import.AccessPermission"></a>

要从 Amazon S3 文件中导入数据，请为 RDS for PostgreSQL 数据库实例提供权限以访问包含该文件的 Amazon S3 存储桶。您可以通过两种方式提供 Amazon S3 存储桶的访问权限，如以下主题中所述。

**Topics**
+ [使用 IAM 角色访问 Amazon S3 存储桶](#USER_PostgreSQL.S3Import.ARNRole)
+ [使用安全凭证访问 Amazon S3 存储桶](#USER_PostgreSQL.S3Import.Credentials)
+ [Amazon S3 访问故障排除](#USER_PostgreSQL.S3Import.troubleshooting)

## 使用 IAM 角色访问 Amazon S3 存储桶
<a name="USER_PostgreSQL.S3Import.ARNRole"></a>

从 Amazon S3 文件中加载数据之前，请为 RDS for PostgreSQL 数据库实例提供权限以访问该文件所在的 Amazon S3 存储桶。这样，您无需管理其他凭证信息或在 [aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3) 函数调用中提供该信息。

为此，请创建一个 IAM 策略以提供 Amazon S3 存储桶的访问权限。创建一个 IAM 角色并将策略附加到该角色。然后，将该 IAM 角色分配给数据库实例。

**通过 IAM 角色向 RDS for PostgreSQL 数据库实例授予访问 Amazon S3 的权限**

1. 创建一个 IAM 策略。

   该策略提供存储桶和对象权限，以允许 RDS for PostgreSQL 数据库实例访问 Amazon S3。

   在策略中包含以下必需操作，以允许将文件从 Amazon S3 存储桶传输到 Amazon RDS：
   + `s3:GetObject` 
   + `s3:ListBucket` 

   在策略中包含以下资源以标识 Amazon S3 存储桶以及存储桶中的对象。这会显示用于访问 Amazon S3 的 Amazon Resource Name (ARN) 格式。
   + arn:aws:s3:::*amzn-s3-demo-bucket*
   + arn:aws:s3:::*amzn-s3-demo-bucket*/\$1

   有关为 RDS for PostgreSQL 创建 IAM policy 的更多信息，请参阅[创建和使用适用于 IAM 数据库访问的 IAM 策略](UsingWithRDS.IAMDBAuth.IAMPolicy.md)。另请参阅 *IAM 用户指南*中的[教程：创建和附加您的第一个客户托管策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_managed-policies.html)。

   以下 AWS CLI 命令使用这些选项创建一个名为 `rds-s3-import-policy` 的 IAM 策略。该策略授予对名为 *amzn-s3-demo-bucket* 的存储桶的访问权限。
**注意**  
记下此命令返回的策略的 Amazon 资源名称（ARN）。在后续步骤中将策略附加到 IAM 角色时，您需要此 ARN。  
**Example**  

   对于 Linux、macOS 或 Unix：

   ```
   aws iam create-policy \
      --policy-name rds-s3-import-policy \
      --policy-document '{
        "Version": "2012-10-17",		 	 	 
        "Statement": [
          {
            "Sid": "s3import",
            "Action": [
              "s3:GetObject",
              "s3:ListBucket"
            ],
            "Effect": "Allow",
            "Resource": [
              "arn:aws:s3:::amzn-s3-demo-bucket", 
              "arn:aws:s3:::amzn-s3-demo-bucket/*"
            ] 
          }
        ] 
      }'
   ```

   对于：Windows

   ```
   aws iam create-policy ^
      --policy-name rds-s3-import-policy ^
      --policy-document '{
        "Version": "2012-10-17",		 	 	 
        "Statement": [
          {
            "Sid": "s3import",
            "Action": [
              "s3:GetObject",
              "s3:ListBucket"
            ], 
            "Effect": "Allow",
            "Resource": [
              "arn:aws:s3:::amzn-s3-demo-bucket", 
              "arn:aws:s3:::amzn-s3-demo-bucket/*"
            ] 
          }
        ] 
      }'
   ```

1. 创建 IAM 角色。

   这样，Amazon RDS 就可以担任该 IAM 角色以访问您的 Amazon S3 存储桶。有关更多信息，请参阅《IAM 用户指南》**中的[创建向 IAM 用户委派权限的角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user.html)。

   我们建议在基于资源的策略中使用 `[aws:SourceArn](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn)` 和 `[aws:SourceAccount](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourceaccount)` 全局条件上下文键，以限制对特定资源的服务权限。这是防范[混淆代理人问题](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)最有效的方法。

   如果同时使用全局条件上下文键和包含账户 ID 的 `aws:SourceArn` 值，则 `aws:SourceAccount` 值和 `aws:SourceArn` 值中的账户在同一策略语句中使用时，必须使用相同的账户 ID。
   + 如果您想对单个资源进行跨服务访问，请使用 `aws:SourceArn`。
   + 如果您想允许该账户中的任何资源与跨服务使用操作相关联，请使用 `aws:SourceAccount`。

   在策略中，确保使用具有资源的完整 ARN 的 `aws:SourceArn` 全局条件上下文键。以下示例说明了如何使用 AWS CLI 命令创建一个名为 `rds-s3-import-role` 的角色来实现该目的。  
**Example**  

   对于 Linux、macOS 或 Unix：

   ```
   aws iam create-role \
      --role-name rds-s3-import-role \
      --assume-role-policy-document '{
        "Version": "2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
               "Service": "rds.amazonaws.com"
             },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                   "aws:SourceAccount": "111122223333",
                   "aws:SourceArn": "arn:aws:rds:us-east-1:111122223333:db:dbname"
                   }
                }
          }
        ] 
      }'
   ```

   对于：Windows

   ```
   aws iam create-role ^
      --role-name rds-s3-import-role ^
      --assume-role-policy-document '{
        "Version": "2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
               "Service": "rds.amazonaws.com"
             },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                   "aws:SourceAccount": "111122223333",
                   "aws:SourceArn": "arn:aws:rds:us-east-1:111122223333:db:dbname"
                   }
                }
          }
        ] 
      }'
   ```

1. 将您创建的 IAM 策略附加到您创建的 IAM 角色。

   以下 AWS CLI 命令将上一步中创建的策略附加到一个名为 `rds-s3-import-role` 的角色。请将 `your-policy-arn` 替换为您在前面的步骤中记下的策略 ARN。  
**Example**  

   对于 Linux、macOS 或 Unix：

   ```
   aws iam attach-role-policy \
      --policy-arn your-policy-arn \
      --role-name rds-s3-import-role
   ```

   对于：Windows

   ```
   aws iam attach-role-policy ^
      --policy-arn your-policy-arn ^
      --role-name rds-s3-import-role
   ```

1. 将该 IAM 角色添加到数据库实例中。

   您可以使用 AWS 管理控制台 或 AWS CLI 执行该操作，如下所述。

### 控制台
<a name="collapsible-section-1"></a>

**使用控制台为 PostgreSQL 数据库实例添加 IAM 角色**

1. 登录AWS 管理控制台并通过以下网址打开 Amazon RDS 控制台：[https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)。

1. 选择 PostgreSQL 数据库实例名称以显示其详细信息。

1. 在**连接性和安全性**选项卡上的**管理 IAM 角色**部分中，在**向此实例添加 IAM 角色**下选择要添加的角色。

1. 在 **Feature (功能)** 下，选择 **s3Import**。

1. 选择 **Add role (添加角色)**。

### AWS CLI
<a name="collapsible-section-2"></a>

**使用 CLI 为 PostgreSQL 数据库实例添加 IAM 角色**
+ 使用以下命令将角色添加到名为 `my-db-instance` 的 PostgreSQL 数据库实例中。将 *`your-role-arn`* 替换为您在上一步中记下的角色 ARN。使用 `s3Import` 作为 `--feature-name` 选项的值。  
**Example**  

  对于 Linux、macOS 或 Unix：

  ```
  aws rds add-role-to-db-instance \
     --db-instance-identifier my-db-instance \
     --feature-name s3Import \
     --role-arn your-role-arn   \
     --region your-region
  ```

  对于：Windows

  ```
  aws rds add-role-to-db-instance ^
     --db-instance-identifier my-db-instance ^
     --feature-name s3Import ^
     --role-arn your-role-arn ^
     --region your-region
  ```

### RDS API
<a name="collapsible-section-3"></a>

要使用 Amazon RDS API 为 PostgreSQL 数据库实例添加 IAM 角色，请调用 [ AddRoleToDBInstance](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_AddRoleToDBInstance.html) 操作。

## 使用安全凭证访问 Amazon S3 存储桶
<a name="USER_PostgreSQL.S3Import.Credentials"></a>

如果愿意，您可以使用安全凭证提供 Amazon S3 存储桶的访问权限，而不是使用 IAM 角色提供访问权限。这可以通过在 [aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3) 函数调用中指定 `credentials` 参数来实现。

`credentials` 参数是 `aws_commons._aws_credentials_1` 类型的结构，其中包含 AWS 凭证。使用 [aws\$1commons.create\$1aws\$1credentials](USER_PostgreSQL.S3Import.Reference.md#USER_PostgreSQL.S3Import.create_aws_credentials) 函数设置 `aws_commons._aws_credentials_1` 结构中的访问密钥和私有密钥，如下所示。

```
postgres=> SELECT aws_commons.create_aws_credentials(
   'sample_access_key', 'sample_secret_key', '')
AS creds \gset
```

在创建 `aws_commons._aws_credentials_1 ` 结构后，请将 [aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3) 函数与 `credentials` 参数结合使用来导入数据，如下所示。

```
postgres=> SELECT aws_s3.table_import_from_s3(
   't', '', '(format csv)',
   :'s3_uri', 
   :'creds'
);
```

也可以在 [aws\$1commons.create\$1aws\$1credentials](USER_PostgreSQL.S3Import.Reference.md#USER_PostgreSQL.S3Import.create_aws_credentials) 函数调用中以内联方式包括 `aws_s3.table_import_from_s3` 函数调用。

```
postgres=> SELECT aws_s3.table_import_from_s3(
   't', '', '(format csv)',
   :'s3_uri', 
   aws_commons.create_aws_credentials('sample_access_key', 'sample_secret_key', '')
);
```

## Amazon S3 访问故障排除
<a name="USER_PostgreSQL.S3Import.troubleshooting"></a>

如果在尝试从 Amazon S3 导入数据时遇到连接问题，请参阅以下内容以了解相应的建议：
+ [对 Amazon RDS 身份和访问权限问题进行故障排除](security_iam_troubleshoot.md)
+ *Amazon Simple Storage Service 用户指南*中的[排查 Amazon S3 的问题](https://docs.aws.amazon.com/AmazonS3/latest/userguide/troubleshooting.html)
+ *IAM 用户指南*中的[排查 Amazon S3 和 IAM 的问题](https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_iam-s3.html)

# 将数据从 Amazon S3 导入到 RDS for PostgreSQL 数据库实例
<a name="USER_PostgreSQL.S3Import.FileFormats"></a>

您可以使用 aws\$1S3 扩展的 `table_import_from_s3` 函数从 Amazon S3 桶导入数据。有关参考信息，请参阅[aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3)。

**注意**  
以下示例使用 IAM 角色方法以允许访问 Amazon S3 桶。因此，`aws_s3.table_import_from_s3` 函数调用不包括凭据参数。

下面显示典型示例。

```
postgres=> SELECT aws_s3.table_import_from_s3(
   't1',
   '', 
   '(format csv)',
   :'s3_uri'
);
```

下面是参数：
+ `t1` – 将数据复制到的 PostgreSQL 数据库实例中的表的名称。
+ `''` – 数据库表中的列的可选列表。您可以使用此参数来指示哪些 S3 数据列进入哪些表列中。如果未指定任何列，则会将所有列复制到表中。有关使用列列表的示例，请参阅 [导入使用自定义分隔符的 Amazon S3 文件](#USER_PostgreSQL.S3Import.FileFormats.CustomDelimiter)。
+ `(format csv)` – PostgreSQL COPY 参数。复制过程使用 [PostgreSQL COPY](https://www.postgresql.org/docs/current/sql-copy.html) 命令的参数和格式以导入数据。格式选择包括本例中所示的逗号分隔值（CSV），以及文本和二进制。原定设置为文本。
+  `s3_uri` – 包含标识 Amazon S3 文件的信息的结构。有关使用 [aws\$1commons.create\$1s3\$1uri](USER_PostgreSQL.S3Import.Reference.md#USER_PostgreSQL.S3Import.create_s3_uri) 函数创建 `s3_uri` 结构的示例，请参阅 [从 Amazon S3 数据导入数据概述](USER_PostgreSQL.S3Import.Overview.md)。

有关此函数的更多信息，请参阅 [aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3)。

`aws_s3.table_import_from_s3` 函数返回文本。要指定要从 Amazon S3 存储桶中导入的其他类型的文件，请参阅以下示例之一。

**注意**  
导入 0 字节文件将导致错误。

**Topics**
+ [导入使用自定义分隔符的 Amazon S3 文件](#USER_PostgreSQL.S3Import.FileFormats.CustomDelimiter)
+ [导入 Amazon S3 压缩 (gzip) 文件](#USER_PostgreSQL.S3Import.FileFormats.gzip)
+ [导入编码的 Amazon S3 文件](#USER_PostgreSQL.S3Import.FileFormats.Encoded)

## 导入使用自定义分隔符的 Amazon S3 文件
<a name="USER_PostgreSQL.S3Import.FileFormats.CustomDelimiter"></a>

以下示例说明了如何导入使用自定义分隔符的文件。它还说明如何使用 `column_list` 函数的 [aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3) 参数来控制将数据放置在数据库表中的哪个位置。

在此示例中，假定将以下信息组织到 Amazon S3 文件中的竖线分隔列中。

```
1|foo1|bar1|elephant1
2|foo2|bar2|elephant2
3|foo3|bar3|elephant3
4|foo4|bar4|elephant4
...
```

**导入使用自定义分隔符的文件**

1. 在数据库中为导入的数据创建一个表。

   ```
   postgres=> CREATE TABLE test (a text, b text, c text, d text, e text);
   ```

1. 使用以下形式的 [aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3) 函数从 Amazon S3 文件导入数据。

   您可以在 [aws\$1commons.create\$1s3\$1uri](USER_PostgreSQL.S3Import.Reference.md#USER_PostgreSQL.S3Import.create_s3_uri) 函数调用中以内联方式包括 `aws_s3.table_import_from_s3` 函数调用来指定文件。

   ```
   postgres=> SELECT aws_s3.table_import_from_s3(
      'test',
      'a,b,d,e',
      'DELIMITER ''|''', 
      aws_commons.create_s3_uri('amzn-s3-demo-bucket', 'pipeDelimitedSampleFile', 'us-east-2')
   );
   ```

数据现在位于表的以下列中。

```
postgres=> SELECT * FROM test;
a | b | c | d | e 
---+------+---+---+------+-----------
1 | foo1 | | bar1 | elephant1
2 | foo2 | | bar2 | elephant2
3 | foo3 | | bar3 | elephant3
4 | foo4 | | bar4 | elephant4
```

## 导入 Amazon S3 压缩 (gzip) 文件
<a name="USER_PostgreSQL.S3Import.FileFormats.gzip"></a>

以下示例说明如何从 Amazon S3 导入使用 gzip 压缩的文件。导入的文件需要具有以下 Amazon S3 元数据：
+ 键：`Content-Encoding`
+ 值：`gzip`

如果使用 AWS 管理控制台 上传文件，则元数据通常由系统应用。有关使用 AWS 管理控制台、AWS CLI 或 API 将文件上传到 Amazon S3 的信息，请参阅《Amazon Simple Storage Service 用户指南**》中的[上传对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html)。

有关 Amazon S3 元数据的更多信息以及有关系统提供的元数据的详细信息，请参阅《Amazon Simple Storage Service 用户指南**》中的[在 Amazon S3 控制台中编辑对象元数据](https://docs.aws.amazon.com/AmazonS3/latest/userguide/add-object-metadata.html)。

将 gzip 文件导入到 RDS for PostgreSQL 数据库实例，如下所示。

```
postgres=> CREATE TABLE test_gzip(id int, a text, b text, c text, d text);
postgres=> SELECT aws_s3.table_import_from_s3(
 'test_gzip', '', '(format csv)',
 'amzn-s3-demo-bucket', 'test-data.gz', 'us-east-2'
);
```

## 导入编码的 Amazon S3 文件
<a name="USER_PostgreSQL.S3Import.FileFormats.Encoded"></a>

以下示例说明如何从 Amazon S3 导入具有 Windows-1252 编码的文件。

```
postgres=> SELECT aws_s3.table_import_from_s3(
 'test_table', '', 'encoding ''WIN1252''',
 aws_commons.create_s3_uri('amzn-s3-demo-bucket', 'SampleFile', 'us-east-2')
);
```

# 函数参考
<a name="USER_PostgreSQL.S3Import.Reference"></a>

**Topics**
+ [aws\$1s3.table\$1import\$1from\$1s3](#aws_s3.table_import_from_s3)
+ [aws\$1commons.create\$1s3\$1uri](#USER_PostgreSQL.S3Import.create_s3_uri)
+ [aws\$1commons.create\$1aws\$1credentials](#USER_PostgreSQL.S3Import.create_aws_credentials)

## aws\$1s3.table\$1import\$1from\$1s3
<a name="aws_s3.table_import_from_s3"></a>

将 Amazon S3 数据导入到 Amazon RDS 表中。`aws_s3` 扩展提供 `aws_s3.table_import_from_s3` 函数。返回值为文本。

### 语法
<a name="aws_s3.table_import_from_s3-syntax"></a>

必需的参数为 `table_name`、`column_list` 和 `options`。这些标识数据库表并指定如何将数据复制到表中。

您还可以使用以下参数：
+ `s3_info` 参数指定要导入的 Amazon S3 文件。在您使用此参数时，IAM 角色为 PostgreSQL 数据库实例提供访问 Amazon S3 的权限。

  ```
  aws_s3.table_import_from_s3 (
     table_name text, 
     column_list text, 
     options text, 
     s3_info aws_commons._s3_uri_1
  )
  ```
+ `credentials` 参数指定凭证以访问 Amazon S3。在您使用此参数时，不使用 IAM 角色。

  ```
  aws_s3.table_import_from_s3 (
     table_name text, 
     column_list text, 
     options text, 
     s3_info aws_commons._s3_uri_1,
     credentials aws_commons._aws_credentials_1
  )
  ```

### 参数
<a name="aws_s3.table_import_from_s3-parameters"></a>

 *table\$1name*   
包含要将数据导入到的 PostgreSQL 数据库表的名称的必需文本字符串。

 *column\$1list*   
包含要将数据复制到的 PostgreSQL 数据库表列的可选列表的必需文本字符串。如果此字符串为空，将使用表的所有列。有关示例，请参阅[导入使用自定义分隔符的 Amazon S3 文件](USER_PostgreSQL.S3Import.FileFormats.md#USER_PostgreSQL.S3Import.FileFormats.CustomDelimiter)。

 *选项*   
包含 PostgreSQL `COPY` 命令的参数的必需文本字符串。这些参数指定如何将数据复制到 PostgreSQL 表中。有关更多详细信息，请参阅 [PostgreSQL COPY 文档](https://www.postgresql.org/docs/current/sql-copy.html)。

 *s3\$1info*   
包含有关 S3 对象的以下信息的 `aws_commons._s3_uri_1` 复合类型：  
+ `bucket` – 包含文件的 Amazon S3 存储桶的名称。
+ `file_path` – 包含文件路径的 Amazon S3 文件名。
+ `region` – 文件所在的AWS区域。有关 AWS 区域名称和关联值的列表，请参阅[区域、可用区和 Local Zones ](Concepts.RegionsAndAvailabilityZones.md)。

 *凭证*   
包含以下用于导入操作的凭证的 `aws_commons._aws_credentials_1` 复合类型：  
+ 访问密钥
+ 私有密钥
+ 会话令牌
有关创建 `aws_commons._aws_credentials_1` 复合结构的信息，请参阅 [aws\$1commons.create\$1aws\$1credentials](#USER_PostgreSQL.S3Import.create_aws_credentials)。

### 替代语法
<a name="aws_s3.table_import_from_s3-alternative-syntax"></a>

为帮助进行测试，您可以使用一组扩展的参数而非 `s3_info` 和 `credentials` 参数。下面是 `aws_s3.table_import_from_s3` 函数的其他语法变化。
+ 不使用 `s3_info` 参数来标识 Amazon S3 文件，而使用 `bucket`、`file_path` 和 `region` 参数的组合。使用此形式的函数，IAM 角色在 PostgreSQL 数据库实例上提供访问 Amazon S3 的权限。

  ```
  aws_s3.table_import_from_s3 (
     table_name text, 
     column_list text, 
     options text, 
     bucket text, 
     file_path text, 
     region text 
  )
  ```
+ 不使用 `credentials` 参数来指定 Amazon S3 访问权限，而使用 `access_key`、`session_key` 和 `session_token` 参数的组合。

  ```
  aws_s3.table_import_from_s3 (
     table_name text, 
     column_list text, 
     options text, 
     bucket text, 
     file_path text, 
     region text, 
     access_key text, 
     secret_key text, 
     session_token text 
  )
  ```

### 替代参数
<a name="aws_s3.table_import_from_s3-alternative-parameters"></a>

*bucket*  
包含 Amazon S3 存储桶（其中包含文件）的名称的文本字符串。

*file\$1path*  
包含 Amazon S3 文件名（包含文件路径）的文本字符串。

*region*  
标识文件的 AWS 区域位置的文本字符串。有关 AWS 区域名称和关联值的列表，请参阅[区域、可用区和 Local Zones ](Concepts.RegionsAndAvailabilityZones.md)。

*access\$1key*  
包含用于导入操作的访问密钥的文本字符串。默认值为 NULL。

*secret\$1key*  
包含用于导入操作的私有密钥的文本字符串。默认值为 NULL。

*session\$1token*  
（可选）包含用于导入操作的会话密钥的文本字符串。默认值为 NULL。

## aws\$1commons.create\$1s3\$1uri
<a name="USER_PostgreSQL.S3Import.create_s3_uri"></a>

创建 `aws_commons._s3_uri_1` 结构来保存 Amazon S3 文件信息。在 `aws_commons.create_s3_uri` 函数的 `s3_info` 参数中使用 [aws\$1s3.table\$1import\$1from\$1s3](#aws_s3.table_import_from_s3) 函数的结果。

### 语法
<a name="USER_PostgreSQL.S3Import.create_s3_uri-syntax"></a>

```
aws_commons.create_s3_uri(
   bucket text,
   file_path text,
   region text
)
```

### 参数
<a name="USER_PostgreSQL.S3Import.create_s3_uri-parameters"></a>

*bucket*  
包含文件的 Amazon S3 存储桶名称的必需文本字符串。

*file\$1path*  
包含 Amazon S3 文件名（包含文件路径）的必填文本字符串。

*region*  
一个包含文件所在的 AWS 区域的必需文本字符串。有关 AWS 区域名称和关联值的列表，请参阅[区域、可用区和 Local Zones ](Concepts.RegionsAndAvailabilityZones.md)。

## aws\$1commons.create\$1aws\$1credentials
<a name="USER_PostgreSQL.S3Import.create_aws_credentials"></a>

在 `aws_commons._aws_credentials_1` 结构中设置访问密钥和私有密钥。在 `aws_commons.create_aws_credentials` 函数的 `credentials` 参数中使用 [aws\$1s3.table\$1import\$1from\$1s3](#aws_s3.table_import_from_s3) 函数的结果。

### 语法
<a name="USER_PostgreSQL.S3Import.create_aws_credentials-syntax"></a>

```
aws_commons.create_aws_credentials(
   access_key text,
   secret_key text,
   session_token text
)
```

### 参数
<a name="USER_PostgreSQL.S3Import.create_aws_credentials-parameters"></a>

*access\$1key*  
包含用于导入 Amazon S3 文件的访问密钥的必需文本字符串。默认值为 NULL。

*secret\$1key*  
包含用于导入 Amazon S3 文件的私有密钥的必需文本字符串。默认值为 NULL。

*session\$1token*  
包含用于导入 Amazon S3 文件的会话令牌的可选文本字符串。默认值为 NULL。如果您提供了可选的 `session_token`，则可以使用临时凭证。

# 在数据库实例之间传输 PostgreSQL 数据库
<a name="PostgreSQL.TransportableDB"></a>

通过将 PostgreSQL 可传输数据库用于 Amazon RDS，您可以在两个数据库实例之间传输 PostgreSQL 数据库。这是在不同数据库实例之间迁移大型数据库的一种非常快的方法。要使用该方法，两个数据库实例必须运行相同的 PostgreSQL 主要版本。

此功能要求您在源和目标数据库实例上均安装 `pg_transport` 扩展。`pg_transport` 扩展提供了一种以最少的处理来移动数据库文件的物理传输机制。该机制移动数据的速度比传统的转储和加载过程快得多，并减少了停机时间。

**注意**  
PostgreSQL 可传输数据库在 RDS for PostgreSQL 11.5 和更高版本以及 RDS for PostgreSQL 版本 10.10 和更高版本中提供。

要将 PostgreSQL 数据库实例从一个 RDS for PostgreSQL 数据库实例传输到另一个，首先设置源实例和目标实例，如 [ 设置数据库实例以进行传输](PostgreSQL.TransportableDB.Setup.md) 中详述。然后，您可以使用 [ 传输 PostgreSQL 数据库](PostgreSQL.TransportableDB.Transporting.md) 中所述的函数传输数据库。

**Topics**
+ [在数据库传输期间发生的情况](#PostgreSQL.TransportableDB.DuringTransport)
+ [使用 PostgreSQL 可传输数据库的限制](#PostgreSQL.TransportableDB.Limits)
+ [设置以传输 PostgreSQL 数据库](PostgreSQL.TransportableDB.Setup.md)
+ [将 PostgreSQL 数据库从源传输到目标](PostgreSQL.TransportableDB.Transporting.md)
+ [可传输数据库函数参考](PostgreSQL.TransportableDB.transport.import_from_server.md)
+ [可传输数据库参数参考](PostgreSQL.TransportableDB.Parameters.md)

## 在数据库传输期间发生的情况
<a name="PostgreSQL.TransportableDB.DuringTransport"></a>

PostgreSQL 可传输数据库功能使用拉取模式，将数据库从源数据库实例导入到目标数据库实例。`transport.import_from_server` 函数在目标数据库实例上创建传输中的数据库。在传输期间，无法在目标数据库实例上访问传输中的数据库。

在传输开始时，源数据库上的所有当前会话将会结束。源数据库实例上的源数据库以外的任何数据库不受传输影响。

源数据库被置于特殊只读模式。在处于该模式时，您可以连接到源数据库并运行只读查询。不过，阻止启用了写入的查询和某些其他类型的命令。仅正在传输的特定源数据库受这些限制的影响。

在传输期间，您无法将目标数据库实例还原到某个时间点。这是因为传输不是事务性的，并且不使用 PostgreSQL 预写日志记录更改。如果目标数据库实例启用了自动备份，则会在传输完成后自动创建备份。时间点还原适用于备份完成*后*的时间。

如果传输失败，`pg_transport` 扩展将尝试撤消对源和目标数据库实例的所有更改。这包括删除目标的部分传输的数据库。根据失败类型，源数据库可能会继续拒绝启用了写入的查询。如果发生这种情况，请使用以下命令允许启用了写入的查询。

```
ALTER DATABASE db-name SET default_transaction_read_only = false;
```

## 使用 PostgreSQL 可传输数据库的限制
<a name="PostgreSQL.TransportableDB.Limits"></a>

可传输数据库具有以下限制：
+ **只读副本** – 您无法在只读副本或只读副本的父实例上使用可传输数据库。
+ **不支持的列类型** – 您不能在打算使用该方法传输的任何数据库表中使用 `reg` 数据类型。这些类型取决于系统目录对象 ID (OID)，这些 ID 在传输过程中经常发生变化。
+ **表空间** – 所有源数据库对象必须位于默认 `pg_default` 表空间中。
+ **兼容性** – 源和目标数据库实例必须运行相同的 PostgreSQL 主要版本。
+ **扩展** - 源数据库实例只能安装 `pg_transport`。
+ **角色和 ACL** – 源数据库的访问权限和所有权信息不会传输到目标数据库。所有数据库对象是由传输的本地目标用户创建和拥有的。
+ **并发传输** - 如果工件线程进程配置正确，单个数据库实例最多可支持 32 个并发传输，包括导入和导出。
+ **仅限 RDS for PostgreSQL 数据库实例** - PostgreSQL 可传输数据库仅在 RDS for PostgreSQL 数据库实例上支持。您不能将其与 Amazon EC2 上运行的本地数据库或数据库一起使用。

# 设置以传输 PostgreSQL 数据库
<a name="PostgreSQL.TransportableDB.Setup"></a>

在开始之前，请确保您的 RDS for PostgreSQL 数据库实例满足以下要求：
+ 源和目标 RDS for PostgreSQL 数据库实例必须运行相同的 PostgreSQL 版本。
+ 目标数据库不能拥有与要传输的源数据库同名的数据库。
+ 您用来运行传输的账户需要源数据库和目标数据库的 `rds_superuser` 权限。
+ 源数据库实例的安全组必须允许来自目标数据库实例的入站访问。如果源和目标数据库实例均位于 VPC 中，则可能已经是这种情况。有关安全组的更多信息，请参阅 [使用安全组控制访问权限](Overview.RDSSecurityGroups.md)。

将数据库从源数据库实例传输到目标数据库实例需要对与每个实例关联的数据库参数组进行若干更改。这意味着您必须为源数据库实例创建自定义数据库参数组，同时为目标数据库实例创建自定义数据库参数组。

**注意**  
如果您的数据库实例已使用自定义数据库参数组进行配置，则可以从以下过程中的步骤 2 开始。

**配置用于传输数据库的自定义数据库组参数**

对于以下步骤，请使用具有 `rds_superuser` 特权的账户。

1. 如果源和目标数据库实例使用默认的数据库参数组，您需要使用适合您的实例的版本创建自定义数据库参数组。这样便可更改多个参数的值。有关更多信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

1. 在自定义数据库参数组中，更改以下参数的值：
   + `shared_preload_libraries` - 将 `pg_transport` 添加到库列表。
   + `pg_transport.num_workers` - 默认值为 3。根据数据库的需要增加或减少该值。对于 200 GB 的数据库，我们建议该值不大于 8。请记住，如果增加该参数的默认值，还应增加 `max_worker_processes` 的值。
   + `pg_transport.work_mem` - 默认值为 128 MB 或 256 MB，具体视 PostgreSQL 版本而定。默认设置通常可以保持不变。
   + `max_worker_processes` – 需要使用以下计算来设置此参数的值：

     ```
     (3 * pg_transport.num_workers) + 9
     ```

     目标上需要此值来处理传输中涉及的各种后台工作进程。要了解有关 `max_worker_processes,` 的更多信息，请参阅 PostgreSQL 文档中的[资源消耗](https://www.postgresql.org/docs/current/runtime-config-resource.html)。

   有关 `pg_transport` 参数的更多信息，请参阅 [可传输数据库参数参考](PostgreSQL.TransportableDB.Parameters.md)。

1. 重启源 RDS for PostgreSQL 数据库实例和目标实例以使参数的设置生效。

1. 连接到 RDS for PostgreSQL 源数据库实例。

   ```
   psql --host=source-instance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

1. 从数据库实例的公共架构中删除无关的扩展。实际传输操作期间只允许 `pg_transport` 扩展。

1. 按如下方式安装 `pg_transport` 扩展：

   ```
   postgres=> CREATE EXTENSION pg_transport;
   CREATE EXTENSION
   ```

1. 连接到 RDS for PostgreSQL 目标数据库实例。删除任何无关的扩展，然后安装 `pg_transport` 扩展。

   ```
   postgres=> CREATE EXTENSION pg_transport;
   CREATE EXTENSION
   ```

# 将 PostgreSQL 数据库从源传输到目标
<a name="PostgreSQL.TransportableDB.Transporting"></a>

在完成 [设置以传输 PostgreSQL 数据库](PostgreSQL.TransportableDB.Setup.md) 中所述的过程后，您可以启动传输。为此，请在目标数据库实例上运行 `transport.import_from_server` 函数。在下面的语法中，您可以找到函数参数。

```
SELECT transport.import_from_server( 
   'source-db-instance-endpoint', 
    source-db-instance-port, 
   'source-db-instance-user', 
   'source-user-password', 
   'source-database-name', 
   'destination-user-password', 
   false);
```

示例中显示的 `false` 值告知函数这不是一次试运行。要测试传输设置，您可以指定调用函数时 `dry_run` 选项的 `true`，如下所示：

```
postgres=> SELECT transport.import_from_server(
    'docs-lab-source-db.666666666666aws-region.rds.amazonaws.com', 5432,
    'postgres', '********', 'labdb', '******', true);
INFO:  Starting dry-run of import of database "labdb".
INFO:  Created connections to remote database        (took 0.03 seconds).
INFO:  Checked remote cluster compatibility          (took 0.05 seconds).
INFO:  Dry-run complete                         (took 0.08 seconds total).
 import_from_server
--------------------

(1 row)
```

由于 `pg_transport.timing` 参数设置为其默认值 `true`，因此输出 INFO 行。运行该命令时将 `dry_run` 设置为 `false`，源数据库将导入到目标数据库，如下所示：

```
INFO:  Starting import of database "labdb".
INFO:  Created connections to remote database        (took 0.02 seconds).
INFO:  Marked remote database as read only           (took 0.13 seconds).
INFO:  Checked remote cluster compatibility          (took 0.03 seconds).
INFO:  Signaled creation of PITR blackout window     (took 2.01 seconds).
INFO:  Applied remote database schema pre-data       (took 0.50 seconds).
INFO:  Created connections to local cluster          (took 0.01 seconds).
INFO:  Locked down destination database              (took 0.00 seconds).
INFO:  Completed transfer of database files          (took 0.24 seconds).
INFO:  Completed clean up                            (took 1.02 seconds).
INFO:  Physical transport complete              (took 3.97 seconds total).
import_from_server
--------------------
(1 row)
```

该函数要求您提供数据库用户密码。因此，在传输完成后，我们建议您更改使用的用户角色的密码。或者，您可以使用 SQL 绑定变量创建临时用户角色。使用这些临时角色进行传输，然后丢弃这些角色。

如果传输失败，您可能会看到类似于以下内容的错误消息：

```
pg_transport.num_workers=8 25% of files transported failed to download file data
```

“failed to download file data”（下载文件数据失败）错误消息表示没有根据数据库的大小正确设置工件线程进程的数量。您可能需要增加或减少为 `pg_transport.num_workers` 设置的值。每次失败都会报告完成的百分比，因此您可以看到更改的影响。例如，在一个案例中将设置从 8 更改为 4 会导致以下情况：

```
pg_transport.num_workers=4 75% of files transported failed to download file data
```

请记住，在传输过程中还会考虑 `max_worker_processes` 参数。换句话说，您可能需要同时修改 `pg_transport.num_workers` 和 `max_worker_processes` 才能成功传输数据库。图示的例子当 `pg_transport.num_workers` 设置为 2 后最终生效：

```
pg_transport.num_workers=2 100% of files transported
```

有关 `transport.import_from_server` 函数及其参数的更多信息，请参阅 [可传输数据库函数参考](PostgreSQL.TransportableDB.transport.import_from_server.md)。

# 可传输数据库函数参考
<a name="PostgreSQL.TransportableDB.transport.import_from_server"></a>

`transport.import_from_server` 函数将 PostgreSQL 数据库从源数据库实例导入到目标数据库实例以传输该数据库。它使用物理数据库连接传输机制以执行该操作。

在开始传输之前，此函数将验证源和目标数据库实例的版本是否相同，以及是否与迁移兼容。它还确认目标数据库实例有足够的空间容纳源数据库实例。

**语法**

```
transport.import_from_server(
   host text,
   port int,
   username text,
   password text,
   database text,
   local_password text,
   dry_run bool
)
```

**返回值**

无。

**参数**

您可以在下表中找到 `transport.import_from_server` 函数参数说明。


****  

| 参数 | 描述 | 
| --- | --- | 
| host |  源数据库实例的端点。  | 
| port | 表示源数据库实例端口的整数。PostgreSQL 数据库实例通常使用端口 5432。 | 
| username |  源数据库实例的用户。该用户必须是 `rds_superuser` 角色的成员。  | 
| password |  源数据库实例的用户密码。  | 
| database |  源数据库实例中要传输的数据库的名称。  | 
| local\$1password |  目标数据库实例的当前用户的本地密码。该用户必须是 `rds_superuser` 角色的成员。  | 
| dry\$1run | 可选的布尔值，指定是否执行试运行。默认值为 `false`，这表示传输继续进行。要确认源和目标数据库实例之间的兼容性而不执行实际传输，请将 dry\$1run 设置为 true。 | 

**示例**

有关示例，请参阅 [将 PostgreSQL 数据库从源传输到目标](PostgreSQL.TransportableDB.Transporting.md)。

# 可传输数据库参数参考
<a name="PostgreSQL.TransportableDB.Parameters"></a>

有多个参数可控制 `pg_transport` 扩展的行为。在下文中，您可以找到这些参数的说明。

**`pg_transport.num_workers`**  
用于传输过程的工件线程数。默认值为 3。有效值为 1-32。即使是最大的数据库，传输通常需要也少于 8 个工件线程。在传输期间，目标数据库实例上此设置的值供目标和源使用。

**`pg_transport.timing` **  
指定是否在传输期间报告计时信息。默认值为 `true`，表示报告计时信息。我们建议您将该参数设置为 `true`，以便监控进度。有关示例输出，请参阅 [将 PostgreSQL 数据库从源传输到目标](PostgreSQL.TransportableDB.Transporting.md)。

**`pg_transport.work_mem`**  
为每个工作线程分配的最大内存量。默认值为 131072 千字节 (KB) 或 262144 KB (256 MB)，具体视 PostgreSQL 版本而定。最小值为 64 兆字节 (65536 KB)。有效值是以二进制单位表示的千字节 (KB)，其中 1 KB = 1024 字节。  
传输使用的内存不能超过该参数中指定的值。即使是大型数据库传输，通常所需的每个工件线程内存少于 256 MB (262144 KB)。