在 Amazon RDS 中使用 PostgreSQL 只读副本 - Amazon Relational Database Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

在 Amazon RDS 中使用 PostgreSQL 只读副本

一般使用只读副本配置 Amazon RDS 数据库实例之间的复制。有关只读副本的一般信息,请参阅 使用只读副本

在下文中,您可以找到使用 PostgreSQL 上的只读副本的特定信息。

PostgreSQL 只读副本配置

Amazon RDS PostgreSQL 使用 PostgreSQL 本机流式复制来创建源数据库实例的只读副本。此只读副本(PostgreSQL 术语中的“备用”)数据库实例是源数据库实例的异步创建的物理副本。该副本是由在源数据库实例和只读副本之间传输预写日志 (WAL) 数据的特殊连接创建。PostgreSQL 在发生数据库更改时将异步流式处理这些更改。

PostgreSQL 使用“副本”角色执行流式复制。该角色拥有特权,但不能用于修改任何数据。PostgreSQL 使用处理复制的单个过程。

您必须在数据库实例上建立自动备份,然后数据库实例才能充当源数据库实例。为此,请将备份保留期设定为非 0 值。

您可以在不影响源数据库实例和源用户的情况下创建 PostgreSQL 只读副本。Amazon RDS 为源数据库实例和只读副本设置必要的参数和权限,而不会中断服务。将创建源数据库实例的快照,此快照将变为只读副本。在删除只读副本时不会发生中断。

您可以从一个源数据库实例创建最多 5 个只读副本。为了有效地进行复制,每个只读副本具有的计算和存储资源的量应与源数据库实例的一样多。如果扩展源数据库实例,则还应扩展只读副本。

如果 Amazon RDS 从一开始就阻止只读副本,它将覆盖只读副本上任何不兼容的参数。例如,假定源数据库实例上的 max_connections 参数值高于只读副本上的此参数值。在这种情况下,Amazon RDS 将只读副本上的参数更新为与源数据库实例上的参数相同的值。

PostgreSQL 数据库实例使用一个安全连接,可通过同时将源实例和只读副本实例的 ssl 参数设置为 1 来对此安全连接进行加密。

您可从单可用区或多可用区数据库实例中创建只读副本。您可以使用多可用区部署提高关键数据的持久性和可用性,但无法使用多可用区备用副本为读取流量提供服务。您可以改为从大流量、多可用区数据库实例创建只读副本以分载只读查询。

如果多可用区部署的源数据库实例故障转移到备用可用区,则任何关联的只读副本都将切换为使用备用可用区(现在为主可用区)作为其复制源。新主可用区的 IP 地址与其前身不同。因此,在某些情况下,只读副本会在故障转移后重启,以便它们可以重新与新的主可用区同步。PostgreSQL 13 之前的所有 PostgreSQL 版本都是这种情况。对于 PostgreSQL 13 及更高版本,不需要重启。

注意

更改数据库实例类或更改数据库实例名称也会更改实例的 IP 地址。在 PostgreSQL 13 之前,这些更改需要重启数据库实例。

要了解关于多可用区部署的更多信息,请参阅 多可用区数据库实例部署。有关故障转移机制的信息,请参阅 Amazon RDS 的故障转移过程。要了解关于只读副本如何在多可用区部署中工作的更多信息,请参阅 使用只读副本

您可以将只读副本创建为多可用区数据库实例。Amazon RDS 会在另一个可用区 (AZ) 中创建备用副本,用于支持副本的故障转移。创建您的只读副本作为多可用区数据库实例与源数据库是否为多可用区数据库实例无关。

如果使用 postgres_fdw 扩展从远程服务器访问数据,则只读副本也可访问远程服务器。有关使用 postgres_fdw 的更多信息,请参阅。使用 postgres_fdw 扩展访问外部数据

监控 PostgreSQL 只读副本

对于 RDS for PostgreSQL 只读副本,可以通过在 Amazon CloudWatch 中查看 Amazon RDS ReplicaLag 指标来监控复制滞后。副本滞后是只读副本滞后于源数据库实例的时间量(以毫秒为单位)。ReplicaLag 指标报告 SELECT extract(epoch from now() - pg_last_xact_replay_timestamp()) AS replica_lag 的值。

