

# 在数据库实例之间传输 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)。