

# 流式复制如何适用于不同的 RDS for PostgreSQL 版本
<a name="USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions"></a>

正如[PostgreSQL 只读副本配置](USER_PostgreSQL.Replication.ReadReplicas.Configuration.md)中讨论的，RDS for PostgreSQL 使用 PostgreSQL 的原生流式复制协议从源数据库实例发送 WAL 数据。它将源 WAL 数据发送到区域内和跨区域只读副本。在 9.4 版中，PostgreSQL 引入了物理复制槽作为复制过程的支持机制。

*物理复制槽*可防止源数据库实例在所有只读副本使用 WAL 数据之前将其删除。每个只读副本在源数据库实例上都有自己的物理槽。该槽跟踪副本可能需要的最旧 WAL（按逻辑序列号，LSN）。在所有槽和数据库连接都进展到超出给定 WAL（LSN）之后，该 LSN 将成为在下一个检查点移除的候选项。

Amazon RDS 使用 Amazon S3 来归档 WAL 数据。对于区域内只读副本，您可以在必要时使用此归档数据恢复只读副本。例如，当源数据库和只读副本之间的连接由于任何原因中断时，您就可以这么做。

在下表中，您可以找到 PostgreSQL 版本之间以及 RDS for PostgreSQL 使用的区域内和跨区域支持机制之间的差异的摘要。