若要了解有关 ReplicaLag 和 Amazon RDS 的其他指标的更多信息,请参阅 Amazon RDS 的 Amazon CloudWatch 指标

PostgreSQL 只读副本限制

以下是 PostgreSQL 只读副本的限制:

  • 每个 PostgreSQL 只读副本是只读的。无法将其设置为可写只读副本。

  • 您无法从另一个只读副本中创建只读副本。因此,您无法创建级联只读副本。

  • 您可将 PostgreSQL 只读副本提升为新的源数据库实例。但只读副本不会自动变为新的源数据库实例。提升只读副本时,该副本将停止接收预写日志 (WAL) 通信并且不再是只读实例。必须设置任何后续复制,因为所提升的只读副本现已成为新的源数据库实例。

  • 如果源数据库实例上未发生任何用户事务,则 PostgreSQL 只读副本将在最迟 5 分钟后报告复制滞后。

  • 您无法为 PostgreSQL 只读副本启用自动备份。

PostgreSQL 只读副本的复制中断

一些 PostgreSQL 参数会控制复制过程。在某些情况下,这些参数可能会意外中断只读副本复制。下面是一些示例:

  • max_wal_senders 参数设置为一个太小的值,导致无法向只读副本的数目提供足够的数据。如果发生这种情况,复制将停止。

  • wal_keep_segments 参数指定保留的预写日志 (WAL) 文件(日志)数,以便为只读副本提供数据。如果将该参数值设置为一个太小的值,则可能导致只读副本在流式复制停止后大幅滞后。在这种情况下,Amazon RDS 会报告复制错误。然后,RDS 将通过重放来自 Amazon S3 的源数据库实例的已存档 WAL 日志,开始对只读副本执行恢复操作。在只读副本赶上进度可继续流式复制之前,该恢复过程将继续。有关更多信息,请参阅 解决 PostgreSQL 只读副本问题

  • max_slot_wal_keep_size 参数指明了允许复制槽在检查点时间保留在 pg_wal 目录中的 WAL 文件的最大大小。如果 max_slot_wal_keep_size 是 -1(默认值),复制槽可能会保留无限量的 WAL 文件。否则,复制槽的 restart_lsn 值可能会落后于当前日志序列号 (LSN),超过给定的大小。如果发生这种情况,由于删除了所需的 WAL 文件,使用该复制槽的备用副本可能无法继续复制。您可以在 pg_Replation_slot 中查看复制槽的 WAL 可用性。

向只读副本提供数据的 WAL 流中断时,PostgreSQL 会切换为恢复模式。其使用来自 Amazon S3 的已存档 WAL 文件还原只读副本。在此过程完成后,PostgreSQL 将尝试重新建立流式复制。

解决 PostgreSQL 只读副本问题

如何解决 PostgreSQL 只读副本问题因几个因素而异。其中包括正在运行的 RDS for PostgreSQL 版本,以及复制是否跨 Amazon Web Services 区域 或在同一区域内:

  • 从 PostgreSQL 9.5.2 开始,RDS for PostgreSQL 使用物理复制槽来管理跨 Amazon Web Services 区域 源数据库实例上的预写日志 (WAL) 保留。

  • 从 RDS for PostgreSQL 版本 14.1 及更高版本开始,物理复制槽用于跨区域以及同一区域内的副本。

若要解决使用物理复制槽时的复制问题,请参阅 只读副本和物理复制槽。该部分中的信息适用于 RDS for PostgreSQL 14.1 及更高版本的区域内只读副本。其也适用于 RDS for PostgreSQL 9.5.2 及更高版本(但不高于 PostgreSQL 14.1)的跨区域只读副本。

若要解决 PostgreSQL 参数设置可能导致的复制问题,请参阅 只读副本和 WAL 参数设置

只读副本和 WAL 参数设置

正如 PostgreSQL 只读副本的复制中断 中所述,PostgreSQL 参数 wal_keep_segments 的参数值如果设置得过低,可能会中断复制。为该参数设置的值会指定要保留的日志数量。如果该值过低,则可能导致只读副本在流式复制停止后大幅滞后。如果出现此情况,Amazon RDS 将通过重放源数据库实例的已存档 WAL 日志,开始对只读副本执行恢复操作。在只读副本赶上进度可继续流式复制之前,该恢复过程将继续。

只读副本的 PostgreSQL 日志将捕获该过程,如本示例中所示。粗体行显示 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 文件赶上进度后,可以再次开始流式传输到只读副本。PostgreSQL 恢复流式传输时,其会向日志文件中写入条目,类似于以下内容。

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

PostgreSQL 日志会捕获其他重要信息,可用来帮助您解决只读副本问题。例如,在每个检查点中,PostgreSQL 日志会捕获回收事务日志文件的数量,如以下示例所示。

2014-11-07 19:59:35 UTC::@:[26820]:LOG:  checkpoint complete: wrote 376 buffers (0.2%); 0 transaction log file(s) added, 0 removed, 1 recycled; write=35.681 s, sync=0.013 s, total=35.703 s; sync files=10, longest=0.013 s, average=0.001 s

您可以使用此信息来确定在给定时间段内将回收多少事务文件,然后根据需要调整 wal_keep_segments 参数。例如,假设 checkpoint complete 时的 PostgreSQL 日志每隔 5 分钟显示 35 recycled。在这种情况下,wal_keep_segments 默认值 32 不足以跟上流式传输活动的节奏,因此建议您增加此参数的值。

而且,如果数据库实例上的工作负载生成大量 WAL 数据,则您可能需要更改源数据库实例和只读副本的数据库实例类。将其更改为具有高 (10 Gbps) 网络性能的实例类有助于副本跟上源的节奏。若要了解工作负载生成 WAL 数据的速率的更多信息,请查看 Amazon CloudWatch TransactionLogsGeneration 指标。

只读副本和物理复制槽

自 RDS for PostgreSQL 9.5.2 起,我们就使用物理复制槽来管理跨区域只读副本的源数据库实例上的预写日志 (WAL) 保留。从 RDS for PostgreSQL 14.1 起,物理复制槽也用于在 Amazon Web Services 区域 中管理 WAL 保留。Amazon RDS 为每个只读副本创建和关联保留 WAL 数据的物理复制槽。与使用来自 Amazon S3 的已存档日志文件相比,物理复制槽的恢复速度更快,因此目标是确保 RDS for PostgreSQL 数据库实例尽可能使用物理复制槽来进行快速恢复。

您可以使用两个 Amazon CloudWatch 指标来帮助管理物理复制槽:

  • OldestReplicationSlotLag:列出滞后时间最长的副本,即落后于主副本最远的副本

  • TransactionLogsDiskUsage:显示 WAL 数据使用了多少存储空间。如果只读副本出现明显滞后,此指标的值可能会大幅增加。

若要了解将 Amazon CloudWatch 及其指标用于 RDS for PostgreSQL 的更多信息,请参阅 使用 Amazon CloudWatch 监控 Amazon RDS 指标

若要检查只读副本的物理复制槽状态,您可以在源实例上查询 pg_replication_slots,如以下示例所示。

postgres=#select * from pg_replication_slots; slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn _______________________________________________________________________________________________________________________________________________ rds_us_east_1_db_uzwlholddgpblksce6hgw4nkte | | physical | | | t | 12598 | | | 4E/95000060 (1 row)

正如 PostgreSQL 只读副本的复制中断 中所述,max_slot_wal_keep_size 参数的值会影响复制过程。默认情况下,此参数的值为 -1,即允许复制槽保留无限量的 WAL 文件。您可以将其更改为特定值,但请注意,在数据库实例达到该值后,其复制槽便无法保存更多 WAL 日志。如果 max_slot_wal_keep_size 参数达到限制,Amazon RDS 数据库实例的最终行为取决于复制是针对区域内还是跨区域只读副本:

  • 对于区域内副本,如果已达到 max_slot_wal_keep_size 限制,在日志捕捉到源之前,Amazon RDS 将使用来自 Amazon S3 的存档日志。然后其可以再次开始流式传输。为避免这种情况,您可以监控物理复制槽并调整 max_slot_wal_keep_size,从而尽量减少对存档日志文件的需求。

  • 对于跨区域副本,如果已达到 max_slot_wal_keep_size 限制,复制将停止。由于不使用存档日志,请谨慎调整跨区域只读副本的 max_slot_wal_keep_size 参数。