| 版本 | 区域内 | 跨区域 | 
| --- | --- | --- | 
| PostgreSQL 14.1 及更高版本 |  [See the AWS documentation website for more details](http://docs.amazonaws.cn/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  |  [See the AWS documentation website for more details](http://docs.amazonaws.cn/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  | 
| PostgreSQL 13 及更低版本 |  [See the AWS documentation website for more details](http://docs.amazonaws.cn/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  |  [See the AWS documentation website for more details](http://docs.amazonaws.cn/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  | 

有关更多信息，请参阅 [监控和调整复制过程](USER_PostgreSQL.Replication.ReadReplicas.Monitor.md)。

## 了解控制 PostgreSQL 复制的参数
<a name="USER_PostgreSQL.Replication.ReadReplicas.Parameters"></a>

以下参数会影响复制过程，并确定只读副本与源数据库实例保持同步的程度：

**max\_wal\_senders**  
`max_wal_senders` 参数指定源数据库实例可以通过流式复制协议同时支持的最大连接数。  
默认值因 RDS for PostgreSQL 版本而各不相同：  
+ 对于版本 13、14 和 15，默认值为 20。
+ 对于版本 16 及更高版本，默认值为 35。
此参数应设置为略高于实际只读副本数量。如果此参数设置为对只读副本数来说太少，则复制将停止。  
有关更多信息，请参阅 PostgreSQL 文档中的 [max\_wal\_senders](https://www.postgresql.org/docs/devel/runtime-config-replication.html#GUC-MAX-WAL-SENDERS)。  
`max_wal_senders` 是一个静态参数，要求重启数据库实例才能使更改生效。

**wal\_keep\_segments**  
`wal_keep_segments` 指定源数据库实例在 `pg_wal` 目录中保留的预写日志（WAL）文件的数量。默认设置为 32。  
如果 `wal_keep_segments` 没有针对您的部署设置为足够大的值，只读副本可能远远落后于流式复制停止。如果出现此情况，Amazon RDS 将生成复制错误并开始对只读副本进行恢复。为此，它将重放来自 Amazon S3 的源数据库实例的已归档 WAL 数据。在只读副本赶上进度可继续流式复制之前，该恢复过程将继续。您可以在[示例：只读副本如何从复制中断中恢复示例：从复制中断中恢复只读副本](#USER_PostgreSQL.Replication.example-how-it-works)中看到 PostgreSQL 日志所捕获的这个过程的实际执行情况。  
在 PostgreSQL 版本 13 中，`wal_keep_segments` 参数名为 `wal_keep_size`。它的目的与 `wal_keep_segments` 相同，但其默认值以兆字节（MB），而不是文件数为单位（2048MB）。有关更多信息，请参阅 PostgreSQL 文档中 [wal\_keep\_segments](https://www.postgresql.org/docs/12/runtime-config-replication.html#GUC-WAL-KEEP-SEGMENTS) 和 [wal\_keep\_size](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-WAL-KEEP-SIZE)。

**max\_slot\_wal\_keep\_size**  
`max_slot_wal_keep_size` 参数控制 RDS for PostgreSQL 数据库实例保留在 `pg_wal` 目录中以服务插槽的 WAL 数据量。此参数用于使用复制槽的配置。此参数的默认值为 `-1`，这意味着对源数据库实例上保留多少 WAL 数据没有限制。有关监控复制槽的信息，请参阅[监控 RDS for PostgreSQL 数据库实例的复制槽](USER_PostgreSQL.Replication.ReadReplicas.Monitor.md#USER_PostgreSQL.Replication.ReadReplicas.Monitor-monitor-replication-slots)。  
有关此参数的更多信息，请参阅 PostgreSQL 文档中的 [max\_slot\_wal\_keep\_size](https://www.postgresql.org/docs/devel/runtime-config-replication.html#GUC-MAX-SLOT-WAL-KEEP-SIZE)。

每次向只读副本提供数据的 WAL 流中断时，PostgreSQL 都会切换为恢复模式。它使用来自 Amazon S3 的已存档 WAL 数据或使用与复制槽关联的 WAL 数据来恢复只读副本。在此过程完成后，PostgreSQL 会重新建立流式复制。

### 示例：只读副本如何从复制中断中恢复
<a name="USER_PostgreSQL.Replication.example-how-it-works"></a>

在以下示例中，您可以找到演示只读副本恢复过程的日志详细信息。该示例来自与源数据库在同一 Amazon Web Services 区域中运行 PostgreSQL 版本 12.9 的 RDS for PostgreSQL 数据库实例，因此不使用复制槽。对于运行早于 14.1 版的 PostgreSQL 且具有区域内只读副本的其他 RDS for PostgreSQL 数据库实例，恢复过程相同。

当只读副本与源数据库实例失去联系时，Amazon RDS 会在日志中将问题记录为 `FATAL: could not receive data from WAL stream` 消息以及 `ERROR: requested WAL segment ... has already been removed`。如粗体行所示，Amazon RDS 通过重播归档的 WAL 文件来恢复副本。

```
2014-11-07 19:01:10 UTC::@:[23180]:DEBUG:  switched WAL source from archive to stream after failure
2014-11-07 19:01:10 UTC::@:[11575]:LOG: started streaming WAL from primary at 1A/D3000000 on timeline 1
2014-11-07 19:01:10 UTC::@:[11575]:FATAL: could not receive data from WAL stream:
ERROR:  requested WAL segment 000000010000001A000000D3 has already been removed
2014-11-07 19:01:10 UTC::@:[23180]:DEBUG: could not restore file "00000002.history" from archive: return code 0
2014-11-07 19:01:15 UTC::@:[23180]:DEBUG: switched WAL source from stream to archive after failure recovering 000000010000001A000000D3
2014-11-07 19:01:16 UTC::@:[23180]:LOG:  restored log file "000000010000001A000000D3" from archive
```

当 Amazon RDS 在副本上重放足够多的已归档 WAL 数据以赶上进度时，将再次开始向只读副本流式传输。恢复流式传输时，Amazon RDS 会向日志文件中写入一个类似以下内容的条目。

```
2014-11-07 19:41:36 UTC::@:[24714]:LOG:started streaming WAL from primary at 1B/B6000000 on timeline 1
```

## 设置控制共享内存的参数
<a name="USER_PostgreSQL.Replication.ReadReplicas.Parameters.Settings"></a>

您设置的参数确定了用于跟踪事务 ID、锁和已准备事务的共享内存的大小。**备用实例的共享内存结构必须等于或大于主实例的共享内存结构。**这样可以确保前者在恢复过程中不会耗尽共享内存。如果副本上的参数值小于主实例上的参数值，Amazon RDS 将自动调整副本参数并重启引擎。

受影响的参数有：
+ max\_connections
+ max\_worker\_processes
+ max\_wal\_senders
+ max\_prepared\_transactions
+ max\_locks\_per\_transaction

为避免由于内存不足而导致副本 RDS 重启，我们建议将参数更改作为滚动重启应用于每个副本。在设置参数时，必须应用以下规则：
+ **增加参数值：**
  + 您应始终先增加所有只读副本的参数值，然后对所有副本执行滚动重启。然后，在主实例上应用参数更改并重启。
+  **减小参数值：**
  + 您应该首先减少主实例的参数值，然后执行重启。然后，将参数更改应用于所有关联的只读副本并执行滚动重启。