

# Amazon RDS for PostgreSQL
<a name="CHAP_PostgreSQL"></a>

Amazon RDS 支持运行多种 PostgreSQL 版本的数据库实例。有关可用版本列表，请参阅[可用的 PostgreSQL 数据库版本](PostgreSQL.Concepts.General.DBVersions.md)。

可创建数据库实例和数据库快照、时间点还原和备份。运行 PostgreSQL 的数据库实例支持多可用区部署、只读副本、预置 IOPS，可以在 Virtual Private Cloud (VPC) 内创建此类数据库实例。您还可以使用安全套接字层 (SSL) 连接到运行 PostgreSQL 的数据库实例。

创建数据库实例之前，确保完成 [设置 Amazon RDS 环境](CHAP_SettingUp.md) 中的步骤。

您可以使用任何标准 SQL 客户端应用程序从客户端计算机对实例运行命令。此类应用程序包括 pgAdmin（用于 PostgreSQL 的流行开源管理和开发工具）或 psql（PostgreSQL 安装包含的命令行实用程序）。为了提供托管服务体验，Amazon RDS 未提供数据库实例的主机访问权限。并且它还限制了对需要高级权限的某些系统程序和表的访问。Amazon RDS 支持使用任何标准 SQL 客户端应用程序访问数据库实例上的数据库。Amazon RDS 不允许使用远程登录或安全外壳（SSH）直接从主机进行访问数据库实例。

Amazon RDS for PostgreSQL 符合很多行业标准。例如，您可以使用 Amazon RDS for PostgreSQL 数据库构建符合 HIPAA 标准的应用程序，并存储与医疗保健相关的信息。这包括根据与 AWS 签订的完整业务合作协议 (BAA) 存储受保护的健康信息 (PHI)。Amazon RDS for PostgreSQL 还满足联邦风险与授权管理项目（FedRAMP）安全要求。在AWS GovCloud (US)区域中，Amazon RDS for PostgreSQL 获得了 FedRAMP 联合授权委员会（JAB）的 FedRAMP 高基准临时授权操作（P-ATO）。有关支持的合规性标准的更多信息，请参阅[AWS云合规性](https://aws.amazon.com/compliance/)。

要将 PostgreSQL 数据导入到数据库实例中，请按[将数据导入 Amazon RDS 上的 PostgreSQL](PostgreSQL.Procedural.Importing.md)一节中的信息操作。

**重要**  
如果您的 RDS for PostgreSQL 数据库实例遇到问题，AWS 支持座席可能需要有关数据库运行状况的更多信息。目标是确保 AWS Support 尽快获得所需的信息。  
您可以使用 PG Collector 帮助在整合的 HTML 文件中收集有价值的数据库信息。有关 PG Collector、如何运行它以及如何下载 HTML 报告的更多信息，请参阅 [PG Collector](https://github.com/awslabs/pg-collector)。  
成功完成后，除非另有说明，否则脚本将以可读的 HTML 格式返回输出。该脚本设计为从 HTML 中排除任何可能危及您业务的数据或安全细节。它也不会对您的数据库或其环境进行任何修改。但是，如果您在 HTML 中发现任何不愿意分享的信息，您可以在上传 HTML 之前随意删除有问题的信息。当 HTML 的内容可以接受时，请在支持案例的案例详细信息中，使用附件部分进行上传。

**Topics**
+ [Amazon RDS for PostgreSQL 的常见管理任务](CHAP_PostgreSQL.CommonTasks.md)
+ [使用数据库预览环境](working-with-the-database-preview-environment.md)
+ [可用的 PostgreSQL 数据库版本](PostgreSQL.Concepts.General.DBVersions.md)
+ [了解 RDS for PostgreSQL 增量发行版流程](PostgreSQL.Concepts.General.ReleaseProcess.md)
+ [支持的 PostgreSQL 扩展版本](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md)
+ [使用 Amazon RDS for PostgreSQL 支持的 PostgreSQL 功能](PostgreSQL.Concepts.General.FeatureSupport.md)
+ [连接到运行 PostgreSQL 数据库引擎的数据库实例](USER_ConnectToPostgreSQLInstance.md)
+ [使用 SSL/TLS 保护与 RDS for PostgreSQL 的连接](PostgreSQL.Concepts.General.Security.md)
+ [在 Amazon RDS for PostgreSQL 中使用 Kerberos 身份验证](postgresql-kerberos.md)
+ [将自定义 DNS 服务器用于出站网络访问](Appendix.PostgreSQL.CommonDBATasks.CustomDNS.md)
+ [升级 RDS for PostgreSQL 数据库引擎](USER_UpgradeDBInstance.PostgreSQL.md)
+ [升级 PostgreSQL 数据库快照引擎版本](USER_UpgradeDBSnapshot.PostgreSQL.md)
+ [使用 Amazon RDS for PostgreSQL 只读副本](USER_PostgreSQL.Replication.ReadReplicas.md)
+ [使用 Amazon RDS 优化型读取功能提高 RDS for PostgreSQL 的查询性能](USER_PostgreSQL.optimizedreads.md)
+ [将数据导入 Amazon RDS 上的 PostgreSQL](PostgreSQL.Procedural.Importing.md)
+ [将数据从 RDS for PostgreSQL 数据库实例导出到 Amazon S3](postgresql-s3-export.md)
+ [从 RDS for PostgreSQL 数据库实例中调用 AWS Lambda 函数](PostgreSQL-Lambda.md)
+ [Amazon RDS for PostgreSQL 的数据库管理员常见任务](Appendix.PostgreSQL.CommonDBATasks.md)
+ [使用 RDS for PostgreSQL 的等待事件进行优化](PostgreSQL.Tuning.md)
+ [使用 Amazon DevOps Guru 主动见解优化 RDS for PostgreSQL](PostgreSQL.Tuning_proactive_insights.md)
+ [将 PostgreSQL 扩展与 Amazon RDS for PostgreSQL 结合使用](Appendix.PostgreSQL.CommonDBATasks.Extensions.md)
+ [使用 Amazon RDS for PostgreSQL 支持的外部数据包装器](Appendix.PostgreSQL.CommonDBATasks.Extensions.foreign-data-wrappers.md)
+ [使用适用于 PostgreSQL 的可信语言扩展](PostgreSQL_trusted_language_extension.md)

# Amazon RDS for PostgreSQL 的常见管理任务
<a name="CHAP_PostgreSQL.CommonTasks"></a>

下面是对 Amazon RDS for PostgreSQL 数据库实例执行的常见管理任务，以及有关每个任务的相关文档的链接。


| 任务区域 | 相关文档 | 
| --- | --- | 
|  **设置 Amazon RDS 供首次使用** 创建数据库实例之前，确保完成一些先决条件。例如，默认情况下，数据库实例在创建后带有一个阻止对其进行访问的防火墙。因此，您需要使用正确的 IP 地址和网络配置创建安全组来访问数据库实例。  |  [设置 Amazon RDS 环境](CHAP_SettingUp.md)  | 
|  **了解 Amazon RDS 数据库实例** 如果您出于生产目的而创建数据库实例，则应该了解 Amazon RDS 中的实例类、存储类型和配置的 IOPS 的工作原理。  |  [数据库实例类](Concepts.DBInstanceClass.md) [Amazon RDS 存储类型](CHAP_Storage.md#Concepts.Storage) [预置 IOPS SSD 存储](CHAP_Storage.md#USER_PIOPS)  | 
|  **查找可用的 PostgreSQL 版本** Amazon RDS 支持 PostgreSQL 的多个版本。  |  [可用的 PostgreSQL 数据库版本](PostgreSQL.Concepts.General.DBVersions.md)  | 
|  **设置高可用性和故障转移支持** 生产数据库实例应使用多可用区部署。多可用区部署为数据库实例提供了更高的可用性、数据持久性和容错能力。  |  [配置和管理 Amazon RDS 的多可用区部署](Concepts.MultiAZ.md)  | 
|  **了解 Amazon Virtual Private Cloud (VPC) 网络** 如果您的 AWS 账户具有默认 VPC，则自动在默认 VPC 中创建数据库实例。在某些情况下，您的账户可能没有默认 VPC，并且您可能希望在 VPC 中使用数据库实例。在这些情况下，请在创建数据库实例之前创建 VPC 和子网组。   |  [在 VPC 中使用数据库实例](USER_VPC.WorkingWithRDSInstanceinaVPC.md)  | 
|  **将数据导入 Amazon RDS PostgreSQL** 您可以使用多种不同的工具将数据导入 Amazon RDS 中的 PostgreSQL 数据库实例。  |  [将数据导入 Amazon RDS 上的 PostgreSQL](PostgreSQL.Procedural.Importing.md)  | 
|  **设置只读副本（主和备用）** RDS for PostgreSQL 支持来自主实例的同一 AWS 区域和不同 AWS 区域的只读副本。  |  [使用数据库实例只读副本](USER_ReadRepl.md) [使用 Amazon RDS for PostgreSQL 只读副本](USER_PostgreSQL.Replication.ReadReplicas.md) [在不同的 中创建只读副本AWS 区域](USER_ReadRepl.XRgn.md)  | 
|  **了解安全组** 默认情况下，数据库实例在创建时带有一个防火墙，这个防火墙会阻止对实例进行访问。要通过该防火墙提供访问权限，您需要编辑与托管数据库实例的 VPC 关联的 VPC 安全组的入站规则。  |  [使用安全组控制访问权限](Overview.RDSSecurityGroups.md)  | 
|  **设置参数组和特征** 要更改数据库实例的默认参数，请创建自定义数据库参数组并将设置更改为该参数组。如果您在创建数据库实例之前执行此操作，则可以在创建实例时选择自定义数据库参数组。  |  [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)  | 
|  **连接到您的 PostgreSQL 数据库实例** 在创建安全组并将其与数据库实例关联后，您可以使用任何标准 SQL 客户端应用程序（如 `psql` 或 `pgAdmin`）连接到数据库实例。  |  [连接到运行 PostgreSQL 数据库引擎的数据库实例](USER_ConnectToPostgreSQLInstance.md) [将 SSL 与 PostgreSQL 数据库实例结合使用](PostgreSQL.Concepts.General.SSL.md)  | 
|  **备份和还原数据库实例** 您可以配置数据库实例以采用自动备份或采用手动快照，然后从备份或快照还原实例。  |  [备份、还原和导出数据](CHAP_CommonTasks.BackupRestore.md)  | 
|  **监控数据库实例的活动和性能** 您可以使用 CloudWatch Amazon RDS 指标、事件和增强监控来监控 PostgreSQL 数据库实例。  |  [在 Amazon RDS 控制台中查看指标](USER_Monitoring.md) [查看 Amazon RDS 事件](USER_ListEvents.md)  | 
|  **升级 PostgreSQL 数据库版本** 您可以对 PostgreSQL 数据库实例同时执行主要和次要版本升级。  |  [升级 RDS for PostgreSQL 数据库引擎](USER_UpgradeDBInstance.PostgreSQL.md) [为 RDS for PostgreSQL 升级选择主要版本](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.md)  | 
|  **使用日志文件** 您可以访问 PostgreSQL 数据库实例的日志文件。  |  [RDS for PostgreSQL 数据库日志文件](USER_LogAccess.Concepts.PostgreSQL.md)  | 
|  **了解 PostgreSQL 数据库实例的最佳实践** 查找在 Amazon RDS 上使用 PostgreSQL 的一些最佳实践。  |  [使用 PostgreSQL 的最佳实践](CHAP_BestPractices.md#CHAP_BestPractices.PostgreSQL)  | 

以下是本指南中可以帮助您了解和使用 RDS for PostgreSQL 的重要特征的其他章节列表：
+  [了解 PostgreSQL 角色和权限](Appendix.PostgreSQL.CommonDBATasks.Roles.md) 
+  [控制用户对 PostgreSQL 数据库的访问控制用户对 PostgreSQL 的访问](Appendix.PostgreSQL.CommonDBATasks.Access.md) 
+  [在 RDS for PostgreSQL 数据库实例上使用参数](Appendix.PostgreSQL.CommonDBATasks.Parameters.md) 
+  [了解 RDS for PostgreSQL 支持的日志记录机制](Appendix.PostgreSQL.CommonDBATasks.md#Appendix.PostgreSQL.CommonDBATasks.Auditing) 
+  [在 Amazon RDS for PostgreSQL 上使用 PostgreSQL autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md) 
+  [将自定义 DNS 服务器用于出站网络访问](Appendix.PostgreSQL.CommonDBATasks.CustomDNS.md) 

# 使用数据库预览环境
<a name="working-with-the-database-preview-environment"></a>

 PostgreSQL 社区会不断发布新的 PostgreSQL 版本和扩展，包括测试版。这让 PostgreSQL 用户有机会尽早试用新的 PostgreSQL 版本。要了解有关 PostgreSQL 社区测试版发布流程的更多信息，请参阅 PostgreSQL 文档中的[测试版信息](https://www.postgresql.org/developer/beta/)。同样，Amazon RDS 将某些 PostgreSQL 测试版作为预览版提供。这允许您使用预览版创建数据库实例，并在数据库预览环境中测试其特征。

数据库预览环境中的 RDS for PostgreSQL 数据库实例在功能上类似于其他 RDS for PostgreSQL 实例。但是，不能将预览版用于生产。

请注意以下重要限制：
+ 所有数据库实例在创建之后的 60 天删除，包括其所有备份和快照。
+ 您只能在 Virtual Private Cloud (VPC) 中创建基于 Amazon VPC 服务的数据库实例。
+ 您只能使用通用 SSD 和预置 IOPS SSD 存储。
+ 您无法从 AWS Support 获得数据库实例的帮助。而是可以将您的问题发布到 AWS 托管的问答社群，即 [AWS re:Post](https://repost.aws/tags/TAsibBK6ZeQYihN9as4S_psg/amazon-relational-database-service)。
+ 您无法将数据库实例的快照复制到生产环境。

预览版支持以下选项：
+ 只能使用 M6i、R6i、M6g、M5、T3、R6g 和 R5 实例类型创建数据库实例。有关 RDS 实例类的更多信息，请参阅[数据库实例类](Concepts.DBInstanceClass.md)。
+ 您可以同时使用单可用区和多可用区部署。
+ 您可以使用标准 PostgreSQL 转储和加载函数从数据库预览环境中导出数据库或将数据库导入数据库预览环境。

**Topics**
+ [数据库预览环境中不支持的功能](#preview-environment-exclusions)
+ [数据库预览环境中的 PostgreSQL 版本 17](#PostgreSQL.Concepts.General.version17)
+ [在数据库预览环境中创建新数据库实例](create-db-instance-in-preview-environment.md)

## 数据库预览环境中不支持的功能
<a name="preview-environment-exclusions"></a>

以下功能在预览环境中不可用：
+ 跨区域快照复制
+ 跨区域只读副本

## 数据库预览环境中的 PostgreSQL 版本 17
<a name="PostgreSQL.Concepts.General.version17"></a>

**注意**  
这是 Amazon RDS PostgreSQL 版本 17 的预览文档。本文档随时可能更改。

PostgreSQL 版本 17.0 现可在 Amazon RDS 数据库预览环境中使用。PostgreSQL 版本 17.0 包含一些改进，如以下 PostgreSQL 文档中所述：[PostgreSQL 17 Released\$1](https://www.postgresql.org/docs/17/release-17.html)

有关数据库预览环境的信息，请参阅[使用数据库预览环境](#working-with-the-database-preview-environment)。要从控制台中访问预览环境，请选择 [https://console.aws.amazon.com/rds-preview/](https://console.aws.amazon.com/rds-preview/)。

# 在数据库预览环境中创建新数据库实例
<a name="create-db-instance-in-preview-environment"></a>

使用以下过程在预览环境中创建数据库实例。

**在数据库预览环境中创建数据库实例**

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

1. 从导航窗格选择 **Dashboard (控制面板)**。

1. 在控制面板页面中，找到控制面板页面上的 **Database Preview Environment**（数据库预览环境）部分，如下图所示。  
![\[预览环境部分，链接显示在 RDS 控制台、控制面板中\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/preview-environment-dashboard.png)

   您可以直接导航到[数据库预览环境](https://us-east-2.console.aws.amazon.com/rds-preview/home?region=us-east-2#)。在继续操作之前，您必须确认并接受这些限制。  
![\[Preview environment limitations（预览环境限制）对话框\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/preview-environment-console.png)

1. 要创建 RDS for PostgreSQL 数据库实例，请遵循与创建任何 Amazon RDS 数据库实例相同的流程。有关更多信息，请参阅[创建数据库实例](USER_CreateDBInstance.md#USER_CreateDBInstance.Creating)中的[控制台](USER_CreateDBInstance.md#USER_CreateDBInstance.CON)过程。

要使用 RDS API 或 AWS CLI 在数据库预览环境中创建实例，请使用以下端点。

```
rds-preview.us-east-2.amazonaws.com
```

# 可用的 PostgreSQL 数据库版本
<a name="PostgreSQL.Concepts.General.DBVersions"></a>

Amazon RDS 支持运行多种 PostgreSQL 版本的数据库实例。在创建新数据库实例时，您可以指定目前可用的任何 PostgreSQL 版本。您可以指定主要版本（例如 PostgreSQL 14），以及所指定主要版本的任何可用的次要版本。如果没有指定任何版本，Amazon RDS 会默认使用可用的版本，通常是最新的版本。如果指定了主要版本但未指定次要版本，Amazon RDS 将默认使用您指定的主要版本的最新版本。

要查看受支持版本的列表以及新创建的数据库实例的默认值，请使用 [https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-engine-versions.html](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-engine-versions.html) AWS CLI 命令。例如，要显示默认 PostgreSQL 引擎版本，请使用以下命令：

```
aws rds describe-db-engine-versions --default-only --engine postgres
```

有关 Amazon RDS 支持的 PostgreSQL 版本的详细信息，请参阅 [https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/Welcome.html](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/Welcome.html)。您还可以运行 [describe-db-major-engine-versions](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-major-engine-versions.html) AWS CLI 命令或者使用 [DescribeDBMajorEngineVersions](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBMajorEngineVersions.html) RDS API 操作，来查看有关主要引擎版本的支持日期的信息。

如果您还没有准备好在 RDS 标准支持终止日期之前手动升级到新的主要引擎版本，Amazon RDS 将在 RDS 标准支持终止日期之后自动将您的数据库注册到 Amazon RDS Extended Support。然后，您可以继续运行 RDS for PostgreSQL 11 及更高版本。有关更多信息，请参阅[Amazon RDS 的 Amazon RDS 扩展支持](extended-support.md)和 [Amazon RDS 定价](https://aws.amazon.com/rds/pricing/)。

## Amazon RDS for PostgreSQL 已弃用的版本
<a name="PostgreSQL.Concepts.General.DeprecatedVersions"></a>

请注意以下已停用的版本：
+ RDS for PostgreSQL 10 已于 2023 年 2 月停用。
+ RDS for PostgreSQL 9.6 已于 2022 年 3 月停用。
+ RDS for PostgreSQL 9.5 已于 2021 年 3 月停用。

若要了解有关 RDS for PostgreSQL 弃用策略的更多信息，请参阅 [Amazon RDS 常见问题](https://aws.amazon.com/rds/faqs/)。有关 PostgreSQL 版本的更多信息，请参阅 PostgreSQL 文档中的[版本控制策略](https://www.postgresql.org/support/versioning/)。

# 了解 RDS for PostgreSQL 增量发行版流程
<a name="PostgreSQL.Concepts.General.ReleaseProcess"></a>

RDS for PostgreSQL 通过增量发行版提供安全修复、性能改进和新功能，同时保持次要版本兼容性。这些发行版标为 R1、R2、R3，以此类推。

**发行版命名约定**
+ R1 是次要版本的初始发行版。它偶尔会包含新功能、扩展或对现有扩展的升级。
+ 后续发行版（R2、R3 及更高版本）包括：
  + 安全更新
  + 性能改进
  + 漏洞修复
  + 扩展更新

## RDS for PostgreSQL 增量发行版流程的优势
<a name="PostgreSQL.Concepts.General.ReleaseProcess.Adv"></a>

增量发行版流程提供以下优势：
+ 快速采用新的 PostgreSQL 社区发行版，同时通过后续发行版单独管理 RDS 特定的增强功能。这简化了发行版流程，并确保更快地交付关键更新。
+ 访问错误修复、新功能、安全更新和扩展更新，同时保持与 PostgreSQL 次要版本的兼容性。

## 管理发行版更新
<a name="PostgreSQL.Concepts.General.ReleaseProcess.Manage"></a>

Amazon RDS 通过 AWS 管理控制台中的待处理维护操作来通知您有关新的增量发行版的信息。您可以使用以下方法之一更新数据库：
+ 在计划的维护时段内启用自动更新。
+ 通过待处理的维护操作手动应用更新。
+ 将蓝绿部署与物理复制结合使用，以最大限度地减少停机时间。有关更多信息，请参阅 [RDS 蓝绿部署支持 RDS for PostgreSQL 进行次要版本升级](https://aws.amazon.com/about-aws/whats-new/2024/11/rds-blue-green-deployments-upgrade-rds-postgresql/)。

在更新数据库之前，请考虑以下关键点：
+ 除非您将蓝绿部署与物理复制结合使用，否则更新需要重启数据库。
+ 某些增量发行版是强制性的，尤其是那些包含安全修复的发行版。

有关更新 Amazon RDS 数据库实例的更多信息，请参阅 [PostgreSQL 可信扩展](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md#PostgreSQL.Concepts.General.Extensions.Trusted)和 [apply-pending-maintenance-action](https://docs.aws.amazon.com/cli/latest/reference/rds/apply-pending-maintenance-action.html)。

# 支持的 PostgreSQL 扩展版本
<a name="PostgreSQL.Concepts.General.FeatureSupport.Extensions"></a>

RDS for PostgreSQL 支持许多 PostgreSQL 扩展。PostgreSQL 社区有时将这些扩展称为模块。扩展针对 PostgreSQL 引擎提供的功能进行了扩展。您可以在 PostgreSQL 版本的默认数据库参数组中找到 Amazon RDS 支持的扩展列表。您还可使用 `psql` 通过显示 `rds.extensions` 参数来查看当前扩展列表，如以下示例中所示。

```
SHOW rds.extensions; 
```

**注意**  
在 `rds.extensions` 中使用 `psql` 参数时，可能不会准确显示在次要版本中添加的参数。

从 RDS for PostgreSQL 13 开始，某些扩展可以由数据库用户（而不是 `rds_superuser`）安装。它们称为*可信扩展*。要了解更多信息，请参阅[PostgreSQL 可信扩展](#PostgreSQL.Concepts.General.Extensions.Trusted)。

某些版本的 RDS for PostgreSQL 支持 `rds.allowed_extensions` 参数。这个参数允许 `rds_superuser` 限制可以在 RDS for PostgreSQL 数据库实例中安装的扩展。有关更多信息，请参阅 [限制 PostgreSQL 扩展的安装](#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)。

对于每个可用 RDS For PostgreSQL 版本支持的 PostgreSQL 扩展和版本的列表，请参阅《Amazon RDS for PostgreSQL 发行说明》**中的 [Amazon RDS 上支持的 PostgreSQL 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)。

## 限制 PostgreSQL 扩展的安装
<a name="PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction"></a>

您可以限制在 PostgreSQL 数据库实例上安装哪些扩展。默认情况下，不设置此参数，因此如果用户有添加扩展的权限，则可以添加任何受支持的扩展。为此，请将 `rds.allowed_extensions` 参数设置为一串以逗号分隔的扩展名称。通过向此参数添加扩展列表，您可以明确标识 RDS for PostgreSQL 数据库实例可使用的扩展。然后，只有这些扩展才能安装在 PostgreSQL 数据库实例中。

`rds.allowed_extensions` 参数的默认字符串为 '\$1'，这意味着可以安装引擎版本可用的任何扩展。更改 `rds.allowed_extensions` 参数不需要重新启动数据库，因为它是动态参数。

PostgreSQL 数据库实例引擎必须是以下版本之一才能使用 `rds.allowed_extensions` 参数：
+ 所有 PostgreSQL 16 版本
+ PostgreSQL 15 及所有更高版本
+ PostgreSQL 14 及所有更高版本
+ PostgreSQL 13.3 及更高的次要版本
+ PostgreSQL 12.7 及更高的次要版本

 要查看允许哪些扩展安装，请使用以下 psql 命令。

```
postgres=> SHOW rds.allowed_extensions;
 rds.allowed_extensions
------------------------
 *
```

如果扩展是在其被 `rds.allowed_extensions` 参数列表排除之前安装的，则该扩展仍可以正常使用，并且诸如 `ALTER EXTENSION` 和 `DROP EXTENSION` 之类的命令将继续运行。但是，在扩展被限制后，限制扩展的 `CREATE EXTENSION` 命令将失败。

使用 `CREATE EXTENSION CASCADE` 安装扩展依赖项也受到限制。必须在 `rds.allowed_extensions` 中指定扩展及其依赖项。如果扩展依赖项安装失败，整个 `CREATE EXTENSION CASCADE` 语句将失败。

如果 `rds.allowed_extensions` 参数中未包含扩展，则尝试安装时将看到如下错误。

```
ERROR: permission denied to create extension "extension-name" 
HINT: This extension is not specified in "rds.allowed_extensions".
```

## PostgreSQL 可信扩展
<a name="PostgreSQL.Concepts.General.Extensions.Trusted"></a>

安装大部分 PostgreSQL 扩展都需要具备 `rds_superuser` 权限。PostgreSQL 13 推出了可信扩展，这些扩展减少了授予普通用户 `rds_superuser` 权限的需求。使用此特征，用户可以安装许多扩展（如果他们具有对当前数据库的 `CREATE` 权限，而不要求具备 `rds_superuser` 角色）。有关详细信息，请参阅 PostgreSQL 文档中的 SQL [创建扩展](https://www.postgresql.org/docs/current/sql-createextension.html)命令。

下面列出了具有对当前数据库的 `CREATE` 权限，但不需要具备 `rds_superuser` 角色的用户可以安装的扩展：
+ bool\$1plperl
+ [btree\$1gin](http://www.postgresql.org/docs/current/btree-gin.html)
+ [btree\$1gist](http://www.postgresql.org/docs/current/btree-gist.html)
+ [citext](http://www.postgresql.org/docs/current/citext.html)
+ [cube](http://www.postgresql.org/docs/current/cube.html)
+ [dict\$1int](http://www.postgresql.org/docs/current/dict-int.html)
+ [fuzzystrmatch](http://www.postgresql.org/docs/current/fuzzystrmatch.html)
+  [hstore](http://www.postgresql.org/docs/current/hstore.html)
+ [intarray](http://www.postgresql.org/docs/current/intarray.html)
+ [isn](http://www.postgresql.org/docs/current/isn.html)
+ jsonb\$1plperl
+ [ltree](http://www.postgresql.org/docs/current/ltree.html)
+ [pg\$1trgm](http://www.postgresql.org/docs/current/pgtrgm.html)
+ [pgcrypto](http://www.postgresql.org/docs/current/pgcrypto.html)
+ [plperl](https://www.postgresql.org/docs/current/plperl.html)
+ [plpgsql](https://www.postgresql.org/docs/current/plpgsql.html)
+ [pltcl](https://www.postgresql.org/docs/current/pltcl-overview.html)
+ [tablefunc](http://www.postgresql.org/docs/current/tablefunc.html) 
+ [tsm\$1system\$1rows](https://www.postgresql.org/docs/current/tsm-system-rows.html)
+ [tsm\$1system\$1time](https://www.postgresql.org/docs/current/tsm-system-time.html)
+ [unaccent](http://www.postgresql.org/docs/current/unaccent.html)
+ [uuid-ossp](http://www.postgresql.org/docs/current/uuid-ossp.html)

对于每个可用 RDS For PostgreSQL 版本支持的 PostgreSQL 扩展和版本的列表，请参阅《Amazon RDS for PostgreSQL 发行说明》**中的 [Amazon RDS 上支持的 PostgreSQL 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)。

# 使用 Amazon RDS for PostgreSQL 支持的 PostgreSQL 功能
<a name="PostgreSQL.Concepts.General.FeatureSupport"></a>

Amazon RDS for PostgreSQL 支持很多最常见的 PostgreSQL 功能。例如，PostgreSQL 具有对数据库执行例行维护的 autovacuum 功能。原定设置情况下，autovacuum 功能处于活动状态。尽管您可以禁用此功能，但我们强烈建议您继续启用该功能。了解此功能以及您可以做些什么来确保该功能正常工作，如同任何 DBA 基本任务一样。有关 autovacuum 的更多信息，请参阅 [在 Amazon RDS for PostgreSQL 上使用 PostgreSQL autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md)。要了解有关其他常见 DBA 任务的更多信息，请参阅 [Amazon RDS for PostgreSQL 的数据库管理员常见任务](Appendix.PostgreSQL.CommonDBATasks.md)。

RDS for PostgreSQL 还支持向数据库实例添加重要功能的扩展。例如，您可以使用 PostGIS 扩展处理空间数据，或者使用 pg\$1cron 扩展从实例内计划维护。有关 PostgreSQL 扩展的更多信息，请参阅 [将 PostgreSQL 扩展与 Amazon RDS for PostgreSQL 结合使用](Appendix.PostgreSQL.CommonDBATasks.Extensions.md)。

外部数据包装器是一种特定类型的扩展，旨在让您的 RDS for PostgreSQL 数据库实例与其他商用数据库或数据类型配合使用。有关 RDS for PostgreSQL 支持的外部数据包装器的更多信息，请参阅 [使用 Amazon RDS for PostgreSQL 支持的外部数据包装器](Appendix.PostgreSQL.CommonDBATasks.Extensions.foreign-data-wrappers.md)。

在下文中，您可以了解有关 RDS for PostgreSQL 支持的一些其他功能的信息。

**Topics**
+ [使用 RDS for PostgreSQL 自定义数据类型和枚举](PostgreSQL.Concepts.General.FeatureSupport.AlterEnum.md)
+ [适用于 RDS for PostgreSQL 的事件触发条件](PostgreSQL.Concepts.General.FeatureSupport.EventTriggers.md)
+ [适用于 RDS for PostgreSQL 的大页](PostgreSQL.Concepts.General.FeatureSupport.HugePages.md)
+ [为 Amazon RDS for PostgreSQL 执行逻辑复制](PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication.md)
+ [为逻辑复制连接配置 IAM 身份验证](PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.md)
+ [stats\$1temp\$1directory 的 RAM 磁盘](PostgreSQL.Concepts.General.FeatureSupport.RamDisk.md)
+ [适用于 RDS for PostgreSQL 的表空间](PostgreSQL.Concepts.General.FeatureSupport.Tablespaces.md)
+ [用于 EBCDIC 和其他大型机迁移的 RDS for PostgreSQL 排序规则](PostgreSQL.Collations.mainframe.migration.md)
+ [管理 RDS for PostgreSQL 的逻辑插槽同步](Appendix.PostgreSQL.CommonDBATasks.pglogical.slot.synchronization.md)

# 使用 RDS for PostgreSQL 自定义数据类型和枚举
<a name="PostgreSQL.Concepts.General.FeatureSupport.AlterEnum"></a>

PostgreSQL 支持创建自定义数据类型和使用枚举。有关创建和使用枚举以及其他数据类型的更多信息，请参阅 PostgreSQL 文档中的[枚举类型](https://www.postgresql.org/docs/14/datatype-enum.html)。

以下是创建一种类型作为枚举然后在表中插入值的示例。

```
CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple');
CREATE TYPE
CREATE TABLE t1 (colors rainbow);
CREATE TABLE
INSERT INTO t1 VALUES ('red'), ( 'orange');
INSERT 0 2
SELECT * from t1;
colors
--------
red
orange
(2 rows)
postgres=> ALTER TYPE rainbow RENAME VALUE 'red' TO 'crimson';
ALTER TYPE
postgres=> SELECT * from t1;
colors
---------
crimson
orange
(2 rows)
```

# 适用于 RDS for PostgreSQL 的事件触发条件
<a name="PostgreSQL.Concepts.General.FeatureSupport.EventTriggers"></a>

PostgreSQL 的所有当前版本都支持事件触发条件，RDS for PostgreSQL 的所有可用版本也支持事件触发条件。可以使用主用户账户（默认：`postgres`）创建、修改、重命名和删除事件触发条件。事件触发器位于数据库实例级别，因此，它们可应用于实例上的所有数据库。

例如，以下代码创建在每个数据定义语言 (DDL) 命令结束时打印当前用户的事件触发器。

```
CREATE OR REPLACE FUNCTION raise_notice_func()
    RETURNS event_trigger
    LANGUAGE plpgsql AS
$$
BEGIN
    RAISE NOTICE 'In trigger function: %', current_user;
END;
$$;

CREATE EVENT TRIGGER event_trigger_1 
    ON ddl_command_end
EXECUTE PROCEDURE raise_notice_func();
```

有关 PostgreSQL 事件触发器的更多信息，请参阅 PostgreSQL 文档中的[事件触发器](https://www.postgresql.org/docs/current/static/event-triggers.html)。

在 Amazon RDS 上使用 PostgreSQL 事件触发器存在多个限制。这些功能包括：
+ 您不能在只读副本上创建事件触发器。不过，您可以在只读副本源上创建事件触发器。然后，事件触发器复制到只读副本。从源推送更改时，不会触发只读副本上的事件触发器。不过，如果提升只读副本，则当数据库发生操作时将触发现有事件触发器。
+ 要将主要版本升级到使用事件触发器的 PostgreSQL 数据库实例，请确保在升级该实例之前删除事件触发器。

# 适用于 RDS for PostgreSQL 的大页
<a name="PostgreSQL.Concepts.General.FeatureSupport.HugePages"></a>

*大页*是一项内存管理功能，可以减少数据库实例处理大量连续内存数据块（例如共享缓冲区使用的内存数据块）时的开销。RDS for PostgreSQL 的当前所有可用版本支持 PostgreSQL 的这个功能。您可以通过使用对 `mmap` 或 `SYSV` 共享内存的调用，为应用程序分配大页。RDS for PostgreSQL 支持 4 KB 和 2 MB 的页面大小。

您可以通过更改 `huge_pages` 参数的值来启用或禁用大型页面。原定设置情况下，微型、小型和中型数据库实例类以外的所有数据库实例类都会开启此功能。

RDS for PostgreSQL 根据可用的共享内存使用大页。如果由于共享内存约束，数据库实例无法使用大页，Amazon RDS 会阻止数据库实例启动。在这种情况下，Amazon RDS 会将数据库实例的状态设置为不兼容参数状态。在这种情况下，您可以将 `huge_pages` 参数设置为 `off` 以允许 Amazon RDS 启动数据库实例。

`shared_buffers` 参数是设置使用大页所需的共享内存池的关键。`shared_buffers` 参数的原定设置值使用数据库参数宏。此宏设置数据库实例内存可用的总共 8KB 分页的百分比。使用标准大页时，这些页面会位于大页中。如果共享内存参数设置为需要 90% 以上的数据库实例内存，则 Amazon RDS 将数据库实例置于不兼容参数状态。

若要了解有关 PostgreSQL 内存管理的更多信息，请参阅 PostgreSQL 文档中的[资源消耗](https://www.postgresql.org/docs/current/static/runtime-config-resource.html)。

# 为 Amazon RDS for PostgreSQL 执行逻辑复制
<a name="PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication"></a>

从版本 10.4 开始，RDS for PostgreSQL 支持 PostgreSQL 10 中引入的发布和订阅 SQL 语法。要了解更多信息，请参阅 PostgreSQL 文档中的[逻辑复制](https://www.postgresql.org/docs/current/logical-replication.html)。

**注意**  
除了 PostgreSQL 10 中引入的原生 PostgreSQL 逻辑复制功能外，RDS for PostgreSQL 还支持 `pglogical` 扩展。有关更多信息，请参阅 [使用 pglogical 跨实例同步数据](Appendix.PostgreSQL.CommonDBATasks.pglogical.md)。

在下文中，您可以了解有关为 RDS for PostgreSQL 数据库实例设置逻辑复制的信息。

**Topics**
+ [了解逻辑复制和逻辑解码](#PostgreSQL.Concepts.General.FeatureSupport.LogicalDecoding)
+ [使用逻辑复制槽](#PostgreSQL.Concepts.General.FeatureSupport.LogicalReplicationSlots)
+ [使用逻辑复制来复制表级数据](#PostgreSQL.Concepts.LogicalReplication.Tables)

## 了解逻辑复制和逻辑解码
<a name="PostgreSQL.Concepts.General.FeatureSupport.LogicalDecoding"></a>

RDS for PostgreSQL 支持使用 PostgreSQL 的逻辑复制槽流式传输预写日志 (WAL) 更改。其还支持使用逻辑解码。您可以在实例上设置逻辑复制槽并通过这些槽将数据库更改流式传输到某个客户端（如 `pg_recvlogical`）。您可在数据库级别创建逻辑复制槽，它们支持与单个数据库的复制连接。

PostgreSQL 逻辑复制的最常见客户端是 AWS Database Migration Service 或 Amazon EC2 实例上的自定义托管主机。逻辑复制槽没有关于流接收器的信息。此外，不要求目标是副本数据库。如果设置逻辑复制槽并且不从该槽进行读取，则数据可写入并快速填满数据库实例上的存储。

您可启用 Amazon RDS 的 PostgreSQL 逻辑复制和逻辑解码，带有参数、复制连接类型和安全角色。逻辑解码的客户端可以是能够与 PostgreSQL 数据库实例上的数据库建立复制连接的任何客户端。

**为 RDS for PostgreSQL 数据库实例启用逻辑解码**

1. 确保您使用的用户账户具有以下角色：
   + `rds_superuser` 角色，以使您可以启用逻辑复制 
   + `rds_replication` 角色，以授予管理逻辑槽并使用逻辑槽流式处理数据的权限

1. 将 `rds.logical_replication` 静态参数设置为 1。在应用该参数时，还将设置参数 `wal_level`、`max_wal_senders`、`max_replication_slots` 和 `max_connections`。这些参数更改可能会增加 WAL 生成，因此，仅在使用逻辑槽时设置 `rds.logical_replication` 参数。

1. 重启数据库实例，静态 `rds.logical_replication` 参数才会生效。

1. 请按下一部分中的说明创建逻辑复制槽。该过程需要您指定解码插件。目前，RDS for PostgreSQL 支持 PostgreSQL 随附的 test\$1decoding 和 wal2json 输出插件。

有关 PostgreSQL 逻辑解码的更多信息，请参阅 [PostgreSQL 文档](https://www.postgresql.org/docs/current/static/logicaldecoding-explanation.html)。

## 使用逻辑复制槽
<a name="PostgreSQL.Concepts.General.FeatureSupport.LogicalReplicationSlots"></a>

您可以通过 SQL 命令来使用逻辑槽。例如，以下命令使用默认的 PostgreSQL 输出插件 `test_slot` 创建一个名为 `test_decoding` 的逻辑槽。

```
SELECT * FROM pg_create_logical_replication_slot('test_slot', 'test_decoding');
slot_name    | xlog_position
-----------------+---------------
regression_slot | 0/16B1970
(1 row)
```

要列出逻辑槽，请使用以下命令。

```
SELECT * FROM pg_replication_slots;
```

要删除逻辑槽，请使用以下命令。

```
SELECT pg_drop_replication_slot('test_slot');
pg_drop_replication_slot
-----------------------
(1 row)
```

有关使用逻辑复制槽的更多示例，请参阅 PostgreSQL 文档中的[逻辑解码示例](https://www.postgresql.org/docs/9.5/static/logicaldecoding-example.html)。

创建逻辑复制槽后，就可以开始流式处理。以下示例显示了如何通过流式复制协议控制逻辑解码。此示例使用 PostgreSQL 发行版中包含的程序 pg\$1recvlogical。此操作要求设置客户端身份验证以允许复制连接。

```
pg_recvlogical -d postgres --slot test_slot -U postgres
    --host -instance-name.111122223333.aws-region.rds.amazonaws.com 
    -f -  --start
```

要查看 `pg_replication_origin_status` 视图的内容，请查询 `pg_show_replication_origin_status` 函数。

```
SELECT * FROM pg_show_replication_origin_status();
local_id | external_id | remote_lsn | local_lsn
----------+-------------+------------+-----------
(0 rows)
```

## 使用逻辑复制来复制表级数据
<a name="PostgreSQL.Concepts.LogicalReplication.Tables"></a>

在 RDS for PostgreSQL 中，可以使用逻辑复制将数据从源表复制到目标表。逻辑复制首先对源表中的现有数据执行初始加载，然后继续复制持续发生的更改。

1. 

**创建源表**

   连接到 RDS for PostgreSQL 数据库实例中的源数据库。

   ```
   source=> CREATE TABLE testtab (slno int primary key);
   CREATE TABLE
   ```

1. 

**将数据插入到源表中**

   ```
   source=> INSERT INTO testtab VALUES (generate_series(1,1000));
   INSERT 0 1000
   ```

1. 

**为源表创建发布**
   + 为源表创建发布：

     ```
     source=> CREATE PUBLICATION testpub FOR TABLE testtab;
     CREATE PUBLICATION
     ```
   + 使用 SELECT 查询来验证已创建的发布的详细信息：

     ```
     source=> SELECT * FROM pg_publication;
       oid   | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate | pubviaroot
     --------+---------+----------+--------------+-----------+-----------+-----------+-------------+------------
      115069 | testpub |    16395 | f            | t         | t         | t         | t           | f
     (1 row)
     ```
   + 验证源表已添加到发布中：

     ```
     source=> SELECT * FROM pg_publication_tables; 
     pubname | schemaname | tablename
     ---------+------------+-----------
      testpub | public     | testtab
     (1 rows)
     ```
   + 要复制数据库中的所有表，请使用：

     ```
     CREATE PUBLICATION testpub FOR ALL TABLES;
     ```
   + 如果已经为单个表创建了发布，并且您需要添加新表，则可以运行下面的查询来将任何新表添加到现有发布中：

     ```
     ALTER PUBLICATION <publication_name> add table <new_table_name>;
     ```

1. 

**连接到目标数据库并创建目标表**
   + 连接到目标数据库实例中的目标数据库。创建与源表同名的目标表：

     ```
     target=> CREATE TABLE testtab (slno int primary key);
     CREATE TABLE
     ```
   + 通过对目标表运行 SELECT 查询，确保目标表中不存在数据：

     ```
         
     target=> SELECT count(*) FROM testtab;
      count
     -------
          0
     (1 row)
     ```

1. 

**在目标数据库中创建并验证订阅**
   + 在目标数据库中创建订阅：

     ```
     target=> CREATE SUBSCRIPTION testsub 
     CONNECTION 'host=<source RDS/host endpoint> port=5432 dbname=<source_db_name> user=<user> password=<password>' 
     PUBLICATION testpub;
     NOTICE:  Created replication slot "testsub" on publisher
     CREATE SUBSCRIPTION
     ```
   + 使用 SELECT 查询来验证是否启用了订阅：

     ```
     target=> SELECT oid, subname, subenabled, subslotname, subpublications FROM pg_subscription;
       oid  | subname | subenabled | subslotname | subpublications
     -------+---------+------------+-------------+-----------------
      16434 | testsub | t          | testsub     | {testpub}
     (1 row)
     ```
   + 创建订阅后，它会将源表中的所有数据加载到目标表。对目标表运行 SELECT 查询以验证初始数据是否已加载：

     ```
     target=> SELECT count(*) FROM testtab;
      count
     -------
       1000
     (1 row)
     ```

1. 

**验证源数据库中的复制槽**

   在目标数据库中创建订阅会在源数据库中创建复制槽。通过对源数据库运行以下 SELECT 查询来验证复制槽详细信息：

   ```
   source=> SELECT * FROM pg_replication_slots;
    
   slot_name |  plugin  | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size
   ----------+----------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------
   testsub   | pgoutput | logical   | 115048 | source   | f         | t      |        846 |      |         6945 | 58/B4000568 | 58/B40005A0         | reserved   |
   (1 row)
   ```

1. 

**测试复制**
   + 通过在源表中插入行，测试源表中的数据更改是否复制到目标表：

     ```
     source=> INSERT INTO testtab VALUES(generate_series(1001,2000));
     INSERT 0 1000
     
     source=> SELECT count(*) FROM testtab; 
      count
     -------
       2000
     (1 row)
     ```
   + 验证目标表中的行数，以确认正在复制新的插入内容：

     ```
     target=> SELECT count(*) FROM testtab;
      count
     -------
       2000
     (1 row)
     ```

1. 

**添加表后刷新订阅**
   + 在向现有发布添加新表时，务必刷新订阅才能使更改生效：

     ```
     ALTER SUBSCRIPTION <subscription_name> REFRESH PUBLICATION;
     ```
   + 此命令从发布者那里提取缺失的表信息，并开始复制自创建或上次刷新订阅以来添加到已订阅发布中的表。

# 为逻辑复制连接配置 IAM 身份验证
<a name="PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication"></a>

从 RDS for PostgreSQL 版本 11 及更高版本开始，您可以对复制连接使用 AWS Identity and Access Management（IAM）身份验证。此功能允许您使用 IAM 角色而不是密码来管理数据库访问权限，从而增强安全性。该功能以集群和实例粒度运行，并遵循与标准 IAM 身份验证相同的安全模型。

复制连接的 IAM 身份验证是一项可选功能。要启用此功能，请在数据库集群或数据库参数组中将 `rds.iam_auth_for_replication` 参数设置为 1。由于这是一个动态参数，因此您的数据库集群或实例无需重新启动，这样您就可以在不停机的情况下对现有工作负载使用 IAM 身份验证。启用此功能之前，您必须满足下面列出的先决条件。

**Topics**
+ [先决条件](#PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Prerequisites)
+ [对复制连接启用 IAM 身份验证](#PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Enabling)
+ [对复制连接禁用 IAM 身份验证](#PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Disabling)
+ [限制和注意事项](#PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Limitations)

## 先决条件
<a name="PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Prerequisites"></a>

要对复制连接使用 IAM 身份验证，您需要满足以下所有要求：
+ RDS for PostgreSQL 数据库实例必须为版本 11 或更高版本。
+ 在您的发布者 RDS for PostgreSQL 数据库实例上：
  + 启用 IAM 数据库身份验证。有关更多信息，请参阅 [启用和禁用 IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.Enabling.md)。
  + 通过将 `rds.logical_replication` 参数设置为 1，启用逻辑复制。

在逻辑复制中，发布者是向订阅用户数据库发送数据的源 RDS for PostgreSQL 数据库。有关更多信息，请参阅 [为 Amazon RDS for PostgreSQL 执行逻辑复制](PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication.md)。

**注意**  
必须在发布者 RDS for PostgreSQL 数据库实例上同时启用 IAM 身份验证和逻辑复制。如果任一项未启用，则无法对复制连接使用 IAM 身份验证。

## 对复制连接启用 IAM 身份验证
<a name="PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Enabling"></a>

要对复制连接启用 IAM 身份验证，请完成以下步骤。

**对复制连接启用 IAM 身份验证**

1. 验证 RDS for PostgreSQL 数据库集群或实例满足对复制连接使用 IAM 身份验证的所有先决条件。有关更多信息，请参阅 [先决条件](#PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Prerequisites)。

1. 根据 RDS for PostgreSQL 设置配置 `rds.iam_auth_for_replication` 参数：
   + 对于 RDS for PostgreSQL 数据库实例：修改数据库参数组。
   + 对于多可用集群：修改数据库集群参数组。

   将 `rds.iam_auth_for_replication` 设置为 1。这是一个动态参数，无需重启即可立即生效。
**注意**  
多可用区集群仅使用数据库集群参数组。在多可用区集群中无法修改各个实例参数组。

1. 连接到您的数据库并向您的复制用户授予必要的角色：

   以下 SQL 命令授予对复制连接启用 IAM 身份验证所需的角色：

   ```
   -- Grant IAM authentication role
   GRANT rds_iam TO replication_user_name;
   
   -- Grant replication privileges
   ALTER USER replication_user_name WITH REPLICATION;
   ```

   完成这些步骤后，指定的用户必须对复制连接使用 IAM 身份验证。
**重要**  
启用该功能后，同时拥有 `rds_iam` 和 `rds_replication` 角色的用户必须对复制连接使用 IAM 身份验证。无论角色是直接分配给用户还是通过其他角色继承，都是如此。

## 对复制连接禁用 IAM 身份验证
<a name="PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Disabling"></a>

您可以使用下面任何方法对复制连接禁用 IAM 身份验证：
+ 在数据库实例的数据库参数组中，或在多可用区集群的数据库集群参数组中，将 `rds.iam_auth_for_replication` 参数设置为 0。
+ 或者，您可以在 RDS for PostgreSQL 数据库集群或实例上禁用以下任一功能：
  + 通过将 `rds.logical_replication` 参数设置为 0 来禁用逻辑复制
  + 禁用 IAM 身份验证

禁用该功能后，复制连接可以使用数据库密码进行身份验证。

**注意**  
即使启用了该功能，没有 `rds_iam` 角色的用户的复制连接也可以使用密码身份验证。

## 限制和注意事项
<a name="PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Limitations"></a>

对逻辑复制连接使用 IAM 身份验证时，请考虑以下限制和注意事项。
+ 此功能仅适用于 RDS for PostgreSQL 版本 11 及更高版本。
+ 发布者必须支持对复制连接使用 IAM 身份验证。
+ 默认情况下，IAM 身份验证令牌会在 15 分钟后失效。在令牌失效之前，您可能需要刷新长时间运行的复制连接。

# stats\$1temp\$1directory 的 RAM 磁盘
<a name="PostgreSQL.Concepts.General.FeatureSupport.RamDisk"></a>

您可使用 RDS for PostgreSQL 参数 `rds.pg_stat_ramdisk_size` 指定分配给用于存储 PostgreSQL `stats_temp_directory` 的 RAM 磁盘系统内存。RAM 磁盘参数仅在 RDS for PostgreSQL 版本 14 及更低版本中可用。

在某些工作负载下，设置该参数可提高性能并降低 I/O 要求。有关 `stats_temp_directory` 的更多信息，请参阅 [PostgreSQL 文档](https://www.postgresql.org/docs/current/static/runtime-config-statistics.html#GUC-STATS-TEMP-DIRECTORY)。

要为您的 `stats_temp_directory` 设置 RAM 磁盘，可在数据库实例使用的参数组中将 `rds.pg_stat_ramdisk_size` 参数设置为整数值。此参数表示 MB，因此必须使用整数值。表达式、公式和函数对 `rds.pg_stat_ramdisk_size` 参数无效。请务必重启数据库实例，以便更改能够生效。有关设置参数的信息，请参阅[Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

例如，以下 AWS CLI 命令将 RAM 磁盘参数设置为 256 MB。

```
aws rds modify-db-parameter-group \
    --db-parameter-group-name pg-95-ramdisk-testing \
    --parameters "ParameterName=rds.pg_stat_ramdisk_size, ParameterValue=256, ApplyMethod=pending-reboot"
```

在重启后，请运行以下命令查看 `stats_temp_directory` 的状态。

```
postgres=> SHOW stats_temp_directory;
```

 该命令应返回以下内容。

```
stats_temp_directory
---------------------------
/rdsdbramdisk/pg_stat_tmp
(1 row)
```

# 适用于 RDS for PostgreSQL 的表空间
<a name="PostgreSQL.Concepts.General.FeatureSupport.Tablespaces"></a>

为了实现兼容性，RDS for PostgreSQL 支持表空间。由于所有存储都在单个逻辑卷上，因此不能使用表空间进行 I/O 拆分或隔离。我们的基准测试和经验表明，对于大多数使用案例，单个逻辑卷是最佳设置。

若要为 RDS for PostgreSQL 数据库实例创建和使用表空间，需要 `rds_superuser` 角色。RDS for PostgreSQL 数据库实例的主用户账户（默认名称：`postgres`）是此角色的成员。有关更多信息，请参阅 [了解 PostgreSQL 角色和权限](Appendix.PostgreSQL.CommonDBATasks.Roles.md)。

如果在创建表空间时指定文件名，则路径前缀为 `/rdsdbdata/db/base/tablespace`。以下示例将表空间文件放在 `/rdsdbdata/db/base/tablespace/data` 中。此示例假定 `dbadmin` 用户（角色）存在且已授予其使用表空间所需的 `rds_superuser` 角色。

```
postgres=> CREATE TABLESPACE act_data
  OWNER dbadmin
  LOCATION '/data';
CREATE TABLESPACE
```

若要了解有关 PostgreSQL 表空间的更多信息，请参阅 PostgreSQL 文档中的[表空间](https://www.postgresql.org/docs/current/manage-ag-tablespaces.html)。

# 用于 EBCDIC 和其他大型机迁移的 RDS for PostgreSQL 排序规则
<a name="PostgreSQL.Collations.mainframe.migration"></a>

RDS for PostgreSQL 版本 10 及更高版本包括 ICU 版本 60.2，该版本基于 Unicode 10.0，并包括来自 Unicode 通用区域设置数据存储库 CLDR 32 的排序规则。这些软件国际化库确保字符编码以一致的方式呈现，无论操作系统或平台如何。有关 Unicode CLDR-32 的更多信息，请参阅 Unicode CLDR 网站上的 [CLDR 32 版本注释](https://cldr.unicode.org/index/downloads/cldr-32)。您可以通过 [ICU 技术委员会（ICU-TC）](https://icu.unicode.org/home)网站了解有关 Unicode (ICU) 国际化组件的更多信息。有关 ICU-60 的信息，请参阅[下载 ICU 60](https://icu.unicode.org/download/60)。

从版本 14.3 开始，RDS for PostgreSQL 还包括排序规则，这些排序规则有助于从基于 EBCDIC 的系统进行数据集成和转换。扩展二进制编码的十进制交换码或 *EBCDIC* 编码通常由大型机操作系统使用。这些 Amazon RDS 提供的排序规则的定义非常狭窄，仅对那些直接映射到 EBCDIC 代码页的 Unicode 字符进行排序。字符按 EBCDIC 代码点顺序排序，以便在转换后进行数据验证。这些排序规则不包括非规范化表单，也不包含不直接映射到源 EBCDIC 代码页上字符的 Unicode 字符。

EBCDIC 代码页和 Unicode 代码点之间的字符映射基于 IBM 发布的表。可以从 IBM 下载整套的[压缩文件](http://download.boulder.ibm.com/ibmdl/pub/software/dw/java/cdctables.zip)。RDS for PostgreSQL 使用这些映射以及 ICU 提供的工具来创建本节的各表中列出的排序规则。排序规则名称包括 ICU 要求的语言和国家/地区。但是，EBCDIC 代码页没有指定语言，一些 EBCDIC 代码页涵盖多个国家/地区。这意味着表中排序规则名称的语言和国家/地区部分是任意的，它们不需要与当前的区域设置相匹配。换句话说，代码页码是该表中排序规则名称的最重要部分。您可以在任何 RDS for PostgreSQL 数据库中使用以下各表列出的任何排序规则。
+ [Unicode to EBCDIC collations table](#ebcdic-table) – 一些大型机数据迁移工具在内部使用 LATIN1 或 LATIN9 来编码和处理数据。此类工具使用往返操作方案来保持数据完整性并支持反向转换。使用 LATIN1 编码处理数据（这种编码不需要特殊处理）的工具可以使用此表中的排序规则。
+ [Unicode to LATIN9 collations table](#latin9-table) – 您可以在任何 RDS for PostgreSQL 数据库中使用这些排序规则。

 

在下表中，您可以找到 RDS for PostgreSQL 中可用的排序规则，这些排序规则将 EBCDIC 代码页映射到 Unicode 代码点。我们建议您将此表中的排序规则用于需要根据 IBM 代码页的顺序进行排序的应用程序开发。<a name="ebcdic-table"></a>


| PostgreSQL 排序规则名称 | 代码页映射和排序顺序的描述 | 
| --- | --- | 
| da-DK-cp277-x-icu | 直接映射到 IBM EBCDIC 代码页 277（每个转换表）的 Unicode 字符按 IBM CP 277 代码点顺序排序 | 
| de-DE-cp273-x-icu | 直接映射到 IBM EBCDIC 代码页 273（每个转换表）的 Unicode 字符按 IBM CP 273 代码点顺序排序 | 
| en-GB-cp285-x-icu | 直接映射到 IBM EBCDIC 代码页 285（每个转换表）的 Unicode 字符按 IBM CP 285 代码点顺序排序 | 
| en-US-cp037-x-icu | 直接映射到 IBM EBCDIC 代码页 037（每个转换表）的 Unicode 字符按 IBM CP 37 代码点顺序排序 | 
| es-ES-cp284-x-icu | 直接映射到 IBM EBCDIC 代码页 284（每个转换表）的 Unicode 字符按 IBM CP 284 代码点顺序排序 | 
| fi-FI-cp278-x-icu | 直接映射到 IBM EBCDIC 代码页 278（每个转换表）的 Unicode 字符按 IBM CP 278 代码点顺序排序 | 
| fr-FR-cp297-x-icu | 直接映射到 IBM EBCDIC 代码页 297（每个转换表）的 Unicode 字符按 IBM CP 297 代码点顺序排序 | 
| it-IT-cp280-x-icu | 直接映射到 IBM EBCDIC 代码页 280（每个转换表）的 Unicode 字符按 IBM CP 280 代码点顺序排序 | 
| nl-BE-cp500-x-icu | 直接映射到 IBM EBCDIC 代码页 500（每个转换表）的 Unicode 字符按 IBM CP 500 代码点顺序排序 | 

Amazon RDS 提供了一组额外的排序规则，这些排序规则使用 IBM 发布的表，按源数据的 EBCDIC 代码页的原始代码点顺序，对映射到 LATIN9 字符的 Unicode 代码点进行排序。<a name="latin9-table"></a>


| PostgreSQL 排序规则名称 | 代码页映射和排序顺序的描述 | 
| --- | --- | 
| da-DK-cp1142m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1142（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1142 代码点顺序排序 | 
| de-DE-cp1141m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1141（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1141 代码点顺序排序 | 
| en-GB-cp1146m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1146（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1146 代码点顺序排序 | 
| en-US-cp1140m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1140（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1140 代码点顺序排序 | 
| es-ES-cp1145m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1145（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1145 代码点顺序排序 | 
| fi-FI-cp1143m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1143（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1143 代码点顺序排序 | 
| fr-FR-cp1147m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1147（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1147 代码点顺序排序 | 
| it-IT-cp1144m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1144（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1144 代码点顺序排序 | 
| nl-BE-cp1148m-x-icu | 映射到最初从 IBM EBCDIC 代码页 1148（每个转换表）转换而来的 LATIN9 字符的 Unicode 字符按 IBM CP 1148 代码点顺序排序 | 

在下文中，您可以找到使用 RDS for PostgreSQL 排序规则的示例。

```
db1=> SELECT pg_import_system_collations('pg_catalog');
 pg_import_system_collations
-----------------------------
                          36
db1=> SELECT '¤' < 'a' col1;
 col1
------
 t  
db1=> SELECT '¤' < 'a' COLLATE "da-DK-cp277-x-icu" col1;
 col1
------
 f
```

我们建议您将 [Unicode to EBCDIC collations table](#ebcdic-table)和 [Unicode to LATIN9 collations table](#latin9-table)中的排序规则用于需要根据 IBM 代码页的顺序进行排序的应用程序开发。以下排序规则（后缀为字母“b”）在 `pg_collation` 中也可见，但供 AWS 中的大型机数据集成和迁移工具使用，这些工具将代码页映射到特定的代码点偏移，并要求在排序规则中进行特殊处理。换句话说，不建议使用以下排序规则。
+ da-DK-277b-x-icu
+ da-DK-1142b-x-icu
+ de-DE-cp273b-x-icu
+ de-DE-cp1141b-x-icu
+ en-GB-cp1146b-x-icu
+ en-GB-cp285b-x-icu
+ en-US-cp037b-x-icu
+ en-US-cp1140b-x-icu
+ es-ES-cp1145b-x-icu
+ es-ES-cp284b-x-icu
+ fi-FI-cp1143b-x-icu
+ fr-FR-cp1147b-x-icu
+ fr-FR-cp297b-x-icu
+ it-IT-cp1144b-x-icu
+ it-IT-cp280b-x-icu
+ nl-BE-cp1148b-x-icu
+ nl-BE-cp500b-x-icu

要了解有关将应用程序从大型机环境迁移到 AWS 的更多信息，请参阅[什么是 AWS Mainframe Modernization？](https://docs.aws.amazon.com/m2/latest/userguide/what-is-m2.html)

有关在 PostgreSQL 中管理排序规则的更多信息，请参阅 PostgreSQL 文档中的[排序规则支持](https://www.postgresql.org/docs/current/collation.html)。

# 管理 RDS for PostgreSQL 的逻辑插槽同步
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.slot.synchronization"></a>

从社区 PostgreSQL 17 开始，已通过 `sync_replication_slots` 参数或相关的函数 `pg_sync_replication_slots()` 引入了一项新功能（即自动将逻辑复制插槽从主服务器同步到备用服务器），该功能可在执行时手动同步插槽。

从 RDS for PostgreSQL 17 开始提供这些功能。典型的设置将具有主实例及其[只读副本](USER_PostgreSQL.Replication.ReadReplicas.md)，以及主实例的逻辑复制订阅用户。

确保在创建订阅时将失效转移选项设置为 true：

```
CREATE SUBSCRIPTION subname CONNECTION 'host=...' PUBLICATION pubname WITH (failover = true);
```

这将在发布者上创建一个启用失效转移的逻辑插槽。

```
postgres=> SELECT slot_name, slot_type, failover FROM pg_catalog.pg_replication_slots;
 slot_name | slot_type | failover 
-----------+-----------+----------
 subname   | logical   | t
(1 row)
```

通过启用插槽同步，主实例上的所有失效转移逻辑复制插槽都将在物理备用实例上自动创建并定期同步。确保已通过[参数组](USER_WorkingWithParamGroups.Associating.md)设置以下值：
+ `rds.logical_replication` 必须为 `1` 才能启用逻辑复制
+ 在备用实例上，`hot_standby_feedback` 必须为 `1`
+ 备用实例上的 `rds.logical_slot_sync_dbname` 必须设置为有效的数据库名称

  此参数的默认值为 `postgres`。如果逻辑发布实例有 `postgres` 数据库，则无需更改默认参数。
+ 主实例上的 `synchronized_standby_slots` 必须设置为要同步的备用实例的物理复制插槽
+ `sync_replication_slots` 必须为 `1` 才能启用自动同步

使用启用失效转移的订阅插槽和上述参数值，当提升备用实例时，订阅用户可以更改其对这个新提升实例的订阅，并继续无缝地进行逻辑复制。

# 连接到运行 PostgreSQL 数据库引擎的数据库实例
<a name="USER_ConnectToPostgreSQLInstance"></a>

在 Amazon RDS 预置数据库实例后，您可以使用任何标准 SQL 客户端应用程序连接到该实例。在可以连接之前，数据库实例必须是可用且可访问的。是否可以从 VPC 外部连接到实例取决于您创建 Amazon RDS 数据库实例的方式：
+ 如果您将数据库实例创建为*公有*，VPC 外部的设备和 Amazon EC2 实例便可以连接到您的数据库。
+ 如果您将数据库实例创建为*私有*，只有 Amazon VPC 内的 Amazon EC2 实例和设备可以连接到您的数据库。

若要检查数据库实例是公有还是私有实例，请使用 AWS 管理控制台 查看实例的 **Connectivity & security**（连接和安全性）选项卡。您可以在 **Security**（安全性）项下找到“公开访问”值，其中“否”表示私有，“是”表示公有。

要详细了解不同的 Amazon RDS 和 Amazon VPC 配置及其如何影响可访问性，请参阅 [在 VPC 中访问数据库实例的场景](USER_VPC.Scenarios.md)。

**Contents**
+ [安装 psql 客户端](#install-psql)
+ [查找有关 RDS for PostgreSQL 数据库实例的连接信息](#postgresql-endpoint)
+ [使用 pgAdmin 连接到 RDS for PostgreSQL 数据库实例](USER_ConnectToPostgreSQLInstance.pgAdmin.md)
+ [使用 psql 连接到 RDS for PostgreSQL 数据库实例](USER_ConnectToPostgreSQLInstance.psql.md)
+ [使用 Amazon Web Services（AWS）JDBC 驱动程序连接到 RDS for PostgreSQL](PostgreSQL.Connecting.JDBCDriver.md)
+ [使用 Amazon Web Services（AWS）Python 驱动程序连接到 RDS for PostgreSQL](PostgreSQL.Connecting.PythonDriver.md)
+ [排除与您的 RDS for PostgreSQL 实例的连接故障](USER_ConnectToPostgreSQLInstance.Troubleshooting.md)
  + [错误 – FATAL：数据库*名称*不存在](USER_ConnectToPostgreSQLInstance.Troubleshooting.md#USER_ConnectToPostgreSQLInstance.Troubleshooting-DBname)
  + [错误 – 无法连接到服务器：连接超时](USER_ConnectToPostgreSQLInstance.Troubleshooting.md#USER_ConnectToPostgreSQLInstance.Troubleshooting-timeout)
  + [安全组访问规则错误](USER_ConnectToPostgreSQLInstance.Troubleshooting.md#USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules)

## 安装 psql 客户端
<a name="install-psql"></a>

要从 EC2 实例连接到您的数据库实例，您可以在 EC2 实例上安装 PostgreSQL 客户端。要在 Amazon Linux 2023 上安装 psql 客户端的最新版本，请运行以下命令：

```
sudo dnf install postgresql<version number>
```

要在 Amazon Linux 2 上安装 psql 客户端的最新版本，请运行以下命令：

```
sudo yum install -y postgresql
```

要在 Ubuntu 上安装 psql 客户端的最新版本，请运行以下命令：

```
sudo apt install -y postgresql-client
```

## 查找有关 RDS for PostgreSQL 数据库实例的连接信息
<a name="postgresql-endpoint"></a>

如果数据库实例可用且可访问，则可以通过向 SQL 客户端应用程序提供以下信息进行连接：
+ 数据库实例端点，用作实例的主机名（DNS 名称）。
+ 数据库实例侦听的端口。对于 PostgreSQL，原定设置端口为 5432。
+ 数据库实例的用户名和密码。PostgreSQL 的原定设置“主用户名”是 `postgres`。
+ 数据库的名称和密码（数据库名称）。

 要获取这些详细信息，您可以使用 AWS 管理控制台、AWS CLI [describe-db-instances](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-instances.html) 命令或 Amazon RDS API [DescribeDBInstances](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBInstances.html) 操作。

**要使用 AWS 管理控制台 查找端点、端口编号和数据库名称**

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

1. 打开 RDS 控制台，然后选择 **Databases (数据库)** 以显示数据库实例的列表。

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

1. 在**连接和安全性**选项卡上，复制端点。另请注意端口号。您需要端点和端口号才能连接到数据库实例。  
![\[从 RDS 控制台获取端点\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/PostgreSQL-endpoint.png)

1. 在 **Configuration**（配置）选项卡中，记下数据库名称。如果您在创建 RDS for PostgreSQL 实例时创建了数据库，就会看到数据库名称下列出的名称。如果您没有创建数据库，则数据库名称将显示破折号 (‐)。  
![\[从 RDS 控制台获取数据库名称\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/PostgreSQL-db-name.png)

下面是两种连接到 PostgreSQL 数据库实例的方法。第一个示例使用 pgAdmin，这是一个时下受欢迎的用于 PostgreSQL 的开源管理和开发工具。第二个示例使用 psql，这是一个命令行实用工具，包含在 PostgreSQL 安装中。

# 使用 pgAdmin 连接到 RDS for PostgreSQL 数据库实例
<a name="USER_ConnectToPostgreSQLInstance.pgAdmin"></a>

您可以使用开源工具 pgAdmin 连接到 RDS for PostgreSQL 数据库实例。客户端计算机上不必具有 PostgreSQL 的本地实例，即可从 [http://www.pgadmin.org/](http://www.pgadmin.org/) 下载和使用 pgAdmin。

**要使用 pgAdmin 连接到 RDS for PostgreSQL 数据库实例**

1. 在您的客户端计算机上启动 pgAdmin 应用程序。

1. 在 **Dashboard** (控制面板) 选项卡上，选择 **Add New Server** (添加新服务器)。

1. 在 **Create - Server** (创建 - 服务器) 对话框中，在 **General** (常规) 选项卡上键入名称以在 pgAdmin 中标识该服务器。

1. 在 **Connection (连接)** 选项卡上，键入您的数据库实例的以下信息：
   + 对于 **Host (主机)**，键入端点，例如 `mypostgresql.c6c8dntfzzhgv0.us-east-2.rds.amazonaws.com`。
   + 对于 **Port (端口)**，键入分配的端口。
   + 对于 **Username**（用户名），键入您在创建数据库实例时输入的用户名（如果您更改了“主用户名”的默认值，`postgres`）。
   + 对于 **Password (密码)**，键入您在创建数据库实例时输入的密码。  
![\[键入您在创建数据库实例时输入的密码。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/Postgres-Connect01.png)

1. 选择**保存**。

   如果您有任何连接问题，请参阅[排除与您的 RDS for PostgreSQL 实例的连接故障](USER_ConnectToPostgreSQLInstance.Troubleshooting.md)。

1. 要在 pgAdmin 浏览器中访问数据库，请依次展开 **Servers** (服务器)、数据库实例和 **Databases** (数据库)。选择数据库实例的数据库名称。  
![\[在 pgAdmin 浏览器中选择数据库实例的数据库名称\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/Postgres-Connect02.png)

1. 要打开可在其中输入 SQL 命令的面板，请依次选择 **Tools** (工具) 和 **Query Tool** (查询工具)。

# 使用 psql 连接到 RDS for PostgreSQL 数据库实例
<a name="USER_ConnectToPostgreSQLInstance.psql"></a>

可使用 psql 命令行实用工具的本地实例连接到 RDS for PostgreSQL 数据库实例。需要在您的客户端计算机上安装 PostgreSQL 或 psql 客户端。

您可以从 [PostgreSQL](https://www.postgresql.org/download/) 网站下载 PostgreSQL 客户端。请按照特定于您的操作系统版本的说明安装 psql。

要使用 psql 连接到 RDS for PostgreSQL 数据库实例，您需要提供主机 (DNS) 信息、访问凭证以及数据库名称。

使用以下格式之一连接到 RDS for PostgreSQL 数据库实例。在连接时，系统将提示您输入密码。对于批处理作业或脚本，请使用 `--no-password` 选项。此选项面向整个会话设置。

**注意**  
如果服务器需要进行密码身份验证，而密码不能从其他来源获取，`--no-password` 连接尝试则会失败。有关更多信息，请参阅 [psql 文档](https://www.postgresql.org/docs/13/app-psql.html)。

如果这是您第一次连接到此数据库实例，或者如果您尚未为此 RDS for PostgreSQL 实例创建数据库，则可以使用“主用户名”和密码连接到 **postgres** 数据库。

对于 Unix，使用以下格式。

```
psql \
   --host=<DB instance endpoint> \
   --port=<port> \
   --username=<master username> \
   --password \
   --dbname=<database name>
```

对于 Windows，使用以下格式。

```
psql ^
   --host=<DB instance endpoint> ^
   --port=<port> ^
   --username=<master username> ^
   --password ^
   --dbname=<database name>
```

例如，以下命令使用虚构的凭证连接到名为 `mypgdb` 的 PostgreSQL 数据库实例上名为 `mypostgresql` 的数据库。

```
psql --host=mypostgresql.c6c8mwvfdgv0.us-west-2.rds.amazonaws.com --port=5432 --username=awsuser --password --dbname=mypgdb 
```

# 使用 Amazon Web Services（AWS）JDBC 驱动程序连接到 RDS for PostgreSQL
<a name="PostgreSQL.Connecting.JDBCDriver"></a>

Amazon Web Services（AWS）JDBC 驱动程序已重新设计为高级 JDBC 包装器。此包装器是对现有 JDBC 驱动程序各项功能的补充和扩展。该驱动程序与社区 pgJDBC 驱动程序兼容。

要安装 AWS JDBC 驱动程序，请附加 AWS JDBC 驱动程序.jar 文件（位于应用程序 `CLASSPATH` 中），并保留对相应社区驱动程序的引用。按如下方式更新相应的连接 URL 前缀：
+ `jdbc:postgresql://`到 `jdbc:aws-wrapper:postgresql://`。

有关 AWS JDBC 驱动程序的更多信息及其完整使用说明，请参阅 [Amazon Web Services (AWS) JDBC Driver GitHub 存储库](https://github.com/awslabs/aws-advanced-jdbc-wrapper)。

# 使用 Amazon Web Services（AWS）Python 驱动程序连接到 RDS for PostgreSQL
<a name="PostgreSQL.Connecting.PythonDriver"></a>

Amazon Web Services（AWS）驱动程序设计为高级 Python 包装器。这款包装器是对开源 Psycopg 驱动程序的各项功能的补充和扩展。AWS Python 驱动程序支持 Python 3.8 及更高版本。您可以使用 `pip` 命令和 `psycopg` 开源软件包安装 `aws-advanced-python-wrapper` 程序包。

有关 AWS JDBC 驱动程序的更多信息及其完整使用说明，请参阅 [Amazon Web Services（AWS）Python 驱动程序 GitHub 存储库](https://github.com/awslabs/aws-advanced-python-wrapper)。

# 排除与您的 RDS for PostgreSQL 实例的连接故障
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting"></a>

**Topics**
+ [错误 – FATAL：数据库*名称*不存在](#USER_ConnectToPostgreSQLInstance.Troubleshooting-DBname)
+ [错误 – 无法连接到服务器：连接超时](#USER_ConnectToPostgreSQLInstance.Troubleshooting-timeout)
+ [安全组访问规则错误](#USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules)

## 错误 – FATAL：数据库*名称*不存在
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting-DBname"></a>

如果在尝试连接时收到 `FATAL: database name does not exist` 之类的错误，请尝试对 `--dbname` 选项使用默认数据库名称 **postgres**。

## 错误 – 无法连接到服务器：连接超时
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting-timeout"></a>

如果无法连接到数据库实例，则最常见的错误是 `Could not connect to server: Connection timed out.`如果出现此错误，请检查以下内容：
+ 检查所使用的主机名是否是数据库实例端点，以及所使用的端口号是否正确。
+ 确保将数据库实例的公共可访问性设置为**是**，以允许外部连接。要修改**公有访问权限共访问**设置，请参阅 [修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md)。
+ 确保连接到数据库的用户对数据库具有 CONNECT 访问权限。您可以使用以下查询来提供对数据库的连接访问权限。

  ```
  GRANT CONNECT ON DATABASE database name TO username;
  ```
+ 检查分配给数据库实例的安全组是否具有允许您的连接通过相应防火墙进行访问的规则。例如，如果数据库实例是使用默认端口 5432 创建的，您公司的防火墙规则可能不允许外部公司设备连接到该端口。

  要解决此问题，请修改数据库实例以使用不同的端口。另外，确保应用于数据库实例的安全组允许连接到新端口。要修改**数据库端口**设置，请参阅 [修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md)。
+ 检查您尝试使用的端口是否已被本地的 PostgreSQL 实例或计算机上运行的其他服务占用。例如，如果您有一个本地 PostgreSQL 数据库运行在同一个端口（默认为 5432），则这可能会让您无法成功连接到 RDS for PostgreSQL 数据库实例。请确保该端口空闲，或者如果可能的话，尝试使用不同的端口号进行连接。
+ 另请参阅 [安全组访问规则错误](#USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules)。

## 安全组访问规则错误
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules"></a>

到目前为止，最常见的连接问题与分配给数据库实例的安全组的访问规则有关。如果在创建数据库实例时使用的是原定设置安全组，则该安全组可能没有允许您访问该实例的访问规则。

要使连接运行，您在创建数据库实例时分配给它的安全组必须允许访问该数据库实例。例如，如果数据库实例是在 VPC 中创建的，则它必须具有授权连接的 VPC 安全组。检查数据库实例是否是使用安全组创建的，而该安全组没有授权来自运行应用程序的设备或 Amazon EC2 实例的连接。

您可以在安全组中添加或编辑入站规则。对于 **Source (源)**，选择 **My IP (我的 IP)**，这允许从浏览器中检测到的 IP 地址访问数据库实例。有关更多信息，请参阅“[通过创建安全组提供对 VPC 中的数据库实例的访问](CHAP_SettingUp.md#CHAP_SettingUp.SecurityGroup)”。

或者，如果数据库实例是在 VPC 外部创建的，则它必须具有授权这些连接的数据库安全组。

有关 Amazon RDS 安全组的更多信息，请参阅 [使用安全组控制访问权限](Overview.RDSSecurityGroups.md)。

# 使用 SSL/TLS 保护与 RDS for PostgreSQL 的连接
<a name="PostgreSQL.Concepts.General.Security"></a>

RDS for PostgreSQL 支持对 PostgreSQL 数据库实例进行安全套接字层 (SSL) 加密。使用 SSL 可加密应用程序与 PostgreSQL 数据库实例之间的 PostgreSQL 连接。您还可强制至 PostgreSQL 数据库实例的所有连接使用 SSL。RDS for PostgreSQL 还支持传输层安全性 (TLS)，这是 SSL 的下一代协议。

要了解有关 Amazon RDS 和数据保护的更多信息，包括使用 SSL/TLS 加密连接，请参阅 [Amazon RDS 中的数据保护](DataDurability.md)。

**Topics**
+ [将 SSL 与 PostgreSQL 数据库实例结合使用](PostgreSQL.Concepts.General.SSL.md)
+ [更新应用程序以使用新的 SSL/TLS 证书连接到 PostgreSQL 数据库实例](ssl-certificate-rotation-postgresql.md)

# 将 SSL 与 PostgreSQL 数据库实例结合使用
<a name="PostgreSQL.Concepts.General.SSL"></a>

Amazon RDS 支持对 PostgreSQL 数据库实例进行安全套接字层 (SSL) 加密。使用 SSL 可加密应用程序与 PostgreSQL 数据库实例之间的 PostgreSQL 连接。默认情况下，RDS for PostgreSQL 使用并期望所有客户端使用 SSL/TLS 进行连接，但您也可以要求它这样做。RDS for PostgreSQL 支持传输层安全性协议（TLS）版本 1.1、1.2 和 1.3。

有关 SSL 支持和 PostgreSQL 数据库的一般信息，请参阅 PostgreSQL 文档中的 [SSL 支持](https://www.postgresql.org/docs/11/libpq-ssl.html)。有关通过 JDBC 使用 SSL 连接的信息，请参阅 PostgreSQL 文档中的[配置客户端](https://jdbc.postgresql.org/documentation/head/ssl-client.html)。

所有AWS区域均支持对 PostgreSQL 使用 SSL。在创建数据库实例时，Amazon RDS 会为 PostgreSQL 数据库实例创建一个 SSL 证书。如果启用 SSL 证书验证，SSL 证书会将数据库实例终端节点作为 SSL 证书的公用名 (CN) 包含在内以防止欺诈攻击。

**Topics**
+ [通过 SSL 连接到 PostgreSQL 数据库实例](#PostgreSQL.Concepts.General.SSL.Connecting)
+ [需要至 PostgreSQL 数据库实例的 SSL 连接](#PostgreSQL.Concepts.General.SSL.Requiring)
+ [确定 SSL 连接状态](#PostgreSQL.Concepts.General.SSL.Status)
+ [RDS for PostgreSQL 中的 SSL 密码套件](#PostgreSQL.Concepts.General.SSL.Ciphers)

## 通过 SSL 连接到 PostgreSQL 数据库实例
<a name="PostgreSQL.Concepts.General.SSL.Connecting"></a>

**通过 SSL 连接到 PostgreSQL 数据库实例**

1. 下载证书。

   有关下载证书的信息，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。

1. 通过 SSL 连接到您的 PostgreSQL 数据库实例。

   使用 SSL 连接时，客户端可以选择是否验证证书链。如果连接参数指定 `sslmode=verify-ca` 或 `sslmode=verify-full`，则客户端要求 RDS CA 证书位于其信任存储中或在连接 URL 中进行引用。此要求是为了验证签署您的数据库证书的证书链。

   当客户端（如 psql 或 JDBC）配置有 SSL 支持时，默认情况下，该客户端会首先尝试使用 SSL 连接到数据库。如果该客户端无法使用 SSL 进行连接，它将恢复为不使用 SSL 进行连接。基于 libpq 的客户端（例如 psql）和 JDBC 所使用的默认 `sslmode` 模式不同。基于 libpq 的客户端和 JDBC 客户端默认使用 `prefer`。

   使用 `sslrootcert` 参数引用证书，例如，`sslrootcert=rds-ssl-ca-cert.pem`。

以下是使用 `psql` 连接到 PostgreSQL 数据库实例的示例，该数据库实例使用 SSL 及证书验证。

```
$ psql "host=db-name.555555555555.ap-southeast-1.rds.amazonaws.com 
    port=5432 dbname=testDB user=testuser sslrootcert=rds-ca-rsa2048-g1.pem sslmode=verify-full"
```

## 需要至 PostgreSQL 数据库实例的 SSL 连接
<a name="PostgreSQL.Concepts.General.SSL.Requiring"></a>

您可以使用 `rds.force_ssl` 参数要求至 PostgreSQL 数据库实例的连接使用 SSL。对于 RDS for PostgreSQL 版本 15 及更高版本，`rds.force_ssl` 参数默认值为 1（开启）。对于所有其它 RDS for PostgreSQL 主要版本 14 及更早版本，此参数的默认值均为 0（关闭）。您可将 `rds.force_ssl` 参数设置为 1 (on) 以要求使用 SSL/TLS 连接到数据库集群。您可将 `rds.force_ssl` 参数设置为 1 (on) 以要求至数据库实例的 SSL 连接。

要更改此参数的值，您需要创建自定义数据库参数组。然后将自定义数据库参数组中的 `rds.force_ssl` 的值更改为 `1`，以启用此功能。如果您在创建 RDS for PostgreSQL 数据库实例之前准备了自定义数据库参数组，则可以在创建过程中选择它（而不是默认参数组）。如果您在 RDS for PostgreSQL 数据库实例已运行之后执行此操作，则需要重启该实例，以便您的实例使用自定义参数组。有关更多信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

当 `rds.force_ssl` 功能在数据库实例上处于活动状态时，不使用 SSL 的连接尝试将被拒绝，并显示以下消息：

```
$ psql -h db-name.555555555555.ap-southeast-1.rds.amazonaws.com port=5432 dbname=testDB user=testuser
psql: error: FATAL: no pg_hba.conf entry for host "w.x.y.z", user "testuser", database "testDB", SSL off
```

## 确定 SSL 连接状态
<a name="PostgreSQL.Concepts.General.SSL.Status"></a>

当您连接到数据库实例后，登录横幅中将显示连接的加密状态：

```
Password for user master: 
psql (10.3) 
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256) 
Type "help" for help.
postgres=>
```

也可加载 `sslinfo` 扩展，然后调用 `ssl_is_used()` 函数以判断是否在使用 SSL。如果连接使用的是 SSL，则此函数将返回 `t`；否则返回 `f`。

```
postgres=> CREATE EXTENSION sslinfo;
CREATE EXTENSION
postgres=> SELECT ssl_is_used();
ssl_is_used
---------
t
(1 row)
```

要获取更多详细信息，您可以使用以下查询从 `pg_settings` 中获取信息：

```
SELECT name as "Parameter name", setting as value, short_desc FROM pg_settings WHERE name LIKE '%ssl%';
             Parameter name             |                  value                  |                      short_desc
----------------------------------------+-----------------------------------------+-------------------------------------------------------
 ssl                                    | on                                      | Enables SSL connections.
 ssl_ca_file                            | /rdsdbdata/rds-metadata/ca-cert.pem     | Location of the SSL certificate authority file.
 ssl_cert_file                          | /rdsdbdata/rds-metadata/server-cert.pem | Location of the SSL server certificate file.
 ssl_ciphers                            | HIGH:!aNULL:!3DES                       | Sets the list of allowed SSL ciphers.
 ssl_crl_file                           |                                         | Location of the SSL certificate revocation list file.
 ssl_dh_params_file                     |                                         | Location of the SSL DH parameters file.
 ssl_ecdh_curve                         | prime256v1                              | Sets the curve to use for ECDH.
 ssl_key_file                           | /rdsdbdata/rds-metadata/server-key.pem  | Location of the SSL server private key file.
 ssl_library                            | OpenSSL                                 | Name of the SSL library.
 ssl_max_protocol_version               |                                         | Sets the maximum SSL/TLS protocol version to use.
 ssl_min_protocol_version               | TLSv1.2                                 | Sets the minimum SSL/TLS protocol version to use.
 ssl_passphrase_command                 |                                         | Command to obtain passphrases for SSL.
 ssl_passphrase_command_supports_reload | off                                     | Also use ssl_passphrase_command during server reload.
 ssl_prefer_server_ciphers              | on                                      | Give priority to server ciphersuite order.
(14 rows)
```

您还可以使用以下查询，按流程、客户端和应用程序收集有关 RDS for PostgreSQL 数据库实例 SSL 使用情况的所有信息：

```
SELECT datname as "Database name", usename as "User name", ssl, client_addr, application_name, backend_type
   FROM pg_stat_ssl
   JOIN pg_stat_activity
   ON pg_stat_ssl.pid = pg_stat_activity.pid
   ORDER BY ssl;
 Database name | User name | ssl |  client_addr   |    application_name    |         backend_type
---------------+-----------+-----+----------------+------------------------+------------------------------
               |           | f   |                |                        | autovacuum launcher
               | rdsadmin  | f   |                |                        | logical replication launcher
               |           | f   |                |                        | background writer
               |           | f   |                |                        | checkpointer
               |           | f   |                |                        | walwriter
 rdsadmin      | rdsadmin  | t   | 127.0.0.1      |                        | client backend
 rdsadmin      | rdsadmin  | t   | 127.0.0.1      | PostgreSQL JDBC Driver | client backend
 postgres      | postgres  | t   | 204.246.162.36 | psql                   | client backend
(8 rows)
```

要识别用于 SSL 连接的密码，可按如下方式进行查询：

```
postgres=> SELECT ssl_cipher();
ssl_cipher
--------------------
DHE-RSA-AES256-SHA
(1 row)
```

要了解有关 `sslmode` 选项的更多信息，请参阅 *PostgreSQL 文档*中的[数据库连接控制函数](https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-CONNECT-SSLMODE)。

## RDS for PostgreSQL 中的 SSL 密码套件
<a name="PostgreSQL.Concepts.General.SSL.Ciphers"></a>

PostgreSQL 配置参数 [ssl\$1ciphers](https://www.postgresql.org/docs/current/runtime-config-connection.html#RUNTIME-CONFIG-CONNECTION-SSL) 指定在使用 TLS 1.2 及更低版本时，与数据库的 SSL 连接所支持的密码套件类别。

 在 RDS for PostgreSQL 16 及更高版本中，您可以修改 `ssl_ciphers` 参数，以使用列入许可列表的密码套件中的特定值。这是一个不要求重启数据库实例的动态参数。要查看列入许可列表的密码套件，请使用 Amazon RDS 控制台或以下 CLI AWS 命令：

```
aws rds describe-db-parameters --db-parameter-group-name <your-parameter-group> --region <region> --endpoint-url <endpoint-url> --output json | jq '.Parameters[] | select(.ParameterName == "ssl_ciphers")'
```

下表列出了支持自定义配置的版本的默认密码套件和许可的密码套件。


| PostgreSQL 引擎版本 | 默认 ssl\$1cipher 套件值 | 列入许可列表的自定义 ssl\$1cipher 套件值 | 
| --- | --- | --- | 
| 18 | HIGH:\$1aNULL:\$13DES |  `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384` `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256` `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384` `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`  | 
| 17 | HIGH:\$1aNULL:\$13DES |  `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384` `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256` `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384` `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`  | 
| 16 | HIGH:\$1aNULL:\$13DES |  `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384` `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256` `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384` `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`  | 
| 15 | HIGH:\$1aNULL:\$13DES | 不支持自定义 ssl\$1cipher | 
| 14 | HIGH:\$1aNULL:\$13DES | 不支持自定义 ssl\$1cipher | 
| 13 | HIGH:\$1aNULL:\$13DES | 不支持自定义 ssl\$1cipher | 
| 12 | HIGH:\$1aNULL:\$13DES | 不支持自定义 ssl\$1cipher | 
| 11.4 及更高的次要版本 | HIGH:MEDIUM:\$13DES:\$1aNULL:\$1RC4 | 不支持自定义 ssl\$1cipher | 
| 11.1、11.2 | HIGH:MEDIUM:\$13DES:\$1aNULL | 不支持自定义 ssl\$1cipher | 
| 10.9 及更高的次要版本 | HIGH:MEDIUM:\$13DES:\$1aNULL:\$1RC4 | 不支持自定义 ssl\$1cipher | 
| 10.7 及更低的次要版本 | HIGH:MEDIUM:\$13DES:\$1aNULL | 不支持自定义 ssl\$1cipher | 

要将所有实例连接配置为使用 `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384` 密码套件，请修改参数组，如以下示例所示：

```
aws rds modify-db-parameter-group --db-parameter-group-name <your-parameter-group> --parameters "ParameterName='ssl_ciphers',ParameterValue='TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384',ApplyMethod=immediate"
```

此示例使用 ECDSA 密码，这要求您的实例使用具有椭圆曲线加密（ECC）的证书颁发机构来建立连接。有关 Amazon RDS 提供的证书颁发机构的信息，请参阅[证书颁发机构](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/singWithRDS.SSL.html#UsingWithRDS.SSL.RegionCertificateAuthorities)。

您可以通过[确定 SSL 连接状态](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.Concepts.General.SSL.html#PostgreSQL.Concepts.General.SSL.Status)中所述的方法来验证所使用的密码。

根据上下文，密码可能有不同的名称：
+ 您可以在参数组中配置的列入许可列表的密码以其 IANA 名称来引用。
+ `sslinfo` 和 `psql` 登录横幅使用密码的 OpenSSL 名称来引用这些密码。

默认情况下，RDS for PostgreSQL 16 及更高版本中 `ssl_max_protocol_version` 的值为 TLS v1.3。您必须将此参数的值设置为 TLS v1.2，因为 TLS v1.3 不使用在 `ssl_ciphers` 参数中指定的密码配置。当您将该值设置为 TLS v1.2 时，连接将仅使用您在 `ssl_ciphers` 中定义的密码。

```
aws rds modify-db-parameter-group --db-parameter-group-name <your-parameter-group> --parameters "ParameterName='ssl_max_protocol_version',ParameterValue='TLSv1.2',ApplyMethod=immediate"
```

为确保数据库连接使用 SSL，请在参数组中将 `rds.force_ssl parameter` 设置为 1。有关参数和参数组的更多信息，请参阅 [Amazon RDS 的参数组](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html)。

# 更新应用程序以使用新的 SSL/TLS 证书连接到 PostgreSQL 数据库实例
<a name="ssl-certificate-rotation-postgresql"></a>

用于安全套接字层或传输层安全 (SSL/TLS) 的证书通常具有设定的生命周期。服务提供商更新其证书颁发机构 (CA) 证书时，客户端必须更新其应用程序才能使用新证书。在下文中，您可以了解有关如何确定客户端应用程序是否使用 SSL/TLS 连接到 Amazon RDS for PostgreSQL 数据库实例的信息。您还可以找到有关如何检查这些应用程序在连接时是否验证服务器证书的信息。

**注意**  
配置为在 SSL/TLS 连接之前验证服务器证书的客户端应用程序必须在客户端的信任存储中具有有效的 CA 证书。必要时更新客户端信任存储以获取新证书。

更新客户端应用程序信任存储中的 CA 证书后，可以在数据库实例上轮换这些证书。强烈建议在生产环境中实现这些过程之前，先在非生产环境中测试它们。

有关证书轮换的更多信息，请参阅[轮换 SSL/TLS 证书](UsingWithRDS.SSL-certificate-rotation.md)。有关下载证书的更多信息，请参阅[使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。有关对 PostgreSQL 数据库实例使用 SSL/TLS 的信息，请参阅[将 SSL 与 PostgreSQL 数据库实例结合使用](PostgreSQL.Concepts.General.SSL.md)。

**Topics**
+ [确定是否有应用程序使用 SSL 连接到 PostgreSQL 数据库实例](#ssl-certificate-rotation-postgresql.determining-server)
+ [确定客户端是否需要证书验证才能连接](#ssl-certificate-rotation-postgresql.determining-client)
+ [更新应用程序信任存储](#ssl-certificate-rotation-postgresql.updating-trust-store)
+ [对不同类型的应用程序使用 SSL/TLS 连接](#ssl-certificate-rotation-postgresql.applications)

## 确定是否有应用程序使用 SSL 连接到 PostgreSQL 数据库实例
<a name="ssl-certificate-rotation-postgresql.determining-server"></a>

检查数据库实例配置中 `rds.force_ssl` 参数的值。默认情况下，对于使用 PostgreSQL 版本 15 之前版本的数据库实例，`rds.force_ssl` 参数设置为 `0`（关闭）。默认情况下，对于使用 PostgreSQL 版本 15 及更高主要版本的数据库实例，`rds.force_ssl` 设置为 `1`（打开）。如果 `rds.force_ssl` 参数设置为 `1`（开），则客户端需要使用 SSL/TLS 进行连接。有关参数组的更多信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

如果您使用的是 RDS PostgreSQL 版本 9.5 或更高的主要版本，并且 `rds.force_ssl` 未设置为 `1`（开），请查询 `pg_stat_ssl` 视图来检查使用 SSL 的连接。例如，以下查询仅返回 SSL 连接和有关使用 SSL 的客户端的信息。

```
SELECT datname, usename, ssl, client_addr 
  FROM pg_stat_ssl INNER JOIN pg_stat_activity ON pg_stat_ssl.pid = pg_stat_activity.pid
  WHERE ssl is true and usename<>'rdsadmin';
```

只有使用 SSL/TLS 连接的行才显示有关连接的信息。下面是示例输出。

```
 datname  | usename | ssl | client_addr 
----------+---------+-----+-------------
 benchdb  | pgadmin | t   | 53.95.6.13
 postgres | pgadmin | t   | 53.95.6.13
(2 rows)
```

此查询仅显示进行查询时有效的连接。没有结果并不表示没有应用程序在使用 SSL 连接。其他 SSL 连接可能在不同的时间建立。

## 确定客户端是否需要证书验证才能连接
<a name="ssl-certificate-rotation-postgresql.determining-client"></a>

当客户端（如 psql 或 JDBC）配置有 SSL 支持时，默认情况下，该客户端会首先尝试使用 SSL 连接到数据库。如果该客户端无法使用 SSL 进行连接，它将恢复为不使用 SSL 进行连接。用于基于 libpq 的客户端（例如 psql）和 JDBC 的默认 `sslmode` 模式设置为 `prefer`。仅当提供 `sslrootcert` 且 `sslmode` 设置为 `verify-ca` 或 `verify-full` 时，才会验证服务器上的证书。如果证书无效，则会引发错误。

使用 `PGSSLROOTCERT` 验证具有 `PGSSLMODE` 环境变量的证书，且 `PGSSLMODE` 设置为 `verify-ca` 或 `verify-full`。

```
PGSSLMODE=verify-full PGSSLROOTCERT=/fullpath/ssl-cert.pem psql -h pgdbidentifier.cxxxxxxxx.us-east-2.rds.amazonaws.com -U masteruser -d postgres
```

使用 `sslrootcert` 参数验证 `sslmode` 为连接字符串格式的证书，将 `sslmode` 设置为 `verify-ca` 或 `verify-full` 来验证证书。

```
psql "host=pgdbidentifier.cxxxxxxxx.us-east-2.rds.amazonaws.com sslmode=verify-full sslrootcert=/full/path/ssl-cert.pem user=masteruser dbname=postgres"
```

例如，在上述情况下，如果您使用无效的根证书，则会在客户端上看到类似于以下内容的错误。

```
psql: SSL error: certificate verify failed
```

## 更新应用程序信任存储
<a name="ssl-certificate-rotation-postgresql.updating-trust-store"></a>

有关更新 PostgreSQL 应用程序的信任存储的信息，请参阅 PostgreSQL 文档中的[使用 SSL 保护 TCP/IP 连接](https://www.postgresql.org/docs/current/ssl-tcp.html)。

有关下载根证书的信息，请参阅 [使用 SSL/TLS 加密与数据库实例或集群的连接](UsingWithRDS.SSL.md)。

有关导入证书的示例脚本，请参阅 [将证书导入信任存储的示例脚本](UsingWithRDS.SSL-certificate-rotation.md#UsingWithRDS.SSL-certificate-rotation-sample-script)。

**注意**  
更新信任存储时，除了添加新证书外，还可以保留较旧证书。

## 对不同类型的应用程序使用 SSL/TLS 连接
<a name="ssl-certificate-rotation-postgresql.applications"></a>

下面提供了有关对不同类型应用程序使用 SSL/TLS 连接的信息：
+ **psql**

  通过将选项指定为连接字符串或环境变量，可以从命令行调用客户端。对于 SSL/TLS 连接，相关选项为 `sslmode`（环境变量 `PGSSLMODE`）和 `sslrootcert`（环境变量 `PGSSLROOTCERT`）。

  有关完整的选项列表，请参阅 PostgreSQL 文档中的[参数关键字](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS)。有关完整的环境变量列表，请参阅 PostgreSQL 文档中的[环境变量](https://www.postgresql.org/docs/current/libpq-envars.html)。
+ **pgAdmin**

  这个基于浏览器的客户端是一个更加用户友好的界面，用于连接到 PostgreSQL 数据库。

  有关配置连接的信息，请参阅 [pgAdmin 文档](https://www.pgadmin.org/docs/pgadmin4/latest/server_dialog.html)。
+ **JDBC**

  JDBC 支持与 Java 应用程序的数据库连接。

  有关使用 JDBC 连接到 PostgreSQL 数据库的一般信息，请参阅 PostgreSQL JDBC 驱动程序文档中的[连接到数据库](https://jdbc.postgresql.org/documentation/use/#connecting-to-the-database)。有关使用 SSL/TLS 进行连接的信息，请参阅 PostgreSQL JDBC 驱动程序文档中的[配置客户端](https://jdbc.postgresql.org/documentation/ssl/#configuring-the-client)。
+ **Python**

  一个常用的连接到 PostgreSQL 数据库的 Python 库是 `psycopg2`。

  有关如何使用 `psycopg2` 的信息，请参阅 [psycopg2 文档](https://pypi.org/project/psycopg2/)。有关如何连接到 PostgreSQL 数据库的简短教程，请参阅 [Psycopg2 教程](https://wiki.postgresql.org/wiki/Psycopg2_Tutorial)。您可以在 [psycopg2 模块内容](http://initd.org/psycopg/docs/module.html#module-psycopg2)中找到有关连接命令接受的选项的信息。

**重要**  
在确定了数据库连接使用 SSL/TLS 并更新了应用程序信任存储之后，可以更新数据库以使用 rds-ca-rsa2048-g1 证书。有关说明，请参阅[通过修改数据库实例或集群来更新 CA 证书](UsingWithRDS.SSL-certificate-rotation.md#UsingWithRDS.SSL-certificate-rotation-updating)中的步骤 3。

# 在 Amazon RDS for PostgreSQL 中使用 Kerberos 身份验证
<a name="postgresql-kerberos"></a>

在用户连接到运行 PostgreSQL 的数据库实例时，您可以使用 Kerberos 对用户进行身份验证。为此，请将数据库实例配置为使用 AWS Directory Service for Microsoft Active Directory 进行 Kerberos 身份验证。AWS Directory Service for Microsoft Active Directory 也称为 AWS Managed Microsoft AD。这是 Directory Service 提供的一项功能。要了解更多信息，请参阅《AWS Directory Service 管理指南》**中的[什么是 Directory Service？](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/what_is.html)

要开始操作，请创建一个 AWS Managed Microsoft AD 目录来存储用户凭证。然后，将 Active Directory 的域和其他信息提供给 PostgreSQL 数据库实例。当用户使用 PostgreSQL 数据库实例进行身份验证时，身份验证请求将转发到 AWS Managed Microsoft AD 目录。

将所有凭证保存在同一目录中可以节省您的时间和精力。您具有一个集中位置用于存储和管理多个数据库实例的凭证。使用目录还可以改善您的整体安全概要。

此外，还可以从自己的本地 Microsoft Active Directory 访问凭证。为此，请创建一个信任域关系，以便 AWS Managed Microsoft AD 目录信任您的本地 Microsoft Active Directory。通过这种方式，您的用户可以使用 Windows 单点登录 (SSO) 访问 PostgreSQL 实例，获得与访问本地网络中的工作负载相同的体验。

数据库可以使用密码身份验证，也可以使用带有 Kerberos 或 AWS Identity and Access Management（IAM）身份验证的密码身份验证。有关 IAM 身份验证的更多信息，请参阅 [适用于 MariaDB、MySQL 和 PostgreSQL 的IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.md)。

**注意**  
RDS for PostgreSQL 不支持对 Active Directory 组进行 Kerberos 身份验证。

**Topics**
+ [区域和版本可用性](#postgresql-kerberos.RegionVersionAvailability)
+ [PostgreSQL 数据库实例的 Kerberos 身份验证概述](#postgresql-kerberos-overview)
+ [为 PostgreSQL 数据库实例设置 Kerberos 身份验证](postgresql-kerberos-setting-up.md)
+ [在 Active Directory 域中管理 RDS for PostgreSQL 数据库实例](postgresql-kerberos-managing.md)
+ [使用 Kerberos 身份验证连接到 PostgreSQL](postgresql-kerberos-connecting.md)

## 区域和版本可用性
<a name="postgresql-kerberos.RegionVersionAvailability"></a>

功能可用性和支持因每个数据库引擎的特定版本以及 AWS 区域而异。有关使用 Kerberos 身份验证的 RDS for PostgreSQL 的版本和区域可用性的更多信息，请参阅[支持 Amazon RDS 中 Kerberos 身份验证功能的区域和数据库引擎](Concepts.RDS_Fea_Regions_DB-eng.Feature.KerberosAuthentication.md)。

## PostgreSQL 数据库实例的 Kerberos 身份验证概述
<a name="postgresql-kerberos-overview"></a>

要为 PostgreSQL 数据库实例设置 Kerberos 身份验证，请执行以下步骤，稍后将详细介绍这些步骤：

1. 使用 AWS Managed Microsoft AD 创建 AWS Managed Microsoft AD 目录。您可以使用 AWS 管理控制台、AWS CLI 或 Directory Service API 创建目录。确保打开目录安全组上的相关出站端口，以便目录可以与实例进行通信。

1. 创建一个角色，以提供对您的 AWS Managed Microsoft AD 目录进行调用的 Amazon RDS 访问权限。为此，请创建使用托管 IAM 策略 `AmazonRDSDirectoryServiceAccess` 的 AWS Identity and Access Management (IAM) 角色。

   要使 IAM 角色允许访问，必须在您的 AWS 账户的正确 AWS 区域中激活 AWS Security Token Service（AWS STS）端点。原定设置情况下，AWS STS 端点在所有 AWS 区域中处于活动状态，您可以直接使用这些端点，而无需执行任何其他操作。有关更多信息，请参阅 *IAM 用户指南*中的[在 AWS STS 区域中激活和停用 AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html#sts-regions-activate-deactivate)。

1. 使用 Microsoft Active Directory 工具在 AWS Managed Microsoft AD 目录中创建和配置用户。有关在 Active Directory 中创建用户的更多信息，请参阅 *AWS 管理指南*中的[在 Directory Service 托管 Microsoft AD 中管理用户和组](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/ms_ad_manage_users_groups.html)。

1. 如果您计划在不同的 AWS 账户或 Virtual Private Cloud (VPC) 中查找目录和数据库实例，请配置 VPC 对等连接。有关更多信息，请参阅 *Amazon VPC Peering Guide* 中的[什么是 VPC 对等连接？](https://docs.aws.amazon.com/vpc/latest/peering/Welcome.html)。

1. 使用以下方法之一，从控制台、CLI 或 RDS API 中创建或修改 PostgreSQL 数据库实例：
   + [创建 Amazon RDS 数据库实例](USER_CreateDBInstance.md) 
   + [修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md) 
   + [还原到数据库实例](USER_RestoreFromSnapshot.md)
   + [将 Amazon RDS 的数据库实例还原到指定时间](USER_PIT.md)

   您可以在与目录相同的 Amazon Virtual Private Cloud (VPC) 中或在不同的 AWS 账户或 VPC 中定位实例。创建或修改 PostgreSQL 数据库实例时，请执行以下操作：
   + 请提供创建目录时生成的域标识符（`d-*` 标识符）。
   + 还要提供您创建的 IAM 角色的名称。
   + 确保数据库实例安全组可以从目录安全组接收入站流量。

1. 使用 RDS 主用户凭证连接到 PostgreSQL 数据库实例。在 PostgreSQL 中创建用户以在外部进行标识。外部标识的用户可以使用 Kerberos 身份验证登录到 PostgreSQL 数据库实例。

# 为 PostgreSQL 数据库实例设置 Kerberos 身份验证
<a name="postgresql-kerberos-setting-up"></a>

您可以使用 AWS Directory Service for Microsoft Active Directory (AWS Managed Microsoft AD) 为 PostgreSQL 数据库实例设置 Kerberos 身份验证。要设置 Kerberos 身份验证，请执行以下步骤。

**Topics**
+ [步骤 1：使用 AWS Managed Microsoft AD 创建目录](#postgresql-kerberos-setting-up.create-directory)
+ [步骤 2：（可选）在本地 Active Directory 和 Directory Service 之间创建信任关系](#postgresql-kerberos-setting-up.create-trust)
+ [步骤 3：为 Amazon RDS 创建 IAM 角色以访问 Directory Service](#postgresql-kerberos-setting-up.CreateIAMRole)
+ [步骤 4：创建和配置用户](#postgresql-kerberos-setting-up.create-users)
+ [步骤 5：在目录和数据库实例之间启用跨 VPC 流量](#postgresql-kerberos-setting-up.vpc-peering)
+ [步骤 6：创建或修改 PostgreSQL 数据库实例](#postgresql-kerberos-setting-up.create-modify)
+ [步骤 7：为您的 Kerberos 主体创建 PostgreSQL 用户](#postgresql-kerberos-setting-up.create-logins)
+ [步骤 8：配置 PostgreSQL 客户端](#postgresql-kerberos-setting-up.configure-client)

## 步骤 1：使用 AWS Managed Microsoft AD 创建目录
<a name="postgresql-kerberos-setting-up.create-directory"></a>

Directory Service 将在 AWS 云中创建一个完全托管的 Active Directory。在创建 AWS Managed Microsoft AD 目录时，Directory Service 将创建两个域控制器和 DNS 服务器。目录服务器在 VPC 中的不同子网中创建。这种冗余有助于确保始终可以访问目录，即使发生了故障。

 创建 AWS Managed Microsoft AD 目录时，AWS Directory Service 将代表您执行下列任务：
+ 在您的 VPC 中设置 Active Directory。
+ 创建具有用户名 `Admin` 和指定密码的目录管理员账户。您可以使用此账户管理您的目录。
**重要**  
请务必保存此密码。Directory Service 不会存储此密码并且它无法取回或重置。
+ 为目录控制器创建安全组。安全组必须允许与 PostgreSQL 数据库实例进行通信。

在启动 AWS Directory Service for Microsoft Active Directory 时，AWS 创建一个组织单位 (OU)，其中包含目录的所有对象。此 OU（具有您在创建目录时输入的 NetBIOS 名称）位于域根目录中。此域根目录由 AWS 拥有和管理。

 使用 `Admin` 目录创建的 AWS Managed Microsoft AD 账户有权为您的 OU 执行最常见的管理活动：
+ 创建、更新或删除用户
+ 将资源添加到域（如文件或打印服务器），然后为 OU 中的用户分配这些资源的权限 
+ 创建额外的 OU 和容器 
+ 委托授权 
+ 从 Active Directory 回收站还原删除的对象 
+ 在 Active Directory Web 服务上为 Windows PowerShell 运行 Active Directory 和域名服务 (DNS) 模块 

`Admin` 账户还有权执行以下域范围的活动：
+ 管理 DNS 配置（添加、删除或更新记录、区域和转发器） 
+ 查看 DNS 事件日志 
+ 查看安全事件日志 

**使用 AWS Managed Microsoft AD 创建目录**

1.  在 [Directory Service 控制台](https://console.aws.amazon.com/directoryservicev2/)导航窗格中，选择 **Directories (目录)**，然后选择 **Set up directory (设置目录)**。

1. 选择 **AWS Managed Microsoft AD**。AWS Managed Microsoft AD 是当前唯一支持用于 Amazon RDS 的选项。

1. 选择 **Next (下一步)**。

1. 在**输入目录信息**页面上，提供以下信息：  
**版本**  
 选择符合您要求的版本。  
**目录 DNS 名称**  
 目录的完全限定名称，例如 **corp.example.com**。  
**目录 NetBIOS 名称**  
 可选的目录短名称，如 `CORP`。  
**目录描述**  
 目录的可选描述。  
**管理员密码**  
 目录管理员的密码。目录创建过程将创建一个具有 `Admin` 用户名和此密码的管理员账户。  
 目录管理员密码不能包含单词“admin”。此密码区分大小写，且长度必须介于 8 – 64 个字符之间。至少，它还必须包含下列四种类别中三种类别的一个字符：  
   +  小写字母 (a–z) 
   +  大写字母 (A–Z) 
   +  数字 (0–9) 
   +  非字母数字字符 (\$1\$1@\$1\$1%^&\$1\$1-\$1=`\$1\$1()\$1\$1[]:;"'<>,.?/)   
**确认密码**  
 重新键入管理员密码。  
确保您保存该密码。Directory Service 不会存储该密码，也无法检索或重置该密码。

1. 选择 **Next (下一步)**。

1. 在**选择 VPC 和子网**页面上，提供以下信息：  
**VPC**  
为目录选择 VPC。您可以在该相同 VPC 或不同的 VPC 中创建 PostgreSQL 数据库实例。  
**子网**  
 为目录服务器选择子网。两个子网必须位于不同的可用区。

1. 选择 **Next (下一步)**。

1.  检查目录信息。如果需要进行更改，请选择 **Previous (上一步)** 并作出更改。如果信息正确，请选择 **Create directory (创建目录)**。  
![\[“目录详细信息”页面\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/WinAuth2.png)

 目录创建需要几分钟时间。创建成功后，**Status (状态)** 值将更改为 **Active (活动)**。

 要查看有关您的目录的信息，请在目录列表中选择目录。记下**目录 ID** 值。在创建或修改 PostgreSQL 数据库实例时，您需要使用该值。

![\[详细信息页面的图像\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/WinAuth3.png)


## 步骤 2：（可选）在本地 Active Directory 和 Directory Service 之间创建信任关系
<a name="postgresql-kerberos-setting-up.create-trust"></a>

如果您不打算使用自己的本地 Microsoft Active Directory，请跳转至 [步骤 3：为 Amazon RDS 创建 IAM 角色以访问 Directory Service](#postgresql-kerberos-setting-up.CreateIAMRole)。

要使用本地 Active Directory 获取 Kerberos 身份验证，您需要使用林信任在本地 Microsoft Active Directory 和 AWS Managed Microsoft AD 目录（在 [步骤 1：使用 AWS Managed Microsoft AD 创建目录](#postgresql-kerberos-setting-up.create-directory) 中创建）之间创建信任域关系。信任可以是单向的，此时 AWS Managed Microsoft AD 目录信任本地 Microsoft Active Directory。信任也可以是双向的，此时两个 Active Directory 相互信任。有关使用 Directory Service 设置信任的更多信息，请参阅 *AWS Directory Service 管理指南*中的[何时创建信任关系](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/ms_ad_setup_trust.html)。

**注意**  
如果您使用本地 Microsoft Active Directory，则 Windows 客户端使用端点中 Directory Service 的域名而不是 rds.amazonaws.com 进行连接。要了解更多信息，请参阅[使用 Kerberos 身份验证连接到 PostgreSQL](postgresql-kerberos-connecting.md)。

请确保您的本地 Microsoft Active Directory 域名包含与新创建的信任关系对应的 DNS 后缀路由。以下屏幕截图显示一个示例。

![\[DNS 路由对应于创建的信任\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/kerberos-auth-trust.png)


## 步骤 3：为 Amazon RDS 创建 IAM 角色以访问 Directory Service
<a name="postgresql-kerberos-setting-up.CreateIAMRole"></a>

要使 Amazon RDS 为您调用 Directory Service，您的 AWS 账户需要一个使用托管式 IAM 策略 `AmazonRDSDirectoryServiceAccess` 的 IAM 角色。该角色允许 Amazon RDS 对 Directory Service 进行调用。

当您使用 AWS 管理控制台 创建数据库实例并且控制台用户账户具有 `iam:CreateRole` 权限时，控制台将自动创建所需的 IAM 角色。在这种情况下，角色名为 `rds-directoryservice-kerberos-access-role`。否则，您必须手动创建 IAM 角色。在创建该 IAM 角色时，请选择 `Directory Service`，然后将 AWS 托管策略 `AmazonRDSDirectoryServiceAccess` 附加到该角色。

有关为服务创建 IAM 角色的更多信息，请参阅 *IAM 用户指南*中的[创建向AWS服务委托权限的角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html)。

**注意**  
用于 RDS for Microsoft SQL Server 的 Windows 身份验证的 IAM 角色不能用于 Amazon RDS for PostgreSQL。

作为使用 `AmazonRDSDirectoryServiceAccess` 托管式策略的替代方法，您可以创建具有所需权限的策略。在这种情况下，IAM 角色必须具有以下 IAM 信任策略。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "directoryservice.rds.amazonaws.com",
          "rds.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

角色还必须具有以下 IAM 角色策略。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Action": [
        "ds:DescribeDirectories",
        "ds:AuthorizeApplication",
        "ds:UnauthorizeApplication",
        "ds:GetAuthorizedApplicationDetails"
      ],
    "Effect": "Allow",
    "Resource": "*"
    }
  ]
}
```

------

对于选择加入的 AWS 区域，请在 IAM 角色信任策略中使用区域特定的服务主体。在为这些区域中的服务创建信任策略时，请在服务主体中指定区域代码。

以下示例显示了包括区域特定的服务主体的信任策略：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "directoryservice.rds.REGION-CODE.amazonaws.com",
          "rds.REGION-CODE.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

将 REGION-CODE 替换为特定区域的代码。例如，对亚太地区（墨尔本）区域使用以下服务主体：

```
"Service": [
  "directoryservice.rds.ap-southeast-4.amazonaws.com",
  "rds.ap-southeast-4.amazonaws.com"
]
```

## 步骤 4：创建和配置用户
<a name="postgresql-kerberos-setting-up.create-users"></a>

 您可以使用“Active Directory 用户和计算机”工具创建用户。该工具是 Active Directory Domain Services 和 Active Directory Lightweight Directory Services 工具之一。有关更多信息，请参阅 Microsoft 文档中的[将用户和计算机添加到 Active Directory 域](https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/create-an-active-directory-server#add-users-and-computers-to-the-active-directory-domain)。在这种情况下，用户是个人或其他实体，例如属于域的计算机，其身份在目录中维护。

要在 Directory Service 目录中创建用户，您必须连接到属于 Directory Service 目录成员的基于 Windows 的 Amazon EC2 实例。同时，您必须以具有创建用户权限的用户身份登录。有关更多信息，请参阅 *AWS Directory Service 管理指南*中的[创建用户](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/ms_ad_manage_users_groups_create_user.html)。

## 步骤 5：在目录和数据库实例之间启用跨 VPC 流量
<a name="postgresql-kerberos-setting-up.vpc-peering"></a>

如果您打算将目录和数据库实例放在同一 VPC 中，请跳过该步骤，然后转到[步骤 6：创建或修改 PostgreSQL 数据库实例](#postgresql-kerberos-setting-up.create-modify)。

如果您计划在不同 VPC 中查找目录和数据库实例，请使用 VPC 对等连接或 [AWS Transit Gateway](https://docs.aws.amazon.com/vpc/latest/tgw/what-is-transit-gateway.html) 配置跨 VPC 流量。

以下过程使用 VPC 对等连接启用 VPC 之间的流量。请按照 *Amazon Virtual Private Cloud 对等连接指南*中的[什么是 VPC 对等连接？](https://docs.aws.amazon.com/vpc/latest/peering/Welcome.html)操作。

**使用 VPC 对等连接启用跨 VPC 流量**

1. 设置适合的 VPC 路由规则，以便确保网络流量可以双向流动。

1. 确保数据库实例安全组可以从目录安全组接收入站流量。

1. 确保没有任何网络访问控制列表 (ACL) 规则会阻止流量。

如果该目录由不同的 AWS 账户拥有，则您必须共享该目录。

**在 AWS 账户之间共享目录**

1. 按照 *AWS 管理指南*中的[教程：共享 AWS 托管 Microsoft AD 目录以实现无缝 EC2 域加入](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/ms_ad_tutorial_directory_sharing.html)中的说明，开始与将要在其中创建数据库实例的 Directory Service 账户共享目录。

1. 使用数据库实例的账户登录到 Directory Service 控制台，并确保在处理之前域具有 `SHARED` 状态。

1. 使用数据库实例的账户登录 Directory Service 控制台时，请记录**目录 ID** 值。您可以使用此目录 ID 将数据库实例加入域。

## 步骤 6：创建或修改 PostgreSQL 数据库实例
<a name="postgresql-kerberos-setting-up.create-modify"></a>

创建或修改 PostgreSQL 数据库实例以用于您的目录。您可以使用控制台、CLI 或 RDS API 将数据库实例与目录关联。您可以通过下列方式之一来执行该操作：
+  使用控制台、[create-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-instance.html) CLI 命令或 [CreateDBInstance](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html) RDS API 操作创建新的 PostgreSQL 数据库实例。有关说明，请参阅 [创建 Amazon RDS 数据库实例](USER_CreateDBInstance.md)。
+  使用控制台、[modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) CLI 命令或 [ModifyDBInstance](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBInstance.html) RDS API 操作修改现有的 PostgreSQL 数据库实例。有关说明，请参阅 [修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md)。
+  使用控制台、[restore-db-instance-from-db-snapshot](https://docs.aws.amazon.com/cli/latest/reference/rds/restore-db-instance-from-db-snapshot.html) CLI 命令或 [RestoreDBInstanceFromDBSnapshot](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_RestoreDBInstanceFromDBSnapshot.html) RDS API 操作，从数据库快照还原 PostgreSQL 数据库实例。有关说明，请参阅 [还原到数据库实例](USER_RestoreFromSnapshot.md)。
+  使用控制台、[restore-db-instance-to-point-in-time](https://docs.aws.amazon.com/cli/latest/reference/rds/restore-db-instance-to-point-in-time.html) CLI 命令或 [RestoreDBInstanceToPointInTime](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_RestoreDBInstanceToPointInTime.html) RDS API 操作，将 PostgreSQL 数据库实例还原到某个时间点。有关说明，请参阅 [将 Amazon RDS 的数据库实例还原到指定时间](USER_PIT.md)。

仅 VPC 中的 PostgreSQL 数据库实例支持 Kerberos 身份验证。数据库实例可以与目录在同一 VPC 中或在不同 VPC 中。数据库实例必须使用允许在目录的 VPC 中传入和传出的安全组，以便数据库实例与目录通信。

### 控制台
<a name="postgresql-kerberos-setting-up.create-modify.Console"></a>

在使用控制台创建、修改或还原数据库实例时，请选择**数据库身份验证**部分中的**密码和 Kerberos 身份验证**。然后选择**浏览目录**。选择目录或选择**创建一个新目录**以使用 Directory Service。

![\[选择 Kerberos 进行身份验证并确定要使用的目录。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/rpg-authentication-use-kerberos.png)


### AWS CLI
<a name="postgresql-kerberos-setting-up.create-modify.CLI"></a>

使用 AWS CLI 时，数据库实例需要以下参数才能使用您创建的目录：
+ 对于 `--domain` 参数，请使用创建目录时生成的域标识符（“d-\$1”标识符）。
+ 对于 `--domain-iam-role-name` 参数，请使用您使用托管 IAM 策略 `AmazonRDSDirectoryServiceAccess` 创建的角色。

例如，以下 CLI 命令会修改数据库实例以使用目录。

```
aws rds modify-db-instance --db-instance-identifier mydbinstance --domain d-Directory-ID --domain-iam-role-name role-name 
```

**重要**  
如果修改数据库实例以启用 Kerberos 身份验证，请在做出更改之后重新启动数据库实例。

## 步骤 7：为您的 Kerberos 主体创建 PostgreSQL 用户
<a name="postgresql-kerberos-setting-up.create-logins"></a>

此时，您的 RDS for PostgreSQL 数据库实例已加入 AWS Managed Microsoft AD 域。您需要将您在[步骤 4：创建和配置用户](#postgresql-kerberos-setting-up.create-users)的目录中创建的用户设置为 PostgreSQL 数据库用户，并授予登录数据库的权限。为此，请以具有 `rds_superuser` 权限的数据库用户身份登录。例如，如果在创建 RDS for PostgreSQL 数据库实例时接受了缺省设置值，请使用 `postgres`，如以下步骤所示。

**为 Kerberos 主体创建 PostgreSQL 数据库用户**

1. 使用 `psql` 通过 `psql` 连接到 RDS for PostgreSQL 数据库实例端点。以下示例对于 `rds_superuser` 角色使用原定设置 `postgres` 账户。

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

1. 为要访问数据库的每个 Kerberos 主体（Active Directory 用户名）创建一个数据库用户名。使用 Active Directory 实例中定义的规范用户名（身份），即该用户名的小写 `alias`（Active Directory 中的用户名）和大写 Active Directory 域名。Active Directory 用户名是经过外部身份验证的用户，因此请在名称前后使用引号，如下所示。

   ```
   postgres=> CREATE USER "username@CORP.EXAMPLE.COM" WITH LOGIN;
   CREATE ROLE
   ```

1. 将 `rds_ad` 角色授予数据库用户。

   ```
   postgres=> GRANT rds_ad TO "username@CORP.EXAMPLE.COM";
   GRANT ROLE
   ```

为 Active Directory 用户身份创建完所有 PostgreSQL 用户后，用户可以使用他们的 Kerberos 凭证访问 RDS for PostgreSQL 数据库实例。

使用 Kerberos 进行身份验证的数据库用户需要从属于 Active Directory 域成员的客户端计算机进行身份验证。

被授予 `rds_ad` 角色的数据库用户不能同时拥有 `rds_iam` 角色。这也适用于嵌套成员资格。有关更多信息，请参阅 [适用于 MariaDB、MySQL 和 PostgreSQL 的IAM 数据库身份验证](UsingWithRDS.IAMDBAuth.md)。

## 步骤 8：配置 PostgreSQL 客户端
<a name="postgresql-kerberos-setting-up.configure-client"></a>

要配置 PostgreSQL 客户端，请采取以下步骤：
+ 创建一个 krb5.conf 文件（或等效的文件）以指向域。
+ 验证流量是否可以在客户端主机和 Directory Service 之间流动。使用网络实用程序（如 Netcat）执行以下操作：
  + 验证端口 53 上通过 DNS 的流量。
  + 验证端口 53 上通过 TCP/UDP 的流量以及 Kerberos 的流量，包括用于 Directory Service 的端口 88 和 464。
+ 验证流量是否可以通过数据库端口在客户端主机和数据库实例之间流动。例如，使用 psql 连接和访问数据库。

以下是 AWS Managed Microsoft AD 的示例 Krb5.conf 内容。

```
[libdefaults]
 default_realm = EXAMPLE.COM
[realms]
 EXAMPLE.COM = {
  kdc = example.com
  admin_server = example.com
 }
[domain_realm]
 .example.com = EXAMPLE.COM
 example.com = EXAMPLE.COM
```

以下是本地 Microsoft Active Directory 的示例 krb5.conf 内容。

```
[libdefaults]
 default_realm = EXAMPLE.COM
[realms]
 EXAMPLE.COM = {
  kdc = example.com
  admin_server = example.com
 }
 ONPREM.COM = {
  kdc = onprem.com
  admin_server = onprem.com
 }
[domain_realm]
 .example.com = EXAMPLE.COM
 example.com = EXAMPLE.COM
 .onprem.com = ONPREM.COM
 onprem.com = ONPREM.COM  
 .rds.amazonaws.com = EXAMPLE.COM
 .amazonaws.com.rproxy.goskope.com.cn = EXAMPLE.COM
 .amazon.com = EXAMPLE.COM
```

# 在 Active Directory 域中管理 RDS for PostgreSQL 数据库实例
<a name="postgresql-kerberos-managing"></a>

可以使用控制台、CLI 或 RDS API 来管理数据库实例及其与 Microsoft Active Directory 的关系。例如，您可以关联 Active Directory 以启用 Kerberos 身份验证。您也可以删除 Active Directory 关联以禁用 Kerberos 身份验证。您也可以将由一个 Microsoft Active Directory 在外部进行身份验证的数据库实例移动到另一个 Active Directory。

例如，使用 CLI，您可以执行下列操作：
+ 要再次尝试为失败的成员启用 Kerberos 身份验证，请使用 [modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) CLI 命令。为 `--domain` 选项指定当前成员的目录 ID。
+ 要在数据库实例上禁用 Kerberos 身份验证，请使用 [modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) CLI 命令。为 `none` 选项指定 `--domain`。
+ 要将数据库实例从一个域移动到另一个域，请使用 [modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) CLI 命令。为 `--domain` 选项指定新域的域标识符。

## 了解域成员资格
<a name="postgresql-kerberos-managing.understanding"></a>

在创建或修改数据库实例后，它将成为域的成员。您可以在控制台中查看域成员身份状态，也可以通过运行 [describe-db-instances](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-instances.html) CLI 命令来查看。数据库实例的状态可以是以下状态之一：
+ `kerberos-enabled` – 数据库实例已启用 Kerberos 身份验证。
+ `enabling-kerberos` – AWS是在此数据库实例上启用 Kerberos 身份验证的过程。
+ `pending-enable-kerberos` – 启用 Kerberos 身份验证正在此数据库实例上等待处理。
+ `pending-maintenance-enable-kerberos` – AWS将尝试在下一个计划的维护时段在数据库实例上启用 Kerberos 身份验证。
+ `pending-disable-kerberos` – 禁用 Kerberos 身份验证正在此数据库实例上等待处理。
+ `pending-maintenance-disable-kerberos` – AWS 将尝试在下一个计划的维护时段在数据库实例上禁用 Kerberos 身份验证。
+ `enable-kerberos-failed` – 出现一个配置问题，导致 AWS 无法在数据库实例上启用 Kerberos 身份验证。在重新发出命令以修改数据库实例之前纠正配置问题。
+ `disabling-kerberos` – AWS是在此数据库实例上启用 Kerberos 身份验证的过程。

启用 Kerberos 身份验证的请求可能因网络连接问题或不正确的 IAM 角色而失败。在某些情况下，在创建或修改数据库实例时，尝试启用 Kerberos 身份验证可能会失败。如果是这样，请确保使用正确的 IAM 角色，然后修改数据库实例以加入域。

**注意**  
仅针对 RDS for PostgreSQL 的 Kerberos 身份验证将流量发送到域的 DNS 服务器。在运行 PostgreSQL 的数据库实例上，所有其他 DNS 请求将被视为出站网络访问。有关使用 RDS for PostgreSQL 进行出站网络访问的更多信息，请参阅 [将自定义 DNS 服务器用于出站网络访问](Appendix.PostgreSQL.CommonDBATasks.CustomDNS.md)。

# 使用 Kerberos 身份验证连接到 PostgreSQL
<a name="postgresql-kerberos-connecting"></a>

您可以使用 pgAdmin 界面或命令行界面（如 psql）通过 Kerberos 身份验证连接到 PostgreSQL。有关连接的更多信息，请参阅 [连接到运行 PostgreSQL 数据库引擎的数据库实例](USER_ConnectToPostgreSQLInstance.md) 。有关获取连接所需的端点、端口号和其他详细信息的信息，请参阅。[连接到 PostgreSQL 数据库实例](CHAP_GettingStarted.CreatingConnecting.PostgreSQL.md#CHAP_GettingStarted.Connecting.PostgreSQL)

**注意**  
PostgreSQL 中的 GSSAPI 身份验证和加密由 Kerberos 库 `libkrb5.so` 实施。`postgres_fdw` 和 `dblink` 等功能也依赖于同一个库，以通过 Kerberos 身份验证或加密进行出站连接。

## pgAdmin
<a name="collapsible-section-pgAdmin"></a>

要使用 pgAdmin 通过 Kerberos 身份验证连接到 PostgreSQL，请执行以下步骤：

1. 在您的客户端计算机上启动 pgAdmin 应用程序。

1. 在 **Dashboard** (控制面板) 选项卡上，选择 **Add New Server** (添加新服务器)。

1. 在 **Create - Server (创建 - 服务器)** 对话框中，在 **General (常规)** 选项卡上键入名称以在 pgAdmin 中标识该服务器。

1. 在 **Connection (连接)** 选项卡上，键入您的 RDS for PostgreSQL 数据库的以下信息。
   + 对于 **Host**（主机），输入 RDS for PostgreSQL 数据库实例的端点。端点看起来类似于以下所示：

     ```
     RDS-DB-instance.111122223333.aws-region.rds.amazonaws.com
     ```

     要从 Windows 客户端连接到本地 Microsoft Active Directory，请使用 AWS Managed Active Directory 的域名，而不是主机端点中的 `rds.amazonaws.com`。例如，假设 AWS Managed Active Directory 的域名为 `corp.example.com`。然后，对于 **Host**（主机），按如下方式指定端点：

     ```
     RDS-DB-instance.111122223333.aws-region.corp.example.com
     ```
   + 对于 **Port (端口)**，输入分配的端口。
   + 对于 **Maintenance database (维护数据库)**，输入客户端将连接到的初始数据库的名称。
   + 对于**用户名**，键入您在 [步骤 7：为您的 Kerberos 主体创建 PostgreSQL 用户](postgresql-kerberos-setting-up.md#postgresql-kerberos-setting-up.create-logins) 中为 Kerberos 身份验证输入的用户名。

1. 选择 **Save**。

## psql
<a name="collapsible-section-psql"></a>

要使用 psql 通过 Kerberos 身份验证连接到 PostgreSQL，请执行以下步骤：

1. 在命令提示符处，运行以下命令。

   ```
   kinit username                
   ```

   将 *`username`* 替换为用户名。在提示符下，输入在 Microsoft Active Directory 中为用户存储的密码。

1. 如果 PostgreSQL 数据库实例使用可公开访问的 VPC，请将数据库实例端点的 IP 地址放在 EC2 客户端上的 `/etc/hosts` 文件中。例如，以下命令获取 IP 地址，然后将其放在 `/etc/hosts` 文件中。

   ```
   % dig +short PostgreSQL-endpoint.AWS-Region.rds.amazonaws.com  
   ;; Truncated, retrying in TCP mode.
   ec2-34-210-197-118.AWS-Region.compute.amazonaws.com.
   34.210.197.118 
   
   % echo " 34.210.197.118  PostgreSQL-endpoint.AWS-Region.rds.amazonaws.com" >> /etc/hosts
   ```

   如果您从 Windows 客户端使用本地 Microsoft Active Directory，则需要使用特殊终端节点进行连接。在主机终端节点中使用 `rds.amazonaws.com` Managed Active Directory 的域名，而不是 Amazon 域 AWS。

   例如，假设 AWS Managed Active Directory 的域名为 `corp.example.com`。为终端节点使用格式 `PostgreSQL-endpoint.AWS-Region.corp.example.com`，将其放入 `/etc/hosts` 文件。

   ```
   % echo " 34.210.197.118  PostgreSQL-endpoint.AWS-Region.corp.example.com" >> /etc/hosts
   ```

1. 使用以下 psql 命令登录到与 Active Directory 集成的 PostgreSQL 数据库实例。

   ```
   psql -U username@CORP.EXAMPLE.COM -p 5432 -h PostgreSQL-endpoint.AWS-Region.rds.amazonaws.com postgres
   ```

   要从 Windows 客户端使用本地 Active Directory 登录 PostgreSQL 数据库集群，请使用以下 psql 命令以及上一步中的域名 (`corp.example.com`)：

   ```
   psql -U username@CORP.EXAMPLE.COM -p 5432 -h PostgreSQL-endpoint.AWS-Region.corp.example.com postgres
   ```

# 将自定义 DNS 服务器用于出站网络访问
<a name="Appendix.PostgreSQL.CommonDBATasks.CustomDNS"></a>

RDS for PostgreSQL 支持您数据库实例上的出站网络访问，并允许从客户拥有的自定义 DNS 服务器进行域名服务 (DNS) 解析。通过自定义 DNS 服务器，您可以仅解析 RDS for PostgreSQL 数据库实例中的完全限定域名。

**Topics**
+ [启用自定义 DNS 解析](#Appendix.PostgreSQL.CommonDBATasks.CustomDNS.Enable)
+ [禁用自定义 DNS 解析](#Appendix.PostgreSQL.CommonDBATasks.CustomDNS.Disable)
+ [设置自定义 DNS 服务器](#Appendix.Oracle.CommonDBATasks.CustomDNS.Setup)

## 启用自定义 DNS 解析
<a name="Appendix.PostgreSQL.CommonDBATasks.CustomDNS.Enable"></a>

要在您的客户 VPC 中启用 DNS 解析，请首先将自定义数据库参数组与 RDS for PostgreSQL 实例相关联。然后，通过将 `rds.custom_dns_resolution` 参数设置为 1 启用该参数，并重新启动数据库实例以使更改生效。

## 禁用自定义 DNS 解析
<a name="Appendix.PostgreSQL.CommonDBATasks.CustomDNS.Disable"></a>

要在您的客户 VPC 中关闭 DNS 解析，请首先将自定义数据库参数组的 `rds.custom_dns_resolution` 参数设置为 0 禁用该参数。然后，重新启动数据库实例以使更改生效。

## 设置自定义 DNS 服务器
<a name="Appendix.Oracle.CommonDBATasks.CustomDNS.Setup"></a>

自定义 DNS 名称服务器设置完成后，它需要 30 分钟将更改传播到数据库实例中。将更改传播到数据库实例后，需要进行 DNS 查找的所有出站网络流量将通过端口 53 查询您的 DNS 服务器。

**注意**  
如果未设置自定义 DNS 服务器，并且 `rds.custom_dns_resolution` 设置为 1，则会使用 Amazon Route 53 私有区域解析主机。有关更多信息，请参阅[使用私有托管区域](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-private.html)。

**为您的 RDS for PostgreSQL 数据库实例设置自定义 DNS 服务器**

1. 在附加到 VPC 的动态主机配置协议 (DHCP) 选项集中，将 `domain-name-servers` 选项设置为您的 DNS 名称服务器的 IP 地址。有关更多信息，请参阅[ DHCP 选项集](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_DHCP_Options.html)。
**注意**  
`domain-name-servers` 选项最多可接受四个值，但您的 Amazon RDS 数据库实例只使用第一个值。

1. 请确保您的 DNS 服务器可以解析所有查找查询，包括公有 DNS 名称、Amazon EC2 私有 DNS 名称和特定客户的 DNS 名称。如果出站网络流量中包含您的 DNS 服务器不能处理的 DNS 查找，您的 DNS 服务器必须已配置适当的上游 DNS 提供程序。

1. 请配置您的 DNS 服务器，以生成等于或小于 512 字节的用户数据报协议 (UDP) 响应。

1. 请配置您的 DNS 服务器，以生成等于或小于 1024 字节的传输控制协议 (TCP) 响应。

1. 配置您的 DNS 服务器，允许流量通过 Amazon RDS 数据库实例的端口 53 入站。如果您的 DNS 服务器在 Amazon VPC 中，此 VPC 的安全组必须包含以下入站规则：允许端口 53 上的 UDP 和 TCP 流量。如果 DNS 服务器不在 Amazon VPC 中，它必须具有适当的防火墙设置，以允许端口 53 上的 UDP 和 TCP 入站流量。

   有关更多信息，请参阅[您的 VPC 的安全组](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)和[添加和删除规则](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html#AddRemoveRules)。

1. 配置您的 Amazon RDS 数据库实例的 VPC，允许流量通过端口 53 出站。您的 VPC 安全组必须包含以下出站规则：允许端口 53 上的 UDP 和 TCP 流量。

   有关更多信息，请参阅 *Amazon VPC 用户指南*中的[您的 VPC 的安全组](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)和[添加和删除规则](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html#AddRemoveRules)。

1. 确保正确配置 Amazon RDS 数据库实例和 DNS 服务器之间的路由路径以允许 DNS 流量。

   此外，如果 Amazon RDS 数据库实例和 DNS 服务器不在同一 VPC 中，确保在它们之间设置对等连接。有关更多信息，请参阅 *Amazon VPC Peering Guide* 中的[什么是 VPC 对等连接？](https://docs.aws.amazon.com/vpc/latest/peering/Welcome.html)。

# 升级 RDS for PostgreSQL 数据库引擎
<a name="USER_UpgradeDBInstance.PostgreSQL"></a>

您可以为 PostgreSQL 数据库管理两种类型的升级：
+ 操作系统更新 – 有时，为了应用安全修复或操作系统更改，Amazon RDS 可能需要更新数据库的基础操作系统。您可通过使用 AWS Command Line Interface（AWS CLI）或 RDS API 来决定 Amazon RDS 何时应用操作系统更新。有关操作系统更新的更多信息，请参阅 [对数据库实例应用更新](USER_UpgradeDBInstance.Maintenance.md#USER_UpgradeDBInstance.OSUpgrades)。
+  数据库引擎升级 – 如果 Amazon RDS 支持数据库引擎的新版本，您可以将您的数据库升级到新版本。

此上下文中的*数据库*是 RDS for PostgreSQL 数据库实例或多可用区数据库集群。

PostgreSQL 数据库有两种引擎升级方式：主要版本升级和次要版本升级。

**主要版本升级。**  
*主要版本升级*会包含不与现有应用程序向后兼容的数据库更改。因此，您必须手动执行数据库的主要版本升级。您可以通过修改数据库实例或多可用区数据库集群来启动主要版本升级。在执行主要版本升级之前，建议您按照[为 RDS for PostgreSQL 升级选择主要版本](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.md)中所述的步骤操作。  
Amazon RDS 通过以下方式处理多可用区主版本升级：  
+ **多可用区数据库实例部署** – Amazon RDS 会同时升级主实例和任何备用实例。在升级完成期间，数据库可能会在几分钟内不可用。
+ **多可用区数据库集群部署** – Amazon RDS 同时升级写入器和读取器实例。在升级完成期间，数据库可能会在几分钟内不可用。
如果您升级具有区域内只读副本的数据库实例，Amazon RDS 会升级副本以及主数据库实例。  
Amazon RDS 不会升级多可用区数据库集群只读副本。如果您对多可用区数据库集群执行主要版本升级，则其只读副本的复制状态会更改为**终止**。升级完成后，您必须手动删除并重新创建只读副本。  
您可以使用蓝绿部署，最大限度地减少主要版本升级所需的停机时间。有关更多信息，请参阅 [使用 Amazon RDS 蓝绿部署进行数据库更新](blue-green-deployments.md)。

**次要版本升级**  
相比之下，*次要版本升级*仅包括与现有应用程序向后兼容的更改。您可以通过修改数据库来手动启动次要版本升级。或者，您可以在创建或修改数据库时启用**自动次要版本升级**选项。这样做意味着 Amazon RDS 会在测试并批准新版本后自动升级您的数据库。  
Amazon RDS 通过以下方式处理多可用区次要版本升级：  
+ **多可用区数据库实例部署** – Amazon RDS 会同时升级主实例和任何备用实例。在升级完成期间，数据库可能会在几分钟内不可用。
+ **多可用区数据库集群部署** – Amazon RDS 一次升级一个读取器数据库实例。然后，其中一个读取器数据库实例将切换为新的写入器数据库实例。然后，Amazon RDS 升级旧的写入器实例（现在是读取器实例）。多可用区数据库集群通常可将次要版本升级的停机时间缩短至大约 35 秒。与 RDS 代理一起使用时，这种方法可以将停机时间进一步缩短到一秒或更短。有关更多信息，请参阅 [Amazon RDS 代理](rds-proxy.md)。或者，您可以使用开源数据库代理，例如 [ProxySQL](https://aws.amazon.com/blogs/database/achieve-one-second-or-less-of-downtime-with-proxysql-when-upgrading-amazon-rds-multi-az-deployments-with-two-readable-standbys/)、[PgBouncer](https://aws.amazon.com/blogs/database/fast-switchovers-with-pgbouncer-on-amazon-rds-multi-az-deployments-with-two-readable-standbys-for-postgresql/) 或 [AWS Advanced JDBC Wrapper Driver](https://aws.amazon.com/blogs/database/achieve-one-second-or-less-downtime-with-the-advanced-jdbc-wrapper-driver-when-upgrading-amazon-rds-multi-az-db-clusters/)。
如果数据库具有只读副本，则您必须在升级源实例或集群之前首先升级所有只读副本。  
有关更多信息，请参阅 [RDS for PostgreSQL 的自动次要版本升级](USER_UpgradeDBInstance.PostgreSQL.Minor.md)。有关手动执行次要版本升级的信息，请参阅 [手动升级引擎版本](USER_UpgradeDBInstance.Upgrading.md#USER_UpgradeDBInstance.Upgrading.Manual)。

有关数据库引擎版本和弃用数据库引擎版本的策略的更多信息，请参阅 Amazon RDS 常见问题解答中的[数据库引擎版本](https://aws.amazon.com/rds/faqs/#Database_Engine_Versions)。

**Topics**
+ [PostgreSQL 升级的注意事项](#USER_UpgradeDBInstance.PostgreSQL.Considerations)
+ [查找有效的升级目标](#USER_UpgradeDBInstance.PostgreSQL.FindingTargets)
+ [PostgreSQL 版本号](USER_UpgradeDBInstance.PostgreSQL.VersionID.md)
+ [RDS for PostgreSQL 中的 RDS 版本号](USER_UpgradeDBInstance.PostgreSQL.rds.version.md)
+ [为 RDS for PostgreSQL 升级选择主要版本](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.md)
+ [如何执行 RDS for PostgreSQL 的主要版本升级](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process.md)
+ [RDS for PostgreSQL 的自动次要版本升级](USER_UpgradeDBInstance.PostgreSQL.Minor.md)
+ [在 RDS for PostgreSQL 数据库中升级 PostgreSQL 扩展](USER_UpgradeDBInstance.PostgreSQL.ExtensionUpgrades.md)
+ [使用事件监控 RDS for PostgreSQL 引擎升级](USER_UpgradeDBInstance.PostgreSQL.Monitoring.md)

## PostgreSQL 升级的注意事项
<a name="USER_UpgradeDBInstance.PostgreSQL.Considerations"></a>

为了安全地升级数据库，Amazon RDS 使用 [PostgreSQL documentation](https://www.postgresql.org/docs/current/pgupgrade.html) 中所述的 `pg_upgrade` 实用程序

如果您的备份保留期大于 0，Amazon RDS 会在升级期间获取两份数据库快照。第一个数据库快照是数据库在进行任何升级更改前的快照。如果数据库升级失败，您可以还原此快照，以创建一个运行旧版本的数据库。第二个数据库快照是在升级完成后制作的。一旦备份保留期到期，就会自动删除这些数据库快照。

**注意**  
仅当您将数据库的备份保留期设置为大于 0 的数字时，Amazon RDS 才会在升级过程中制作数据库快照。要更改数据库实例的备份保留期，请参阅[修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md)。您无法为多可用区数据库集群配置自定义备份保留期。

执行数据库实例的主要版本升级时，任何区域内只读副本也会自动升级。升级工作流程开始后，只读副本实例会等待主数据库实例上的 `pg_upgrade` 成功完成。然后，主数据库实例升级会等待只读副本实例升级完成。在升级完成之前，您会遇到中断。当您对多可用区数据库集群执行主要版本升级时，只读副本的复制状态会更改为**终止**。

升级完成后，您无法还原到以前版本的数据库引擎。如果要返回之前的版本，则需要还原在升级之前创建的数据库快照，以创建新的数据库。

## 查找有效的升级目标
<a name="USER_UpgradeDBInstance.PostgreSQL.FindingTargets"></a>

使用 AWS 管理控制台 升级数据库时，它会显示数据库的有效升级目标。您还可以使用以下 AWS CLI 命令来标识数据库的有效升级目标：

对于 Linux、macOS 或 Unix：

```
aws rds describe-db-engine-versions \
  --engine postgres \
  --engine-version version-number \
  --query "DBEngineVersions[*].ValidUpgradeTarget[*].{EngineVersion:EngineVersion}" --output text
```

对于：Windows

```
aws rds describe-db-engine-versions ^
  --engine postgres ^
  --engine-version version-number ^
  --query "DBEngineVersions[*].ValidUpgradeTarget[*].{EngineVersion:EngineVersion}" --output text
```

例如，要标识 PostgreSQL 版本 16.1 数据库的有效升级目标，请运行以下 AWS CLI 命令：

对于 Linux、macOS 或 Unix：

```
aws rds describe-db-engine-versions \
  --engine postgres \
  --engine-version 16.1 \
  --query "DBEngineVersions[*].ValidUpgradeTarget[*].{EngineVersion:EngineVersion}" --output text
```

对于：Windows

```
aws rds describe-db-engine-versions ^
  --engine postgres ^
  --engine-version 16.1 ^
  --query "DBEngineVersions[*].ValidUpgradeTarget[*].{EngineVersion:EngineVersion}" --output text
```

# PostgreSQL 版本号
<a name="USER_UpgradeDBInstance.PostgreSQL.VersionID"></a>

PostgreSQL 数据库引擎的版本编号序列如下所示：
+ 对于 PostgreSQL 版本 10 及更高版本，引擎版本号格式为 *major.minor*。主要版本号是版本号的整数部分。次要版本号是版本号的小数部分。

  主要版本升级会增加版本号的整数部分，例如从 10.*次要版本* 升级为 11.*次要版本*。
+ 对于版本低于 10 的 PostgreSQL 版本，引擎版本号的格式为 *major.major.minor*。主引擎版本号是版本号的整数和第一个小数点后的部分。例如，9.6 是一个主要版本。次要版本号是版本号的第三部分。例如，版本 9.6.12 中 12 是次要版本号。

  主要版本升级会增加版本号的主要版本部分。例如，从 *9.6*.12 升级到 11.14 是主要版本升级，其中 *9.6* 和 *11* 为主要版本号。

有关 RDS Extended Support 版本号的信息，请参阅[Amazon RDS Extended Support 版本命名](extended-support-versions.md#extended-support-naming)。

# RDS for PostgreSQL 中的 RDS 版本号
<a name="USER_UpgradeDBInstance.PostgreSQL.rds.version"></a>

RDS 版本号使用 `major.minor.patch` 命名方案。RDS 补丁版本包括在发布后添加到次要版本的重要错误修复。有关 RDS 扩展支持版本号的信息，请参阅[Amazon RDS Extended Support 版本命名](extended-support-versions.md#extended-support-naming)。

要识别数据库的 Amazon RDS 版本号，必须先使用以下命令创建 `rds_tools` 扩展：

```
CREATE EXTENSION rds_tools;
```

从 PostgreSQL 版本 15.2-R2 的发行版开始，您可以使用以下 SQL 查询找出 RDS for PostgreSQL 数据库的 RDS 版本号：

```
postgres=> SELECT rds_tools.rds_version();
```

例如，查询 RDS for PostgreSQL 15.2 数据库将返回以下内容：

```
rds_version
----------------
 15.2.R2
(1 row)
```

# 为 RDS for PostgreSQL 升级选择主要版本
<a name="USER_UpgradeDBInstance.PostgreSQL.MajorVersion"></a>

主要版本升级可包含不与数据库的以前版本向后兼容的更改。新功能会导致现有应用程序无法正常工作。出于此原因，Amazon RDS 不会自动应用主要版本升级。要执行主要版本升级，请手动修改数据库。在将升级应用到生产数据库之前，确保彻底地测试任何升级，验证您的应用程序是否正常工作。执行 PostgreSQL 主要版本升级时，建议您按照 [如何执行 RDS for PostgreSQL 的主要版本升级](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process.md) 中所述的步骤操作。

将 PostgreSQL 单可用区数据库实例或多可用区数据库实例部署升级到其下一个主要版本时，与数据库关联的任何只读副本也会升级到该下一个主要版本。在某些情况下，您可以在升级时跳至更高的主要版本。如果跳过升级主要版本，则只读副本也会升级到该目标主要版本。跳过其他主要版本升级到版本 11 有一定的限制。您可以在 [如何执行 RDS for PostgreSQL 的主要版本升级](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process.md) 中所述的步骤中找到详细信息。

PostgreSQL 引擎升级期间大多数 PostgreSQL 扩展都不会升级。这些扩展必须单独升级。有关更多信息，请参阅 [在 RDS for PostgreSQL 数据库中升级 PostgreSQL 扩展](USER_UpgradeDBInstance.PostgreSQL.ExtensionUpgrades.md)。

通过运行以下 AWS CLI 查询，您可以找出哪些主要版本适用于您的 RDS for PostgreSQL 数据库：

```
aws rds describe-db-engine-versions --engine postgres  --engine-version your-version --query "DBEngineVersions[*].ValidUpgradeTarget[*].{EngineVersion:EngineVersion}" --output text
```

下表总结了此查询结果的所有可用版本。版本号上的星号（\$1）表示不再支持该版本。如果当前版本不受支持，建议您升级到最新的次要版本升级目标或该版本的其他可用升级目标之一。


| 当前源版本 | 升级目标 | 
| --- | --- | 
| 17.6 | 无 | 
| 17.5 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176) | 
| 17.4 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175) | 
| 17.3\$1、17.2 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) | 
| 17.1\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) | 
| 16.10 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176) | 
| 16.9 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610) | 
| 16.8 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169) | 
| 16.7\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) | 
| 16.7 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) | 
| 16.6 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) | 
| 16.5\$1、16.4 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166) | 
| 16.3 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166)、[16.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164) | 
| 16.2\$1、16.1\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166)、[16.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164)、[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) | 
| 15.14 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610) | 
| 15.13 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514) | 
| 15.12、15.11\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513) | 
| 15.10 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512) | 
| 15.9\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)、[15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510) | 
| 15.8 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166)、[16.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)、[15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510) | 
| 15.7 | [16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、1[6.8、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)16[.7、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version167)6.[6、16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166).5[、16.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version165)4、[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164), [16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、1[5.12、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)15[.11、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1511)5.[10、15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510).9[、15.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version159)8[15.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158) | 
| 15.6\$1、15.5\$1、15.4\$1、15.3\$1、15.2\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6、16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166).4[、16.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164)3[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)、[15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510)、[15.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158)、[15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) | 
| 14.19 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514) | 
| 14.18 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419) | 
| 14.17、14.16\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418) | 
| 14.15 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)、[15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417) | 
| 14.14\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)5.[10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)、[14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415) | 
| 14.13 | [16.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164) [15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、1[5.12、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)15[.11、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1511)5.[10、15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510).9[、15.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version159)8[15.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158) [14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、1[4.17、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)14[.16、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1416)4.[15、14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415).1[4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1414) | 
| 14.12 | [16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、1[5.12、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)15[.11、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1511)5.[10、15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510).9[、15.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version159)8、[15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158), [15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) [14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、1[4.17、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)14[.16、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1416)4.[15、14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415).1[4、14.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1414)13[14.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413) | 
| 14.11\$1、14.10\$1、14.9\$1、14.8\$1、14.7\$1、14.6\$1、14.5\$1、14.4\$1、14.3\$1、14.2\$1、14.1\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6、16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166).4[、16.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164)3[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)5.[10、15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510).8[、15.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158)7[15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)、[14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415)、[14.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413)、[14.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1412) | 
| 13.22 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419) | 
| 13.21 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322) | 
| 13.20、13.19\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321) | 
| 13.18、13.17\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)5.[10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)、[14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、[13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320) | 
| 13.16 | [16.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164) [15.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158) [14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、1[4.17、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)14[.15、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415)4.[14、14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1414).1[3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413) [13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、1[3.20、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)13[.19、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1319)3.[18、13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318).1[7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1317) | 
| 13.15 | [16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158)、1[5.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) [14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、1[4.17、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)14[.15、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415)4.[14、14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1414).1[3、14.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413)12[14.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1412) [13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、1[3.20、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)13[.19、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1319)3.[18、13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318).1[7、13.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1317)16[13.16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1316) | 
| 13.14\$1、13.13\$1、13.12\$1、13.11\$1、13.10\$1、13.9\$1、13.8\$1、13.7\$1、13.6\$1、13.5\$1、13.4\$1、13.3\$1、13.2\$1、13.1\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6、16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166).4[、16.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164)3[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)5.[10、15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510).8[、15.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158)7[15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、1[4.18、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)14[.17、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)4.[15、14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415).1[3、14.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413)12[14.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1412) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、[13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)、[13.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318)、[13.16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1316)、[13.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1315) | 
| 12.22-rds.20250508 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、1[4.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321) | 
| 12.22-rds.20250220 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、1[4.18、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)14[.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、[13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320) [12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) | 
| 12.22、12.21\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)、[15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)、[14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、[13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)、[13.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318) [12.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250220)、[12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) | 
| 12.20\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166)、[16.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)、[15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510)、[15.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)、[14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415)、[14.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、[13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)、[13.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318)、[13.16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1316) [12.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222)、[12.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250220)、[12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) | 
| 12.19\$1、12.18\$1、12.17\$1、12.16\$1、12.15\$1、12.14\$1、12.13\$1、12.12\$1、12.11\$1、12.10\$1、12.9\$1、12.8\$1、12.7\$1、12.6\$1、12.5\$1、12.4\$1、12.3\$1、12.2\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6、16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166).4[、16.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164)3[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)5.[10、15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510).8[、15.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158)7[15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、1[4.18、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)14[.17、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)4.[15、14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415).1[3、14.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413)12[14.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1412) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、1[3.21、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)13[.20、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)3.[18、13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318).1[6、13.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1316)15[13.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1315) [12.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222)、[12.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250220)、[12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) | 
| 11.22-rds.20250508 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321) [12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) | 
| 11.22-rds.20250220 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、[13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320) [12.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250220)、[12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) [11.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20250508) | 
| 11.22-rds.20240509 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、1[6.9、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)16[.8、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)6.[6、16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166).4[、16.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164)3[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、1[5.13、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)15[.12、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)5.[10、15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510).8[、15.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158)7[15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、1[4.18、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)14[.17、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)4.[15、14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415).1[3、14.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413)12[14.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1412) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、1[3.21、](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)13[.20、1](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)3.[18、13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318).1[6、13.](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1316)15[13.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1315) [12.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222)、[12.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250220)、[12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) [11.22-rds.20240808](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20240808)、[11.22-rds.20241121](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20241121)、[11.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20250220)、[11.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20250508) | 
| 11.22、11.21\$1、11.20\$1、11.19\$1、11.18\$1、11.17\$1、11.16\$1、11.15\$1、11.14\$1、11.13\$1、11.12\$1、11.11\$1、11.10\$1、11.9\$1、11.8\$1、11.7\$1、11.6\$1、11.5\$1、11.4\$1、11.2\$1、11.1\$1 | [17.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version176)、[17.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version175)、[17.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version174)、[17.2](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version172) [16.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1610)、[16.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version169)、[16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168)、[16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166)、[16.4](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version164)、[16.3](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version163) [15.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1514)、[15.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1513)、[15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512)、[15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510)、[15.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version158)、[15.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version157) [14.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1419)、[14.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1418)、[14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417)、[14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415)、[14.13](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1413)、[14.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1412) [13.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1322)、[13.21](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1321)、[13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320)、[13.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318)、[13.16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1316)、[13.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1315) [12.22](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222)、[12.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250220)、[12.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1222rds20250508) [11.22-rds.20240418](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20240418)、[11.22-rds.20240509](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20240509)、[11.22-rds.20240808](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20240808)、[11.22-rds.20241121](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20241121)、[11.22-rds.20250220](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20250220)、[11.22-rds.20250508](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1122rds20250508) | 

\$1 此版本不再受支持。

# 如何执行 RDS for PostgreSQL 的主要版本升级
<a name="USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process"></a>

在 Amazon RDS for PostgreSQL 数据库上执行主要版本升级时，我们建议采用以下过程：

1. **准备一个版本兼容的参数组** – 如果您使用的是自定义参数组，则您有两个选择。您可为新数据库引擎版本指定默认参数组。或者您可为新数据库引擎版本创建您自己的自定义参数组。有关更多信息，请参阅[Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)和[使用多可用区数据库集群的数据库集群参数组](USER_WorkingWithDBClusterParamGroups.md)。

1. **检查不受支持的数据库类** – 检查数据库的实例类是否与您要升级到的 PostgreSQL 版本兼容。有关更多信息，请参阅 [数据库实例类支持的数据库引擎](Concepts.DBInstanceClass.Support.md)。

1. **检查是否有不支持的使用方式：**
   + **准备的事务** – 在尝试升级前，提交或回滚所有打开的已准备事务。

     您可以使用以下查询来验证您的数据库上是否没有未结的已准备事务。

     ```
     SELECT count(*) FROM pg_catalog.pg_prepared_xacts;
     ```
   + **Reg\$1 数据类型** – 在尝试升级前取消使用所有 *reg\$1* 数据类型。除了 `regtype` 和 `regclass` 以外，您不能升级 *reg\$1* 数据类型。`pg_upgrade` 实用程序无法保留此数据类型，Amazon RDS 使用它来执行升级。

     要验证是否没有使用不支持的 *reg\$1* 数据类型，请对每个数据库使用以下查询。

     ```
     SELECT count(*) FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n, pg_catalog.pg_attribute a
       WHERE c.oid = a.attrelid
           AND NOT a.attisdropped
           AND a.atttypid IN ('pg_catalog.regproc'::pg_catalog.regtype,
                              'pg_catalog.regprocedure'::pg_catalog.regtype,
                              'pg_catalog.regoper'::pg_catalog.regtype,
                              'pg_catalog.regoperator'::pg_catalog.regtype,
                              'pg_catalog.regconfig'::pg_catalog.regtype,
                              'pg_catalog.regdictionary'::pg_catalog.regtype)
           AND c.relnamespace = n.oid
           AND n.nspname NOT IN ('pg_catalog', 'information_schema');
     ```

1. **检查是否存在无效的数据库：**
   + 确保没有无效的数据库。`pg_database` 目录中的 `datconnlimit` 列包含一个值 `-2`，用于将 `DROP DATABASE` 操作期间中断的数据库标记为无效。

     使用以下查询来检查是否存在无效的数据库：

     ```
     SELECT datname FROM pg_database WHERE datconnlimit = - 2;
     ```
   + 上一个查询返回无效数据库的名称。可以使用 `DROP DATABASE invalid_db_name;` 删除无效的数据库。也可以使用以下命令来删除无效的数据库：

     ```
     SELECT 'DROP DATABASE ' || quote_ident(datname) || ';' FROM pg_database WHERE datconnlimit = -2 \gexec
     ```

   有关无效数据库的更多信息，请参阅[了解对无效数据库使用 autovacuum 的行为](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/appendix.postgresql.commondbatasks.autovacuumbehavior.html)。

1. **处理逻辑复制槽**：如果数据库有逻辑复制槽，则无法进行升级。逻辑复制插槽通常用于 AWS DMS 迁移，以及将表从数据库复制到数据湖、BI 工具和其他目标。升级之前，请确保您知道正在使用的任何逻辑复制槽的用途，并确认可以将其删除。如果逻辑复制槽仍在使用中，则不应将其删除，但也无法继续升级。

   如果不需要逻辑复制槽，则可以使用以下 SQL 将其删除：

   ```
   SELECT * FROM pg_replication_slots WHERE slot_type NOT LIKE 'physical';
   SELECT pg_drop_replication_slot(slot_name);
   ```

   使用 `pglogical` 扩展的逻辑复制设置还需要删除插槽才能成功升级主要版本。有关如何识别和删除使用 `pglogical` 扩展创建的插槽的信息，请参阅 [管理 RDS for PostgreSQL 的逻辑复制插槽](Appendix.PostgreSQL.CommonDBATasks.pglogical.handle-slots.md)。

   在源版本 17 及更高版本上，升级过程中可保留非只读副本上的逻辑复制槽。升级过程无法保留在只读副本上创建的逻辑复制槽。

   在开始升级之前，请确保所有事务和逻辑解码消息都已在槽中使用。如果逻辑复制槽保留了未使用的预写日志文件（WAL），则升级将失败，并显示一条标识问题槽的消息。有关更多详细信息，请参阅 [PostgreSQL 文档](https://www.postgresql.org/docs/current/logical-replication-upgrade.html)。

   在源版本低于 17.8 或 18.2 的多可用区集群上，请确保禁用 `flow_control`。有关更多信息，请参阅[为多可用区数据库集群开启和关闭流量控制](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html#multi-az-db-clusters-concepts-replica-lag)。从 `shared_preload_libraries` 中移除扩展程序，然后重启数据库实例，即可关闭流量控制。

1. **处理只读副本** – 单可用区数据库实例或多可用区数据库实例部署的升级也会将区域内只读副本与主数据库实例一起升级。Amazon RDS 不会升级多可用区数据库集群只读副本。

   您无法单独升级只读副本。如果您可以单独升级，则可能会导致主数据库和副本数据库具有不同 PostgreSQL 主要版本的情况。但是，只读副本升级可能会增加主数据库实例上的停机时间。为防止只读副本升级，请在开始升级过程之前将副本提升为独立实例或将其删除。

   升级过程将根据只读副本的当前参数组重新创建副本的参数组。只有在升级完成后，才能通过修改只读副本将自定义参数组应用于只读副本。有关只读副本的更多信息，请参阅 [使用 Amazon RDS for PostgreSQL 只读副本](USER_PostgreSQL.Replication.ReadReplicas.md)。

1. **处理大型对象**：在 PostgreSQL 中，大型对象（也称为 BLOB）用于存储和管理大于常规列数据类型支持的最大大小的大型二进制对象（如文件、图像、视频等）。有关更多信息，请参阅 [PostgreSQL 大型对象文档](https://www.postgresql.org/docs/current/largeobjects.html)。

   如果有数百万个大型对象，并且实例在升级期间无法处理它们，则升级可能会耗尽内存并失败。PostgreSQL 主要版本升级过程包括两个主要阶段：通过 pg\$1dump 转储架构和通过 pg\$1restore 还原架构。如果数据库具有数百万个大型对象，则您需要确保实例具有足够的内存，可在升级期间处理 pg\$1dump 和 pg\$1restore，并将其扩展到更大的实例类型。

   在开始升级之前，请检查数据库是否有任何大型对象。目录 `pg_largeobject_metadata` 包含与大型对象关联的元数据。实际的大型对象数据存储在 `pg_largeobject` 中。使用以下查询来检查大型对象的数量：

   ```
   SELECT count(*) FROM pg_largeobject_metadata;
   ```

   要清理现有的大型对象或孤立的大型对象，请参阅[使用 lo 模块管理大型对象](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/PostgreSQL_large_objects_lo_extension.html)。

   在规划主要版本升级时，如果数据库包含 2500 万到 3000 万个大型对象，我们建议使用内存至少为 32 GB 的实例类型。此建议基于我们的测试，可能因您的具体工作负载和数据库配置而异。如果数据库包含其它对象（例如表、索引或实体化视图），我们建议您选择更大的实例类型，以确保在升级过程中获得最佳性能。

1. **处理零 ETL 集成**：如果您具有现有的[零 ETL 集成](zero-etl.md)，请在执行主要版本升级之前[将其删除](zero-etl.deleting.md)。然后，在完成升级后，重新创建集成。

   在源版本为 17 及更高主要版本的情况下，零 ETL 集成可在升级过程中得以保留。

1. **执行备份** – 建议您在执行主要版本升级前执行备份，以便为您的数据库获得一个已知的还原点。如果您的备份保留期大于 0，则在升级之前和之后，升级过程会创建数据库的数据库快照。要更改您的备份保留期，请参阅[修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md)和[修改 Amazon RDS 的多可用区数据库集群](modify-multi-az-db-cluster.md)。

   要手动执行备份，请参阅[为 Amazon RDS 的单可用区数据库实例创建数据库快照](USER_CreateSnapshot.md)和[创建 Amazon RDS 的多可用区数据库集群快照](USER_CreateMultiAZDBClusterSnapshot.md)。

1. **在主要版本升级之前更新某些扩展** – 如果打算在升级时跳过主要版本，您需要在执行主要版本升级*之前*更新某些扩展。例如，从版本 9.5.x 或 9.6.x 升级到版本 11.x 将跳过主要版本。要更新的扩展包括 PostGIS 和用于处理空间数据的相关扩展。
   + `address_standardizer`
   + `address_standardizer_data_us`
   + `postgis_raster`
   + `postgis_tiger_geocoder`
   + `postgis_topology`

   由于 `rdkit` 不兼容，如果您使用的是 `rdkit` 版本 4.6.0 及更低版本，以及 PostgreSQL 版本 16 及更低版本，则无法直接升级到 PostgreSQL 版本 17。以下是升级选项：
   + 如果您使用的是 PostgreSQL 版本 13 及更低版本，则需要先执行主要版本升级，升级到版本 14.14 及更高的 14 版本、15.9 及更高的 15 版本或者 16.5 及更高的 16 版本，然后再执行版本升级，升级到 PostgreSQL 17。
   + 如果您使用的是 PostgreSQL 版本 14、15 或 16，则需要执行次要版本升级到 14.14 及更高版本的 14 版本、15.9 及更高版本的 15 版本或 16.5 及更高版本的 16 版本，然后再升级到 PostgreSQL 版本 17。

   为您要使用的每个扩展运行以下命令：

   ```
   ALTER EXTENSION PostgreSQL-extension UPDATE TO 'new-version';
   ```

   有关更多信息，请参阅 [在 RDS for PostgreSQL 数据库中升级 PostgreSQL 扩展](USER_UpgradeDBInstance.PostgreSQL.ExtensionUpgrades.md)。要了解有关升级 PostGIS 的更多信息，请参阅[步骤 6：升级 PostGIS 扩展](Appendix.PostgreSQL.CommonDBATasks.PostGIS.md#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Update)。

1. **在主要版本升级之前删除某些扩展**：必须删除目标版本不支持的扩展，否则升级将失败。

   `plrust` 扩展从 RDS PostgreSQL 18 开始删除。由于已知问题 [[1](https://trac.osgeo.org/postgis/ticket/5983)]、[[2](https://trac.osgeo.org/postgis/ticket/6016)]，`postgis_topology` 扩展在 RDS PostgreSQL 版本 18.1 和 18.2 上不可用。升级前必须删除这些扩展。

   将主要版本跳转到版本 11.x 的升级不支持更新 `pgRouting` 扩展。从版本 9.4.x、9.5.x 或 9.6.x 升级到版本 11.x 时，将会跳过主要版本。可以安全地删除 `pgRouting` 扩展，然后在升级后将其重新安装到兼容的版本中。有关您可以更新到的扩展版本，请参阅[支持的 PostgreSQL 扩展版本](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md)。

   PostgreSQL 版本 11 或更高版本不再支持 `tsearch2` 和 `chkpass` 扩展。

   您可以通过以下查询来检查是否安装了扩展：

   ```
   SELECT * FROM pg_extension WHERE extname in ('extension_name');
   ```

1. **删除未知数据类型** – 根据目标版本删除 `unknown` 数据类型。

   PostgreSQL 版本 10 停止支持 `unknown` 数据类型。如果版本 9.6 数据库使用 `unknown` 数据类型，升级到版本 10 将显示错误消息，如下所示：

   ```
   Database instance is in a state that cannot be upgraded: PreUpgrade checks failed:
   The instance could not be upgraded because the 'unknown' data type is used in user tables.
   Please remove all usages of the 'unknown' data type and try again."
   ```

   要在数据库中查找 `unknown` 数据类型以便删除有问题的列或将其更改为支持的数据类型，请使用以下 SQL：

   ```
   SELECT DISTINCT data_type FROM information_schema.columns WHERE data_type ILIKE 'unknown';
   ```

1. **执行升级试运行** – 我们强烈建议您在生产数据库的副本上测试主要版本升级，然后再尝试在生产数据库上进行升级。您可以监控重复测试数据库上的执行计划，以了解任何可能的执行计划回归，并评估其性能。要创建副本测试实例，您可以从最近的快照还原数据库，也可以通过时间点还原将数据库还原到最近的可还原时间。

   有关更多信息，请参阅 [从快照还原](USER_RestoreFromSnapshot.md#USER_RestoreFromSnapshot.Restoring) 或 [将 Amazon RDS 的数据库实例还原到指定时间](USER_PIT.md)。对于多可用区数据库集群，请参阅[从快照还原到多可用区数据库集群](USER_RestoreFromMultiAZDBClusterSnapshot.Restoring.md)或[将多可用区数据库集群还原到指定时间](USER_PIT.MultiAZDBCluster.md)。

   有关执行升级的详细信息，请参阅 [手动升级引擎版本](USER_UpgradeDBInstance.Upgrading.md#USER_UpgradeDBInstance.Upgrading.Manual)。

   请注意，在将版本 9.6 数据库升级到版本 10 时，PostgreSQL 10 在默认情况下启用并行查询。您可以将测试数据库上的 `max_parallel_workers_per_gather` 参数更改为 2，从而在升级*之前*测试并行度的影响。
**注意**  
 在 `default.postgresql10` 数据库参数组中，`max_parallel_workers_per_gather` 参数的默认值为 2。

   有关更多信息，请参阅 PostgreSQL 文档中的[并行查询](https://www.postgresql.org/docs/10/parallel-query.html)。要在版本 10 上禁用并行，请将 `max_parallel_workers_per_gather` 参数设置为 0。

   在主要版本升级期间，将暂时重命名 `public` 和 `template1` 数据库以及每个数据库中的 `public` 架构。这些对象显示在日志中，同时附加了它们的原始名称和随机字符串。附加该字符串的目的是，在主要版本升级期间保留自定义设置，例如，`locale` 和 `owner`。升级完成后，对象再次重命名为它们的原始名称。
**注意**  
在主要版本升级过程中，您无法为数据库实例或多可用区数据库集群执行时间点还原。Amazon RDS 执行升级之后，它会自动备份数据库。您可以通过执行时间点还原，还原到数据库自动备份完成之后、升级操作开始之前的时间。

1. **如果升级失败并出现预检查过程错误，请解决这些问题** – 在主要版本升级过程中，Amazon RDS for PostgreSQL 先运行预检查过程，以确定可能导致升级失败的任何问题。预检查过程检查实例上的所有数据库中的所有潜在的不兼容情况。

   如果预检查遇到问题，它将创建一个日志事件以指示升级预检查失败。对于所有数据库，预检查过程详细信息位于相应数据库的升级日志（名称为 `pg_upgrade_precheck.log`）中。Amazon RDS 在文件名中附加时间戳。有关查看日志的详细信息，请参阅 [监控 Amazon RDS 日志文件](USER_LogAccess.md)。

   如果只读副本升级在预检查时失败，则失败的只读副本上的复制将中断，并将该副本置于终止状态。删除该只读副本，并根据升级后的主数据库实例重新创建只读副本。

   解决预检查日志中确定的所有问题，然后重试主要版本升级。以下是一个预检查日志示例。

   ```
   ------------------------------------------------------------------------
   Upgrade could not be run on Wed Apr 4 18:30:52 2018
   -------------------------------------------------------------------------
   The instance could not be upgraded from 9.6.11 to 10.6 for the following reasons.
   Please take appropriate action on databases that have usage incompatible with the requested major engine version upgrade and try the upgrade again.
   
   * There are uncommitted prepared transactions. Please commit or rollback all prepared transactions.* One or more role names start with 'pg_'. Rename all role names that start with 'pg_'.
   
   * The following issues in the database 'my"million$"db' need to be corrected before upgrading:** The ["line","reg*"] data types are used in user tables. Remove all usage of these data types.
   ** The database name contains characters that are not supported by RDS for PostgreSQL. Rename the database.
   ** The database has extensions installed that are not supported on the target database version. Drop the following extensions from your database: ["tsearch2"].
   
   * The following issues in the database 'mydb' need to be corrected before upgrading:** The database has views or materialized views that depend on 'pg_stat_activity'. Drop the views.
   ```

1. **如果在升级数据库时只读副本升级失败，解决问题** – 将失败的只读副本置于 `incompatible-restore` 状态并终止数据库上的复制。删除该只读副本，并根据升级后的主数据库实例重新创建只读副本。
**注意**  
Amazon RDS 不会升级多可用区数据库集群的只读副本。如果您对多可用区数据库集群执行主要版本升级，则其只读副本的复制状态会更改为**终止**。

   只读副本升级可能会因以下原因而失败：
   + 即使等待了一段时间，也无法跟上主数据库实例。
   + 处于终端或不兼容的生命周期状态，如 storage-full、incompatible-restore 等。
   + 主数据库实例升级开始后，在只读副本上运行了单独的次要版本升级。
   + 只读副本实例使用了不兼容的参数。
   + 只读副本实例无法与主实例通信以同步数据文件夹。

1. **升级生产数据库** – 在成功完成试运行主要版本升级后，您就可以放心地升级生产数据库了。有关更多信息，请参阅 [手动升级引擎版本](USER_UpgradeDBInstance.Upgrading.md#USER_UpgradeDBInstance.Upgrading.Manual)。

1. 运行 `ANALYZE` 操作以刷新 `pg_statistic` 表。您应该为所有 PostgreSQL 数据库上的每个数据库执行此操作。在主要版本升级期间不会传输优化程序统计数据，因此您需要重新生成所有统计数据，避免出现性能问题。运行不带任何参数的命令，为当前数据库中的所有常规表生成统计数据，如下所示：

   ```
   ANALYZE VERBOSE;
   ```

   `VERBOSE` 标记为可选项，可用于显示进度。有关更多信息，请参阅 PostgreSQL 文档中的 [ANALYZE](https://www.postgresql.org/docs/10/sql-analyze.html)。

   在分析特定表而不是使用 ANALYZE VERBOSE 时，请对每个表运行 ANALYZE 命令，如下所示：

   ```
   ANALYZE table_name;
   ```

   对于分区表，请始终分析父表。此过程：
   + 自动对所有分区中的行进行采样
   + 以递归方式更新每个分区的统计数据
   + 在父级维护基本的规划统计数据

   尽管父表不存储任何实际数据，但分析父表对于查询优化至关重要。仅对各个分区运行 ANALYZE 会导致查询性能不佳，因为优化器不具备进行高效跨分区规划所需的全面统计数据。
**注意**  
升级后在系统上运行 ANALYZE，避免出现性能问题。

在完成主要版本升级后，我们建议执行以下操作：
+ PostgreSQL 升级不会升级任何 PostgreSQL 扩展。要升级扩展，请参阅[在 RDS for PostgreSQL 数据库中升级 PostgreSQL 扩展](USER_UpgradeDBInstance.PostgreSQL.ExtensionUpgrades.md)。
+ （可选）使用 Amazon RDS 查看 `pg_upgrade` 实用程序生成的两个日志。它们是 `pg_upgrade_internal.log` 和 `pg_upgrade_server.log`。Amazon RDS 会在这些日志的文件名中附加时间戳。您可以像查看其他任何日志一样查看这些日志。有关更多信息，请参阅“[监控 Amazon RDS 日志文件](USER_LogAccess.md)”。

  您也可以将升级日志上传到 Amazon CloudWatch Logs 中。有关更多信息，请参阅“[将 PostgreSQL 日志发布到 Amazon CloudWatch Logs](USER_LogAccess.Concepts.PostgreSQL.md#USER_LogAccess.Concepts.PostgreSQL.PublishtoCloudWatchLogs)”。
+ 要验证是否一切正常，请在升级的数据库上使用类似的工作负载测试应用程序。验证升级之后，您可以删除此测试实例。

# RDS for PostgreSQL 的自动次要版本升级
<a name="USER_UpgradeDBInstance.PostgreSQL.Minor"></a>

如果在创建或修改数据库实例或多可用区数据库集群时启用**自动次要版本升级**选项，您可以自动升级数据库。

Amazon RDS 还支持升级推出策略，以管理跨多个数据库资源和 AWS 账户的自动次要版本升级。有关更多信息，请参阅 [使用 AWS Organizations 升级推出策略自动升级次要版本](RDS.Maintenance.AMVU.UpgradeRollout.md)。

对于每个 RDS for PostgreSQL 主要版本，RDS 将一个次要版本指定为自动升级版本。在 Amazon RDS 测试并批准次要版本后，将在维护时段内自动进行次要版本升级。RDS 不会自动将发布的较新次要版本设置为自动升级版本。在 RDS 指定较新的自动升级版本之前，将会考虑一些条件，例如：
+ 已知的安全问题
+ PostgreSQL 社区版本中的错误
+ 发布次要版本后的整体队列稳定性

您可以使用以下 AWS CLI 命令确定特定 AWS 区域中指定 PostgreSQL 次要版本的当前自动次要升级目标版本。

对于 Linux、macOS 或 Unix：

```
aws rds describe-db-engine-versions \
--engine postgres \
--engine-version minor-version \
--region region \
--query "DBEngineVersions[*].ValidUpgradeTarget[*].{AutoUpgrade:AutoUpgrade,EngineVersion:EngineVersion}" \
--output text
```

对于：Windows

```
aws rds describe-db-engine-versions ^
--engine postgres ^
--engine-version minor-version ^
--region region ^
--query "DBEngineVersions[*].ValidUpgradeTarget[*].{AutoUpgrade:AutoUpgrade,EngineVersion:EngineVersion}" ^
--output text
```

例如，以下 AWS CLI 命令可确定美国东部（俄亥俄州）AWS 区域（us-east-2）中 PostgreSQL 次要版本 16.1 的自动次要升级目标。

对于 Linux、macOS 或 Unix：

```
aws rds describe-db-engine-versions \
--engine postgres \
--engine-version 16.1 \
--region us-east-2 \
--query "DBEngineVersions[*].ValidUpgradeTarget[*].{AutoUpgrade:AutoUpgrade,EngineVersion:EngineVersion}" \
--output table
```

对于：Windows

```
aws rds describe-db-engine-versions ^
--engine postgres ^
--engine-version 16.1 ^
--region us-east-2 ^
--query "DBEngineVersions[*].ValidUpgradeTarget[*].{AutoUpgrade:AutoUpgrade,EngineVersion:EngineVersion}" ^
--output table
```

输出类似于以下内容。

```
----------------------------------
|    DescribeDBEngineVersions    |
+--------------+-----------------+
|  AutoUpgrade |  EngineVersion  |
+--------------+-----------------+
|  False       |  16.2           |
|  True       |  16.3          |
|  False       |  16.4           |
|  False       |  16.5           |
|  False       |  16.6           |
|  False       |  17.1           |
|  False       |  17.2           |
+--------------+-----------------+
```

在此示例中，`AutoUpgrade` 值对于 PostgreSQL 版本 16.3 为 `True`。因此，自动次要升级目标是 PostgreSQL 版本 16.3，它在输出中突出显示。

如果满足以下条件，则会在维护时段内自动升级 PostgreSQL 数据库：
+ 数据库启用了**自动次要版本升级**选项。
+ 数据库运行的次要数据库引擎版本低于当前的自动升级次要版本。

有关更多信息，请参阅 [自动升级次要引擎版本](USER_UpgradeDBInstance.Upgrading.md#USER_UpgradeDBInstance.Upgrading.AutoMinorVersionUpgrades)。

**注意**  
PostgreSQL 升级不会升级 PostgreSQL 扩展。要升级扩展，请参阅[在 RDS for PostgreSQL 数据库中升级 PostgreSQL 扩展](USER_UpgradeDBInstance.PostgreSQL.ExtensionUpgrades.md)。

# 在 RDS for PostgreSQL 数据库中升级 PostgreSQL 扩展
<a name="USER_UpgradeDBInstance.PostgreSQL.ExtensionUpgrades"></a>

PostgreSQL 引擎升级不会升级大多数的 PostgreSQL 扩展。要在版本升级后更新扩展，请使用 `ALTER EXTENSION UPDATE` 命令。

**注意**  
有关更新 PostGIS 扩展的信息，请参阅[使用 PostGIS 扩展管理空间数据](Appendix.PostgreSQL.CommonDBATasks.PostGIS.md)（[步骤 6：升级 PostGIS 扩展](Appendix.PostgreSQL.CommonDBATasks.PostGIS.md#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Update)）。  
要升级 `pg_repack` 扩展，先删除该扩展，然后在升级后的数据库中创建新版本。有关更多信息，请参阅 `pg_repack` 文档中的[安装 pg\$1repack](https://reorg.github.io/pg_repack/)。

要升级扩展，请使用以下命令。

```
ALTER EXTENSION extension_name UPDATE TO 'new_version';
```

有关受支持的 PostgreSQL 扩展版本列表，请参阅 [支持的 PostgreSQL 扩展版本](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md)。

要列出当前安装的扩展，请在以下命令中使用 PostgreSQL [pg\$1extension](https://www.postgresql.org/docs/current/catalog-pg-extension.html) 目录。

```
SELECT * FROM pg_extension;
```

要查看可用于安装的特定扩展版本的列表，请在以下命令中使用 PostgreSQL [pg\$1available\$1extension\$1versions](https://www.postgresql.org/docs/current/view-pg-available-extension-versions.html) 视图。

```
SELECT * FROM pg_available_extension_versions;
```

# 使用事件监控 RDS for PostgreSQL 引擎升级
<a name="USER_UpgradeDBInstance.PostgreSQL.Monitoring"></a>

在升级 RDS for PostgreSQL 数据库的引擎版本时，Amazon RDS 在流程的每个阶段都会发出一个特定的事件。要跟踪升级进度，您可以查看或订阅这些事件。

 有关 RDS 事件的更多信息，请参阅[监控 Amazon RDS 事件](working-with-events.md)。

有关引擎升级期间发生的特定 Amazon RDS 事件的详细信息，请参阅[Amazon RDS 事件类别和事件消息](USER_Events.Messages.md)。

# 升级 PostgreSQL 数据库快照引擎版本
<a name="USER_UpgradeDBSnapshot.PostgreSQL"></a>

借助 Amazon RDS，您可以为 PostgreSQL 数据库实例创建存储卷数据库快照。数据库快照是根据您的 Amazon RDS 实例使用的引擎版本创建的。您可以升级数据库快照的引擎版本。

将升级到新引擎版本的数据库快照还原后，请确保测试升级是否成功。有关主要版本升级的更多信息，请参阅[升级 RDS for PostgreSQL 数据库引擎](USER_UpgradeDBInstance.PostgreSQL.md)。要了解如何还原数据库快照，请参阅 [还原到数据库实例](USER_RestoreFromSnapshot.md)。

您可以升级已加密或未加密的手动数据库快照。

要查看 RDS for PostgreSQL 数据库快照的可用引擎版本，请使用以下 AWS CLI 示例。

```
aws rds describe-db-engine-versions --engine postgres  --engine-version example-engine-version --query "DBEngineVersions[*].ValidUpgradeTarget[*].{EngineVersion:EngineVersion}" --output text --include-all
```

有关 RDS for PostgreSQL 数据库快照的可用引擎版本的更多信息，请参阅[为 RDS for PostgreSQL 升级选择主要版本](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.md)。

**注意**  
您不能升级在自动备份过程中创建的自动数据库快照。

## 控制台
<a name="USER_UpgradeDBSnapshot.PostgreSQL.Console"></a>

**升级数据库快照**

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

1. 在导航窗格中，选择**快照**。

1. 选择要升级的快照。

1. 对于 **Actions (操作)**，选择 **Upgrade snapshot (升级快照)**。此时会显示 **Upgrade snapshot (升级快照)** 页面。

1. 选择要升级到的 **New engine version (新引擎版本)**。

1. 选择 **Save changes (保存更改)** 以升级快照。

   在升级过程中，将为此数据库快照禁用所有快照操作。此外，数据库快照状态由 **available** 变为 **upgrading**，完成后变为 **active**。如果由于快照损坏导致数据库快照不能升级，状态将变为 **unavailable**。此状态的快照无法恢复。
**注意**  
如果数据库快照升级失败，则快照将回滚到具有原始版本的原始状态。

## AWS CLI
<a name="USER_UpgradeDBSnapshot.PostgreSQL.CLI"></a>

要将数据库快照升级到新的数据库引擎版本，请使用 AWS CLI [modify-db-snapshot](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-snapshot.html) 命令。

**参数**
+ `--db-snapshot-identifier` – 要升级的数据库快照的标识符。标识符必须是唯一的 Amazon 资源名称 (ARN)。有关更多信息，请参阅“[Amazon RDS 中的 Amazon 资源名称（ARN）](USER_Tagging.ARN.md)”。
+ `--engine-version` – 升级后的数据库快照的引擎版本。

**Example**  
对于 Linux、macOS 或 Unix：  

```
1. aws rds modify-db-snapshot \
2.     --db-snapshot-identifier my_db_snapshot \
3.     --engine-version new_version
```
对于：Windows  

```
1. aws rds modify-db-snapshot ^
2.     --db-snapshot-identifier my_db_snapshot ^
3.     --engine-version new_version
```

## RDS API
<a name="USER_UpgradeDBSnapshot.PostgreSQL.API"></a>

要将数据库快照升级到新的数据库引擎版本，请调用 Amazon RDS API [ ModifyDBSnapshot](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBSnapshot.html) 操作。
+ `DBSnapshotIdentifier` – 要升级的数据库快照的标识符。标识符必须是唯一的 Amazon 资源名称 (ARN)。有关更多信息，请参阅“[Amazon RDS 中的 Amazon 资源名称（ARN）](USER_Tagging.ARN.md)”。
+ `EngineVersion` – 升级后的数据库快照的引擎版本。

# 使用 Amazon RDS for PostgreSQL 只读副本
<a name="USER_PostgreSQL.Replication.ReadReplicas"></a>

您可以通过向实例添加只读副本来扩展 Amazon RDS for PostgreSQL 数据库实例的读取。与其它 Amazon RDS 数据库引擎一样，RDS for PostgreSQL 使用 PostgreSQL 的原生复制机制来使只读副本与对源数据库的更改保持同步。有关只读副本和 Amazon RDS 的一般信息，请参阅[使用数据库实例只读副本](USER_ReadRepl.md)。

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



## PostgreSQL 只读副本限制
<a name="USER_PostgreSQL.Replication.ReadReplicas.Limitations"></a>

以下是 PostgreSQL 只读副本的限制：
+ PostgreSQL 只读副本是只读的。尽管只读副本不是可写的数据库实例，但您可以将其升级为独立的 RDS for PostgreSQL 数据库实例。不过该过程无法撤消。
+ 如果 RDS for PostgreSQL 数据库实例运行的是 14.1 之前的 PostgreSQL 版本，则无法从另一个只读副本创建只读副本。RDS for PostgreSQL 仅支持在 RDS for PostgreSQL 版本 14.1 版及更高版本上级联只读副本。有关更多信息，请参阅 [将级联只读副本用于 RDS for PostgreSQL](USER_PostgreSQL.Replication.ReadReplicas.Cascading.md)。
+ 如果您升级 PostgreSQL 只读副本，它将成为可写的数据库实例。它停止从源数据库实例接收预写日志（WAL）文件，并且已不再是只读实例。您可以像对任何 RDS for PostgreSQL 数据库实例一样从升级的数据库实例创建新只读副本。有关更多信息，请参阅 [将只读副本提升为独立的数据库实例](USER_ReadRepl.Promote.md)。
+ 如果您从复制链（一系列级联只读副本）中提升 PostgreSQL 只读副本，则任何现有的下游只读副本将继续自动从提升后的实例接收 WAL 文件。有关更多信息，请参阅 [将级联只读副本用于 RDS for PostgreSQL](USER_PostgreSQL.Replication.ReadReplicas.Cascading.md)。
+ 如果源数据库实例上没有运行任何用户事务，则关联的 PostgreSQL 只读副本会报告长达五分钟的复制滞后。副本滞后的计算公式为 `currentTime - lastCommitedTransactionTimestamp`，这意味着，当未处理任何事务时，副本滞后值会在一段时间内增加，直到预写日志（WAL）分段切换。默认情况下，RDS for PostgreSQL 每 5 分钟切换一次 WAL 分段，这会导致事务记录以及报告的滞后减少。
+ 您无法为早于 14.1 的 RDS for PostgreSQL 版本的 PostgreSQL 只读副本启用自动备份。仅 RDS for PostgreSQL 14.1 及更高版本支持只读副本的自动备份。对于 RDS for PostgreSQL 13 和更早版本，如果需要只读副本的备份，请从只读副本创建快照。
+ 只读副本不支持时间点故障恢复（PITR）。您只能将 PITR 用于主（写入器）实例，而不能用于只读副本。要了解更多信息，请参阅[将 Amazon RDS 的数据库实例还原到指定时间](USER_PIT.md)。
+ 对于 PostgreSQL 版本 12 及更低版本，只读副本会在 60-90 天的维护时段内自动重启以应用密码轮换。如果在安排的重启之前，副本失去了与源的连接，则实例仍将重启以继续复制。对于 PostgreSQL 版本 13 及更高版本，在密码轮换过程中，只读副本可能会出现短暂的复制断开连接和重新连接的情况。

# PostgreSQL 只读副本配置
<a name="USER_PostgreSQL.Replication.ReadReplicas.Configuration"></a>

RDS for PostgreSQL 使用 PostgreSQL 本机流式复制来创建源数据库实例的只读副本。此只读副本数据库实例是源数据库实例的异步创建的物理副本。该副本是通过在源数据库实例和只读副本之间传输预写日志（WAL）数据的特殊连接创建。有关更多信息，请参阅 PostgreSQL 文档中的[流式复制](https://www.postgresql.org/docs/14/warm-standby.html#STREAMING-REPLICATION)。

在源数据库实例上进行更改时，PostgreSQL 会通过此安全连接异步流式传输数据库更改。您可以通过将 `ssl` 参数设置为 `1`，来加密从客户端应用程序到源数据库实例或任何只读副本的通信。有关更多信息，请参阅 [将 SSL 与 PostgreSQL 数据库实例结合使用](PostgreSQL.Concepts.General.SSL.md)。

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

您可以在不影响源数据库实例的操作或用户的情况下创建 PostgreSQL 只读副本。Amazon RDS 为您在源数据库实例和只读副本上设置必要的参数和权限，而不会影响服务。为源数据库实例拍摄快照，该快照用于创建只读副本。如果您在将来某个时间点删除只读副本，则不会发生中断。

您可以从同一区域内的一个源数据库实例创建最多 15 个只读副本。自 RDS for PostgreSQL 14.1 起，您还可以从源数据库实例在链（级联）中创建最多三个级别的只读副本。有关更多信息，请参阅 [将级联只读副本用于 RDS for PostgreSQL](USER_PostgreSQL.Replication.ReadReplicas.Cascading.md)。在所有情况下，源数据库实例都需要配置自动备份。为此，您可以将数据库实例上的备份保留期设置为非 0 值。有关更多信息，请参阅 [创建只读副本](USER_ReadRepl.Create.md)。

您可以在与源数据库实例相同的 AWS 区域中为您的 RDS for PostgreSQL 数据库实例创建只读副本。这称为*区域内*复制。您还可以在与源数据库实例不同的 AWS 区域中创建只读副本。这称为*跨区域*复制。有关设置跨区域只读副本的更多信息，请参阅[在不同的 中创建只读副本AWS 区域](USER_ReadRepl.XRgn.md)。根据 RDS for PostgreSQL 版本，支持区域内和跨区域复制过程的各种机制略有不同，如[流式复制如何适用于不同的 RDS for PostgreSQL 版本](USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.md)中所述。

为了有效地进行复制，每个只读副本具有的计算和存储资源的量应与源数据库实例的一样多。如果扩展源数据库实例，则还应确保扩展只读副本。

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

RDS for PostgreSQL 只读副本可以访问通过源数据库实例上的外部数据包装器（FDW）提供的外部数据库。例如，假设您的 RDS for PostgreSQL 数据库实例使用 `mysql_fdw` 包装器从 RDS for MySQL 访问数据。如果是这样，只读副本也可以访问该数据。其他支持的 FDW 包括 `oracle_fdw`、`postgres_fdw` 和 `tds_fdw`。有关更多信息，请参阅 [使用 Amazon RDS for PostgreSQL 支持的外部数据包装器](Appendix.PostgreSQL.CommonDBATasks.Extensions.foreign-data-wrappers.md)。

## 将 RDS for PostgreSQL 只读副本用于多可用区配置
<a name="USER_PostgreSQL.Replication.ReadReplicas.Configuration.multi-az"></a>

您可从单可用区或多可用区数据库实例中创建只读副本。您可以借助备用副本，使用多可用区部署提高关键数据的持久性和可用性。*备用副本*是专用的只读副本，可以在源数据库发生故障转移时承担工作负载。您不能使用备用副本来提供读取流量。但是，可以从大流量、多可用区数据库实例创建只读副本以分流只读查询的负载。要了解关于多可用区部署的更多信息，请参阅 [Amazon RDS 的多可用区数据库实例部署](Concepts.MultiAZSingleStandby.md)。

如果多可用区部署的源数据库实例故障转移到备用可用区，则关联的只读副本将切换为使用备用可用区（现在为主可用区）作为其复制源。只读副本可能需要重新启动，具体取决于 RDS for PostgreSQL 版本，如下所示：
+ **PostgreSQL 13 及更高版本** – 不需要重新启动。只读副本将自动与新的主副本同步。但是，在某些情况下，您的客户端应用程序可能会缓存只读副本的域名服务（DNS）详细信息。如果是这样，请将生存时间（TTL）值设置为小于 30 秒。这样做可以防止只读副本继续留在陈旧的 IP 地址（因此可以防止它与新的主副本同步）。要了解有关此用法和其他最佳实践的更多信息，请参阅[Amazon RDS 基本操作指导方针](CHAP_BestPractices.md#CHAP_BestPractices.DiskPerformance)。
+ **PostgreSQL 12 和所有早期版本** – 只读副本在故障转移到备用副本后自动重新启动，因为备用副本（现为主）具有不同的 IP 地址和不同的实例名称。重启操作会将只读副本与新的主副本同步。

要详细了解失效转移，请参阅[对 Amazon RDS 的多可用区数据库实例执行失效转移](Concepts.MultiAZ.Failover.md)。要了解关于只读副本如何在多可用区部署中工作的更多信息，请参阅 [使用数据库实例只读副本](USER_ReadRepl.md)。

要为只读副本提供失效转移支持，您可以将只读副本创建为多可用区数据库实例，以便 Amazon RDS 在另一个可用区（AZ）中创建备用副本。创建您的只读副本作为多可用区数据库实例与源数据库是否为多可用区数据库实例无关。

# 只读副本上的逻辑解码
<a name="USER_PostgreSQL.Replication.ReadReplicas.LogicalDecoding"></a>

 RDS for PostgreSQL 支持使用 PostgreSQL 16.1 从备用数据库实例进行逻辑复制。这允许您从只读备用数据库实例创建逻辑解码，从而减少主数据库实例上的负载。对于需要在多个系统之间同步数据的应用程序，您可以实现更高的可用性。此功能可提高数据仓库和数据分析的性能。

 此外，给定备用数据库实例上的复制插槽会持续将该备用数据库实例提升为主数据库实例。这意味着，如果主数据库实例发生失效转移或将备用数据库实例提升为新的主数据库实例，则复制插槽将持续存在，以前的备用数据库实例订阅用户不会受到影响。

**在只读副本上创建逻辑解码**

1. **开启逻辑复制** - 要在备用数据库实例上创建逻辑解码，您必须在源数据库实例及其物理副本上启用逻辑复制。有关更多信息，请参阅 [PostgreSQL 只读副本配置](USER_PostgreSQL.Replication.ReadReplicas.Configuration.md)。
   + **为新创建的 RDS for PostgreSQL 数据库实例启用逻辑复制** – 创建新的数据库自定义参数组，并将静态参数 `rds.logical_replication` 设置为 `1`。然后，将此数据库参数组与源数据库实例及其物理只读副本相关联。有关更多信息，请参阅 [在 Amazon RDS 中将数据库参数组与数据库实例关联](USER_WorkingWithParamGroups.Associating.md)。
   + **为现有 RDS for PostgreSQL 数据库实例开启逻辑复制** – 修改源数据库实例及其物理只读副本的数据库自定义参数组，以将静态参数 `rds.logical_replication` 设置为 `1`。有关更多信息，请参阅 [在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。
**注意**  
必须重启数据库实例才能应用这些参数更改。

   您可以使用以下查询来验证源数据库实例及其物理只读副本上的 `wal_level` 和 `rds.logical_replication` 值。

   ```
   Postgres=>SELECT name,setting FROM pg_settings WHERE name IN ('wal_level','rds.logical_replication');
               
    name                    | setting 
   -------------------------+---------
    rds.logical_replication | on
    wal_level               | logical
   (2 rows)
   ```

1. **在源数据库中创建表** – 连接到源数据库实例中的数据库。有关更多信息，请参阅 [连接到运行 PostgreSQL 数据库引擎的数据库实例](USER_ConnectToPostgreSQLInstance.md)。

   使用以下查询在源数据库中创建表并插入值：

   ```
   Postgres=>CREATE TABLE LR_test (a int PRIMARY KEY);
   CREATE TABLE
   ```

   ```
   Postgres=>INSERT INTO LR_test VALUES (generate_series(1,10000));
   INSERT 0 10000
   ```

1. **为源表创建发布** - 使用以下查询为源数据库实例上的表创建发布。

   ```
   Postgres=>CREATE PUBLICATION testpub FOR TABLE LR_test;
   CREATE PUBLICATION
   ```

   使用 SELECT 查询来验证在源数据库实例和物理只读副本实例上创建的发布的详细信息。

   ```
   Postgres=>SELECT * from pg_publication;
                
   oid    | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate | pubviaroot 
   -------+---------+----------+--------------+-----------+-----------+-----------+-------------+------------
    16429 | testpub |    16413 | f            | t         | t         | t         | t           | f
   (1 row)
   ```

1. **从逻辑副本实例创建订阅** – 创建另一个 RDS for PostgreSQL 数据库实例作为逻辑副本实例。确保 VPC 设置正确，以确保此逻辑副本实例可以访问物理只读副本实例。有关更多信息，请参阅 [Amazon VPC 和 Amazon RDS](USER_VPC.md)。如果您的源数据库实例处于空闲状态，则可能会出现连接问题，并且主数据库实例不会将数据发送到备用数据库实例。

   ```
   Postgres=>CREATE SUBSCRIPTION testsub CONNECTION 'host=Physical replica host name port=port 
                   dbname=source_db_name user=user password=password' PUBLICATION testpub;
   NOTICE:  created replication slot "testsub" on publisher
   CREATE SUBSCRIPTION
   ```

   ```
   Postgres=>CREATE TABLE LR_test (a int PRIMARY KEY);
   CREATE TABLE
   ```

   使用 SELECT 查询来验证逻辑副本实例上的订阅详细信息。

   ```
   Postgres=>SELECT oid,subname,subenabled,subslotname,subpublications FROM pg_subscription;
               
   oid    | subname | subenabled | subslotname | subpublications 
   -------+---------+------------+-------------+-----------------
    16429 | testsub | t          | testsub     | {testpub}
   (1 row)
   postgres=> select count(*) from LR_test;
    count 
   -------
    10000
   (1 row)
   ```

1. **检查逻辑复制插槽状态** - 您只能看到源数据库实例上的物理复制插槽。

   ```
   Postgres=>select slot_name, slot_type, confirmed_flush_lsn from pg_replication_slots;
               
   slot_name                                    | slot_type | confirmed_flush_lsn 
   ---------------------------------------------+-----------+---------------------
    rds_us_west_2_db_dhqfsmo5wbbjqrn3m6b6ivdhu4 | physical  | 
   (1 row)
   ```

   但是，在您的只读副本实例上，您可以看到逻辑复制插槽和 `confirmed_flush_lsn` 值会随着应用程序主动使用逻辑更改而发生变化。

   ```
   Postgres=>select slot_name, slot_type, confirmed_flush_lsn from pg_replication_slots;
               
   slot_name | slot_type | confirmed_flush_lsn 
   -----------+-----------+---------------------
    testsub   | logical   | 0/500002F0
   (1 row)
   ```

   ```
   Postgres=>select slot_name, slot_type, confirmed_flush_lsn from pg_replication_slots;
               
   slot_name | slot_type | confirmed_flush_lsn 
   -----------+-----------+---------------------
    testsub   | logical   | 0/5413F5C0
   (1 row)
   ```

# 将级联只读副本用于 RDS for PostgreSQL
<a name="USER_PostgreSQL.Replication.ReadReplicas.Cascading"></a>

自版本 14.1 开始，RDS for PostgreSQL 支持级联只读副本。使用*级联只读副本*，您可以扩展读取操作，而不会增加源 RDS for PostgreSQL 数据库实例的开销。源数据库实例不会将 WAL 日志的更新发送到每个只读副本。相反，级联系列中的每个只读副本都将 WAL 日志更新发送到该系列中的下一个只读副本。这将减轻源数据库实例的负担。

使用级联只读副本，您的 RDS for PostgreSQL 数据库实例会将 WAL 数据发送到链中的第一个只读副本。然后，该只读副本将 WAL 数据发送到链中的第二个副本，依此类推。最终结果是，链中的所有只读副本都具有 RDS for PostgreSQL 数据库实例中的更改，但不会只在源数据库实例上产生开销。

您可以从源 RDS for PostgreSQL 数据库实例在链中创建最多三个只读副本。例如，假设您具有 RDS for PostgreSQL 14.1 数据库实例 `rpg-db-main`。您可执行以下操作：
+ 从 `rpg-db-main` 开始，创建链中的第一个只读副本 `read-replica-1`。
+ 接下来，从 `read-replica-1`，创建链中的下一个只读副本 `read-replica-2`。
+ 最后，从 `read-replica-2`，创建链中的第三个只读副本 `read-replica-3`。

除了 `rpg-db-main` 系列中的第三个级联只读副本之外，您无法创建另一个只读副本。从 RDS for PostgreSQL 源数据库实例到一系列级联只读副本末尾的完整实例系列最多可以包含四个数据库实例。

要使级联只读副本正常工作，请在 RDS for PostgreSQL 上启用自动备份。首先创建只读副本，然后在 RDS for PostgreSQL 数据库实例上启用自动备份。此过程与其他 Amazon RDS 数据库引擎相同。有关更多信息，请参阅 [创建只读副本](USER_ReadRepl.Create.md)。

与任何只读副本一样，您可以升级属于级联一部分的只读副本。从只读副本链中升级只读副本将从链中移除该副本。例如，假设您希望将一些工作负载从 `rpg-db-main` 数据库实例转移到新实例，以便仅供会计部门使用。假设该示例中的链有三个只读副本，您决定升级 `read-replica-2`。该链受到如下影响：
+ 升级 `read-replica-2` 会将其从复制链中移除。
  + 现在它是一个完全读/写数据库实例。
  + 它继续复制到 `read-replica-3`，就像在升级之前那样。
+ 您的 `rpg-db-main` 继续复制到 `read-replica-1`。

有关升级只读副本的更多信息，请参阅[将只读副本提升为独立的数据库实例](USER_ReadRepl.Promote.md)。

**注意**  
RDS for PostgreSQL 不支持对级联副本进行主要版本升级。在执行主要版本升级之前，您需要删除级联副本。在完成对源数据库实例和一级副本的升级后，可以重新创建这些副本。
对于级联只读副本，RDS for PostgreSQL 在第一复制级别为每个源数据库实例支持 15 个只读副本，在第二和第三复制级别为每个源数据库实例支持 5 个只读副本。

# 使用 RDS for PostgreSQL 创建跨区域级联只读副本
<a name="USER_PostgreSQL.Replication.ReadReplicas.Xregion"></a>

RDS for PostgreSQL 支持跨区域级联只读副本。您可以从源数据库实例创建跨区域副本，然后从该实例创建同区域副本。您也可以从源数据库实例创建同区域副本，然后从该实例创建跨区域副本。

**创建跨区域副本，然后创建同区域副本**

您可以使用版本 14.1 或更高版本的 RDS for PostgreSQL 数据库实例 `rpg-db-main` 执行以下操作：

1. 从 `rpg-db-main`（US-EAST-1）开始，在链中创建第一个跨区域只读副本 `read-replica-1`（US-WEST-2）。

1. 使用第一个跨区域 `read-replica-1`（US-WEST-2），在链中创建第二个只读副本 `read-replica-2`（US-WEST-2）。

1. 使用 `read-replica-2` 在链中创建第三个只读副本 `read-replica-3`（US-WEST-2）。

**创建同区域副本，然后创建跨区域副本**

您可以使用版本 14.1 或更高版本的 RDS for PostgreSQL 数据库实例 `rpg-db-main` 执行以下操作：

1. 从 `rpg-db-main`（US-EAST-1）开始，在链中创建第一个只读副本 `read-replica-1`（US-EAST-1）。

1. 使用 `read-replica-1`（US-EAST-1），在链中创建第一个跨区域只读副本 `read-replica-2`（US-WEST-2）。

1. 使用 `read-replica-2` (US-WEST-2) 在链中创建第三个只读副本 `read-replica-3`（US-WEST-2）。

**有关创建跨区域只读副本的限制**
+ 数据库副本的跨区域级联链最多可跨两个区域以及包含四个级别。这四个级别包括数据库源和三个只读副本。

**使用级联只读副本所带来的好处**
+ 提高了读取可扩展性：通过将读取查询分布到多个副本，级联复制有助于实现负载平衡。这将减轻写入器数据库的压力，从而提高性能，尤其是在读取密集型应用程序中。
+ 地理分布；级联副本可位于不同的地理位置。这将减少远离主数据库的用户的延迟，并提供本地只读副本，从而提升性能和用户体验。
+ 高可用性和灾难恢复：如果主服务器发生故障，可以将副本提升为主服务器，从而确保连续性。级联复制可提供多层失效转移选项来进一步增强此能力，从而提高系统的整体韧性。
+ 灵活性和模块化增长：着系统规模的增长，可以在不同的级别添加新副本，而无需对主数据库进行重大重新配置。此模块化方法可实现复制设置的可扩展且可管理的增长。

**使用跨区域只读副本的最佳实践**
+ 在提升一个副本之前，请创建其他副本。这既能节省时间，又能有效处理工作负载。

# 流式复制如何适用于不同的 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.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  | 
| PostgreSQL 13 及更低版本 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_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\$1wal\$1senders**  
`max_wal_senders` 参数指定源数据库实例可以通过流式复制协议同时支持的最大连接数。  
默认值因 RDS for PostgreSQL 版本而各不相同：  
+ 对于版本 13、14 和 15，默认值为 20。
+ 对于版本 16 及更高版本，默认值为 35。
此参数应设置为略高于实际只读副本数量。如果此参数设置为对只读副本数来说太少，则复制将停止。  
有关更多信息，请参阅 PostgreSQL 文档中的 [max\$1wal\$1senders](https://www.postgresql.org/docs/devel/runtime-config-replication.html#GUC-MAX-WAL-SENDERS)。  
`max_wal_senders` 是一个静态参数，要求重启数据库实例才能使更改生效。

**wal\$1keep\$1segments**  
`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\$1keep\$1segments](https://www.postgresql.org/docs/12/runtime-config-replication.html#GUC-WAL-KEEP-SEGMENTS) 和 [wal\$1keep\$1size](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-WAL-KEEP-SIZE)。

**max\$1slot\$1wal\$1keep\$1size**  
`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\$1slot\$1wal\$1keep\$1size](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>

在以下示例中，您可以找到演示只读副本恢复过程的日志详细信息。该示例来自与源数据库在同一 AWS 区域中运行 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\$1connections
+ max\$1worker\$1processes
+ max\$1wal\$1senders
+ max\$1prepared\$1transactions
+ max\$1locks\$1per\$1transaction

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

# 监控和调整复制过程
<a name="USER_PostgreSQL.Replication.ReadReplicas.Monitor"></a>

我们强烈建议您定期监控 RDS for PostgreSQL 数据库实例和只读副本。您需要确保只读副本与源数据库实例上的更改同步。当复制过程中断时，Amazon RDS 可以透明地恢复您的只读副本。但是，最好避免出现需要恢复的情况。使用复制槽进行恢复比使用 Amazon S3 归档快，但是任何恢复过程都可能会影响读取性能。

要确定只读副本与源数据库实例的同步程度，您可以执行以下操作：
+ **检查源数据库实例和副本之间的 `ReplicaLag` 数量。***副本滞后*是只读副本滞后于其源数据库实例的时间量（以秒为单位）。此指标将报告以下查询的结果。

  ```
  SELECT extract(epoch from now() - pg_last_xact_replay_timestamp()) AS "ReplicaLag";
  ```

  副本滞后可指示只读副本与源数据库实例的同步程度。这是源数据库实例和特定只读实例之间的延迟量。副本滞后值较高可能表示源数据库实例使用的数据库实例类或存储类型（或两者）与其只读副本之间不匹配。数据库源实例和所有只读副本的数据库实例类和存储类型应相同。

  副本滞后也可能是间歇性连接问题导致的。您可以通过查看 Amazon RDS `ReplicaLag` 指标，在 Amazon CloudWatch 中监控复制滞后。若要了解有关 `ReplicaLag` 和 Amazon RDS 的其他指标的更多信息，请参阅 [Amazon RDS 的 Amazon CloudWatch 指标](rds-metrics.md)。
+ **查看 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 不足以跟上流式传输活动的节奏，因此应增加此参数的值。
+ **使用 Amazon CloudWatch 监控可以预测复制问题的指标。**您可以使用 Amazon CloudWatch 检查已收集的指标，而不是直接分析 PostgreSQL 日志。例如，您可以检查 `TransactionLogsGeneration` 指标的值，以查看源数据库实例生成了多少 WAL 数据。某些情况下，数据库实例上的工作负载可能会生成大量 WAL 数据。如果是这样，您可能需要更改源数据库实例和只读副本的数据库实例类。使用具有高（10Gbps）网络性能的实例类可以减少副本滞后。

## 监控 RDS for PostgreSQL 数据库实例的复制槽
<a name="USER_PostgreSQL.Replication.ReadReplicas.Monitor-monitor-replication-slots"></a>

所有 RDS for PostgreSQL 版本都将复制槽用于跨区域只读副本。RDS for PostgreSQL 14.1 及更高版本将复制槽用于区域内只读副本。区域内只读副本还使用 Amazon S3 来归档 WAL 数据。换句话说，如果您的数据库实例和只读副本运行 PostgreSQL 14.1 或更高版本，则复制槽和 Amazon S3 归档都可用于恢复只读副本。使用复制槽恢复只读副本比从 Amazon S3 归档中恢复快。因此，我们建议您监控复制槽和相关指标。

您可以通过查询 `pg_replication_slots` 视图来查看 RDS for PostgreSQL 数据库实例上的复制槽，如下所示。

```
postgres=> SELECT * FROM pg_replication_slots;
slot_name                  | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size | two_phase
---------------------------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------+-----------
rds_us_west_1_db_555555555 |        | physical  |        |          | f         | t      |      13194 |      |              | 23/D8000060 |                     | reserved   |               | f
(1 row)
```

`reserved` 值 `wal_status` 表示插槽持有的 WAL 数据量在 `max_wal_size` 参数的范围内。换句话说，复制槽的大小正确。其他可能的状态值如下所示：
+ `extended` – 插槽超过了`max_wal_size`设置，但 WAL 数据会被保留。
+ `unreserved` – 插槽不再拥有所有必需的 WAL 数据。其中一些将在下一个检查点移除。
+ `lost` – 一些必需的 WAL 数据已删除。插槽不再可用。

`wal_status` 的 `unreserved` 和 `lost` 状态只有在 `max_slot_wal_keep_size` 为非负数时才会显示。

`pg_replication_slots` 视图显示了复制插槽的当前状态。要评估复制插槽的性能，您可以使用 Amazon CloudWatch 并监控以下指标：
+ **`OldestReplicationSlotLag`**：显示源上尚未被滞后程度最高的副本占用的预写日志（WAL）数据量。
+ **`TransactionLogsDiskUsage`**：显示 WAL 数据使用了多少存储空间。如果只读副本出现明显滞后，此指标的值可能会大幅增加。

若要了解将 Amazon CloudWatch 及其指标用于 RDS for PostgreSQL 的更多信息，请参阅 [使用 Amazon CloudWatch 监控 Amazon RDS 指标](monitoring-cloudwatch.md)。有关监控 RDS for PostgreSQL 数据库实例上的流复制的更多信息，请参阅 *AWS数据库博客*上的 [Amazon RDS PostgreSQL 复制的最佳实践](https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/)。

# 在 RDS for PostgreSQL 中配置延迟复制
<a name="rpg-delayed-replication"></a>

## 概述和优势
<a name="rpg-delayed-replication-overview"></a>

借助 RDS for PostgreSQL 中的延迟复制功能，您可以有意延迟将数据更改从主数据库复制到一个或多个备用（只读副本）服务器。这样可以有效防止数据损坏、意外数据丢失或错误事务，否则这些问题可能会立即传播到所有副本。

以下 RDS for PostgreSQL 版本支持延迟复制：
+ 14.19 及更高的 14 版本
+ 15.14 及更高的 15 版本
+ 16.10 及更高的 16 版本
+ 17.6 及更高的 17 版本

通过在复制过程中引入时间滞后，您可以获得一个时间窗口，在数据相关事件影响整个数据库集群之前进行检测和响应。延迟复制过程包括以下好处：
+ 允许您从意外删除、更新或其他逻辑错误中恢复。
+ 提供缓冲区，防止损坏的数据在数据库集群中扩散。
+ 提供额外的恢复点选项，以补充您的传统备份策略。
+ 允许您根据组织的特定需求和风险承受能力配置延迟时间。

## 启用和配置延迟复制
<a name="enabling-rpg-delayed-replication"></a>

要在 RDS for PostgreSQL 只读副本上启用延迟复制，请执行以下步骤：

**注意**  
对于级联只读副本，请使用下述相同的 `recovery_min_apply_delay` 参数和步骤。

**启用延迟复制**

1. 创建新的自定义参数组或修改现有的自定义参数组。有关更多信息，请参阅 [Amazon RDS 数据库实例的数据库参数组](USER_WorkingWithDBInstanceParamGroups.md)。

1. 在参数组中配置 `recovery_min_apply_delay` 参数：
   + 将该值设置为所需的延迟（以毫秒为单位）。例如，3600000 表示延迟 1 小时。
   + 允许的范围：0 到 86400000 毫秒（0 到 24 小时）
   + 默认：0

1. 将参数组应用于要为延迟复制配置的只读副本实例。

1. 要使更改生效，请重启只读副本实例。
**注意**  
`recovery_min_apply_delay` 参数是动态的。如果您修改已附加到实例的现有参数组，则更改无需重启即可立即生效。但是，将新参数组应用于实例时，必须重启才能使更改生效。

## 管理延迟复制恢复
<a name="managing-rpg-delayed-replication"></a>

在传统的时间点恢复方法可能不足或过于耗时的情况下，延迟复制特别有用。

在延迟复制期间，您可以使用以下 PostgreSQL 函数来管理恢复过程：
+ `pg_wal_replay_pause()`：请求暂停延迟副本的恢复过程。
+ `pg_wal_replay_resume()`：如果恢复过程之前已暂停，请重新启动该过程。
+ `pg_is_wal_replay_paused()`：检查恢复过程当前是否已暂停。
+ `pg_get_wal_replay_pause_state()`：获取恢复过程的当前状态（未暂停、未请求暂停或已暂停）。

具有 `rds_superuser` 角色的用户对 `pg_wal_replay_pause()` 和 `pg_wal_replay_resume()` 具有 EXECUTE 权限。如果其他数据库用户需要访问这些函数，则必须向他们授予 `rds_superuser` 角色。有关 `rds_superuser` 角色的更多信息，请参阅 [了解 rds\$1superuser 角色](Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser.md)。

访问其他函数（如 `pg_is_wal_replay_paused()`），`pg_get_wal_replay_pause_state()` 不需要 `rds_superuser` 角色。

您可以使用以下恢复目标参数精确控制延迟副本恢复到的时间点。这些参数是静态的，需要重新启动数据库才能应用更改：
+ recovery\$1target
+ recovery\$1target\$1lsn
+ recovery\$1target\$1name
+ recovery\$1target\$1time
+ recovery\$1target\$1xid
+ recovery\$1target\$1inclusive

**重要**  
一次只能指定一个恢复目标参数。在配置文件中配置多个恢复目标参数会导致错误。

## 规划注意事项
<a name="rpg-delayed-replication-considerations"></a>

在规划 RDS for PostgreSQL 延迟复制时，请考虑以下事项：
+ 在自动轮换 `rdsrepladmin` 凭证（每 90 天轮换一次）期间，延迟只读副本可能会暂时进入 `REPLICATION_ERROR` 状态。如果延迟副本有足够的 WAL 日志来维持配置的延迟，它可能会暂停 WAL 接收方进程，从而导致源端的 WAL 积累。您应监控副本的复制状态以及源端的存储使用情况，以避免存储空间不足。
+ 当延迟只读副本遇到系统事件（例如重启或重新启动）时，它们会进入 `REPLICATION_ERROR` 状态，即在配置的延迟期到期之前，WAL 接收方进程将一直保持非活动状态。此行为可能导致源实例上的 WAL 积累，从而可能导致存储空间耗尽。请考虑以下预防措施：
  + 配置 CloudWatch 警报以监控源实例的存储利用率。
  + 启用存储自动扩缩功能以处理意外的 WAL 增长。
  + 在源实例上设置 `max_slot_wal_keep_size` 参数以限制每个复制槽的 WAL 保留时间。
  + 定期监控复制滞后和插槽状态。
+ 较长的延迟会增加副本上的 WAL 日志，从而消耗更多的存储空间。使用 CloudWatch 警报监控存储空间，启用自动扩缩，或者在需要时追踪副本。
+ 提升延迟只读副本时，不支持 `recovery_min_apply_delay` 参数，并且会立即应用所有待处理的 WAL 记录。
+ `recovery_min_apply_delay` 参数独立于级联复制设置的每个级别。在副本上设置延迟不会增加任何级联副本的延迟。

有关更多信息，请参阅 [RDS for PostgreSQL 只读副本文档](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html)和 [RDS for PostgreSQL 灾难恢复文档](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Disaster-Recovery.html)。

## 理解限制
<a name="rpg-delayed-replication-limitations"></a>

Amazon RDS for PostgreSQL 的延迟复制功能有以下限制：
+ 配置延迟复制时，蓝绿部署具有以下限制：
  + **绿源实例** — 即使在参数组中进行了配置，也会忽略 `recovery_min_apply_delay parameter`。绿源实例上的任何延迟设置都不会生效。
  + **绿副本实例** — 完全支持 `recovery_min_apply_delay parameter` 并将其应用于 PostgreSQL 配置文件。在切换工作流程中，延迟设置可以按预期运行。
  + 主要版本升级的 RDS 蓝绿部署
+ 在主版本升级期间，所有延迟只读副本都将自动终止，以允许源实例继续升级过程，从而最大限度地减少停机时间。源实例完成升级后，您必须手动重新创建延迟副本。
+  延迟复制与以下功能不兼容。
  + RDS for PostgreSQL 逻辑复制
  + RDS for PostgreSQL 多可用区集群（包括入站和出站复制）
  + Aurora PostgreSQL

# RDS for PostgreSQL 只读副本故障排除
<a name="USER_PostgreSQL.Replication.ReadReplicas.Troubleshooting"></a>

下面，您可以找到一些常见 RDS for PostgreSQL 只读副本问题的故障排除思路。

**终止导致只读副本滞后的查询**  
在数据库中长时间运行的处于活动或空闲事务状态的事务可能会干扰 WAL 复制过程，从而增加复制滞后。因此，请务必使用 PostgreSQL `pg_stat_activity` 视图监控这些事务的运行时。  
在主实例上运行类似于以下内容的查询，来查找长时间运行的查询的进程 ID（PID）：  

```
SELECT datname, pid,usename, client_addr, backend_start,
xact_start, current_timestamp - xact_start AS xact_runtime, state,
backend_xmin FROM pg_stat_activity WHERE state='active';
```

```
SELECT now() - state_change as idle_in_transaction_duration, now() - xact_start as xact_duration,* 
FROM  pg_stat_activity 
WHERE state  = 'idle in transaction'
AND   xact_start is not null
ORDER BY 1 DESC;
```
确定查询的 PID 后，您可以选择结束此查询。  
在主实例上运行类似于以下内容的查询，来终止长时间运行的查询：  

```
SELECT pg_terminate_backend(PID);
```

# 使用 Amazon RDS 优化型读取功能提高 RDS for PostgreSQL 的查询性能
<a name="USER_PostgreSQL.optimizedreads"></a>

使用 Amazon RDS 优化型读取功能，您可以更快地处理 RDS for PostgreSQL 查询。与不使用 RDS 优化型读取功能的数据库实例或多可用区数据库集群相比，使用此功能的实例或集群可以实现最多快 50% 的查询处理速度。

**Topics**
+ [PostgreSQL 中的 RDS 优化型读取功能概述](#USER_PostgreSQL.optimizedreads-overview)
+ [RDS 优化读取的使用案例](#USER_PostgreSQL.optimizedreads-use-cases)
+ [RDS 优化读取的最佳实践](#USER_PostgreSQL.optimizedreads-best-practices)
+ [使用 RDS 优化读取](#USER_PostgreSQL.optimizedreads-using)
+ [监控使用 RDS 优化读取的数据库实例](#USER_PostgreSQL.optimizedreads-monitoring)
+ [PostgreSQL 中 RDS 优化型读取功能的限制](#USER_PostgreSQL.optimizedreads-limitations)

## PostgreSQL 中的 RDS 优化型读取功能概述
<a name="USER_PostgreSQL.optimizedreads-overview"></a>

默认情况下，在使用基于 NVMe 的数据库实例类时，RDS for PostgreSQL 版本 15.2 及更高版本、14.7 及更高版本以及 13.10 及更高版本上提供优化型读取功能。有关指示哪些实例使用 NVMe 的硬件规格，请参阅[数据库实例类的硬件规格](Concepts.DBInstanceClass.Summary.md)。

当您使用开启了 RDS 优化型读取功能的 RDS for PostgreSQL 数据库实例或多可用区数据库集群时，该实例或集群通过使用基于本地非易失性存储规范（NVMe）的固态硬盘（SSD）块级存储，可实现速度最多快 50% 的查询性能。您可以通过将 PostgreSQL 生成的临时表放置在本地存储上来实现更快的查询处理，这可减少通过网络流向 Elastic Block Storage（EBS）的流量。

在 PostgreSQL 中，临时对象分配给临时命名空间，该命名空间在会话结束时会自动删除。删除时的临时命名空间会删除任何依赖于会话的对象，包括模式限定的对象，例如表、函数、运算符甚至扩展。

在 RDS for PostgreSQL 中，为存储临时对象的这一临时工作区配置了 `temp_tablespaces` 参数。

以下查询返回表空间的名称及其位置。

```
postgres=> show temp_tablespaces;
temp_tablespaces
---------------------
rds_temp_tablespace
(1 row)
```

`rds_temp_tablespace` 是由 RDS 配置的指向 NVMe 本地存储的表空间。您可以随时切换回 Amazon EBS 存储，方法是使用 AWS 管理控制台修改 `Parameter group` 中的此参数以指向除 `rds_temp_tablespace` 之外的任何表空间。有关更多信息，请参阅 [在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。也可以使用 SET 命令在会话级别将 `temp_tablespaces` 参数的值修改为 `pg_default`。修改此参数会将临时工作区重定向到 Amazon EBS。当 RDS 实例或集群的本地存储空间不足以执行特定的 SQL 操作时，切换回 Amazon EBS 会有所帮助。

```
postgres=> SET temp_tablespaces TO 'pg_default';
SET
```

```
postgres=> show temp_tablespaces;
            
 temp_tablespaces
------------------
 pg_default
```

## RDS 优化读取的使用案例
<a name="USER_PostgreSQL.optimizedreads-use-cases"></a>

以下是一些可从优化型读取功能中受益的使用案例：
+ 包含公用表表达式（CTE）、派生表和分组操作的分析查询。
+ 用于处理应用程序的未优化型查询的只读副本。
+ 具有复杂操作（如 GROUP BY 和 ORDER BY）的按需或动态报告查询，这些操作无法始终使用适当的索引。
+ 使用内部临时表的其他工作负载。
+ 用于排序的 `CREATE INDEX` 或 `REINDEX` 操作。

## RDS 优化读取的最佳实践
<a name="USER_PostgreSQL.optimizedreads-best-practices"></a>

对于 RDS 优化读取使用以下最佳实践：
+ 为只读查询添加重试逻辑，以防它们在执行过程中由于实例存储已满而失败。
+ 使用 CloudWatch 指标 `FreeLocalStorage` 监控实例存储上的可用存储空间。如果由于数据库实例或多可用区数据库集群上的工作负载导致实例存储达到其限制，请修改此实例或集群以使用更大的数据库实例类。

## 使用 RDS 优化读取
<a name="USER_PostgreSQL.optimizedreads-using"></a>

当您在单可用区数据库实例部署、多可用区数据库实例部署或多可用区数据库集群部署中预调配具有基于 NVMe 的数据库实例类之一的 RDS for PostgreSQL 数据库实例时，该数据库实例会自动使用 RDS 优化型读取功能。

有关多可用区部署的更多信息，请参阅[配置和管理 Amazon RDS 的多可用区部署](Concepts.MultiAZ.md)。

要启用 RDS 优化读取，请执行以下操作之一：
+ 使用其中一个基于 NVMe 的数据库实例类创建 RDS for PostgreSQL 数据库实例或多可用区数据库集群。有关更多信息，请参阅 [创建 Amazon RDS 数据库实例](USER_CreateDBInstance.md)。
+ 修改现有 RDS for PostgreSQL 数据库实例或多可用区数据库集群，以使用其中一个基于 NVMe 的数据库实例类。有关更多信息，请参阅 [修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md)。

在支持其中一个或多个数据库实例类（具有本地 NVMe SSD 存储）的所有 AWS 区域中，均可使用 RDS 优化型读取功能。有关更多信息，请参阅 [数据库实例类](Concepts.DBInstanceClass.md)。

要切换回未优化读取功能的 RDS 实例，请将 RDS 实例或集群的数据库实例类修改为类似的实例类，该实例类对于数据库工作负载仅支持 EBS 存储。例如，如果当前数据库实例类是 db.r6gd.4xlarge，请选择 db.r6g.4xlarge 以切换回该实例类。有关更多信息，请参阅 [修改 Amazon RDS 数据库实例](Overview.DBInstance.Modifying.md)。

## 监控使用 RDS 优化读取的数据库实例
<a name="USER_PostgreSQL.optimizedreads-monitoring"></a>

您可以通过以下 CloudWatch 指标监控使用 RDS 优化型读取功能的数据库实例：
+ `FreeLocalStorage`
+ `ReadIOPSLocalStorage`
+ `ReadLatencyLocalStorage`
+ `ReadThroughputLocalStorage`
+ `WriteIOPSLocalStorage`
+ `WriteLatencyLocalStorage`
+ `WriteThroughputLocalStorage`

这些指标提供有关可用实例存储的存储空间、IOPS 和吞吐量的数据。有关这些指标的更多信息，请参阅 [Amazon RDS 的 Amazon CloudWatch 实例级指标](rds-metrics.md#rds-cw-metrics-instance)。

要监控本地存储的当前使用情况，请登录数据库并运行以下查询：

```
SELECT
    spcname AS "Name",
    pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS "size"
FROM
    pg_catalog.pg_tablespace
WHERE
    spcname IN ('rds_temp_tablespace');
```

有关临时文件及其用法的更多信息，请参阅[使用 PostgreSQL 管理临时文件](PostgreSQL.ManagingTempFiles.md)。

## PostgreSQL 中 RDS 优化型读取功能的限制
<a name="USER_PostgreSQL.optimizedreads-limitations"></a>

以下限制适用于 PostgreSQL 中的 RDS 优化型读取功能：
+ 实例存储已满时，事务可能会失败。

# 将数据导入 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)。

# 将数据从 RDS for PostgreSQL 数据库实例导出到 Amazon S3
<a name="postgresql-s3-export"></a>

您可以从 RDS for PostgreSQL 数据库实例中查询数据，并将数据直接导出到存储在 Amazon S3 存储桶中的文件中。为此，您首先要安装 RDS for PostgreSQL `aws_s3` 扩展。该扩展为您提供了用于将查询结果导出到 Amazon S3 的函数。接下来，您可以了解如何安装扩展以及如何将数据导出到 Amazon S3。

**注意**  
不支持跨账户导出到 Amazon S3。

所有当前可用的 RDS for PostgreSQL 版本都支持将数据导出到 Amazon Simple Storage Service。有关详细版本信息，请参阅《Amazon RDS for PostgreSQL 版本注释》中的 [Amazon RDS for PostgreSQL 更新](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html)。

如果您没有为导出设置桶，请参阅《Amazon Simple Storage Service 用户指南》中的以下主题。
+ [设置 Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/setting-up-s3.html)
+ [创建存储桶](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)

默认情况下，从 RDS for PostgreSQL 导出到 Amazon S3 的数据使用具有 AWS 托管式密钥的服务器端加密。如果您使用存储桶加密，则 Amazon S3 存储桶必须使用 AWS Key Management Service（AWS KMS）密钥（SSE-KMS）进行加密。目前，不支持使用 Amazon S3 托管式密钥（SSE-S3）加密的存储桶。

**注意**  
您可以使用AWS 管理控制台、AWS CLI 或 Amazon RDS API 将数据库快照数据保存到 Amazon S3。有关更多信息，请参阅 [将 Amazon RDS 的数据库快照数据导出到 Amazon S3](USER_ExportSnapshot.md)。

**Topics**
+ [安装 aws\$1s3 扩展名](#USER_PostgreSQL.S3Export.InstallExtension)
+ [将数据导出到 Amazon S3 概述](#postgresql-s3-export-overview)
+ [指定要导出到的 Amazon S3 文件路径](#postgresql-s3-export-file)
+ [设置 Amazon S3 存储桶的访问权限](postgresql-s3-export-access-bucket.md)
+ [使用 aws\$1s3.query\$1export\$1to\$1s3 函数导出查询数据](postgresql-s3-export-examples.md)
+ [函数参考](postgresql-s3-export-functions.md)
+ [Amazon S3 访问故障排除](postgresql-s3-export-troubleshoot.md)

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

在将 Amazon Simple Storage Service 用于 RDS for PostgreSQL 数据库实例之前，您需要安装 `aws_s3` 扩展。此扩展提供将数据从 RDS for PostgreSQL 数据库实例中导出到 Amazon S3 桶的函数。它还提供从 Amazon S3 导入数据的函数。有关更多信息，请参阅 [将 Amazon S3 中的数据导入到 RDS for PostgreSQL 数据库实例](USER_PostgreSQL.S3Import.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 的函数现在可供使用。

### 验证您的 RDS for PostgreSQL 版本支持导出到 Amazon S3
<a name="postgresql-s3-supported"></a>

您可以使用 `describe-db-engine-versions` 命令验证 RDS for PostgreSQL 版本是否支持导出到 Amazon S3。以下示例验证对版本 10.14 的支持。

```
aws rds describe-db-engine-versions --region us-east-1
--engine postgres --engine-version 10.14 | grep s3Export
```

如果输出包含字符串 `"s3Export"`，则该引擎支持 Amazon S3 导出。否则，该引擎不支持它们。

## 将数据导出到 Amazon S3 概述
<a name="postgresql-s3-export-overview"></a>

要将存储在 RDS for PostgreSQL 数据库中的数据导出到 Amazon S3 存储桶，请使用以下过程。

**将 RDS for PostgreSQL 数据导出到 S3**

1. 标识要用于导出数据的 Amazon S3 文件路径。有关此过程的详细信息，请参阅[指定要导出到的 Amazon S3 文件路径](#postgresql-s3-export-file)。

1. 提供权限以访问 Amazon S3 存储桶。

   要将数据导出到 Amazon S3 文件，请为 RDS for PostgreSQL 数据库实例提供权限以访问导出将用于存储的 Amazon S3 存储桶。此操作包括以下步骤：

   1. 创建一个 IAM 策略，该策略提供对要导出到的 Amazon S3 存储桶的访问权限。

   1. 创建一个 IAM 角色。

   1. 将您创建的策略附在您创建的角色上。

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

   有关此过程的详细信息，请参阅[设置 Amazon S3 存储桶的访问权限](postgresql-s3-export-access-bucket.md)。

1. 标识数据库查询以获取数据。通过调用 `aws_s3.query_export_to_s3` 函数来导出查询数据。

   在完成上述准备任务后，请使用 [aws\$1s3.query\$1export\$1to\$1s3](postgresql-s3-export-functions.md#aws_s3.export_query_to_s3) 函数将查询结果导出到 Amazon S3。有关此过程的详细信息，请参阅[使用 aws\$1s3.query\$1export\$1to\$1s3 函数导出查询数据](postgresql-s3-export-examples.md)。

## 指定要导出到的 Amazon S3 文件路径
<a name="postgresql-s3-export-file"></a>

指定以下信息以标识要将数据导出到的 Amazon S3 中的位置：
+ 存储桶名称 – *存储桶*是 Amazon S3 对象或文件的容器。

  有关使用 Amazon S3 存储数据的更多信息，请参阅《Amazon Simple Storage Service 用户指南》**中的[创建存储桶](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)和[使用对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-downloading-objects.html)。
+ 文件路径 – 文件路径标识 Amazon S3 存储桶中存储导出的位置。文件路径包含以下内容：
  + 用于标识虚拟文件夹路径的可选路径前缀。
  + 用于标识要存储的一个或多个文件的文件前缀。较大的导出将存储在多个文件中，每个文件的最大大小约为 6 GB。其他文件名具有相同的文件前缀，但追加了 `_partXX`。`XX` 表示 2，然后表示 3，依此类推。

  例如，具有 `exports` 文件夹和 `query-1-export` 文件前缀的文件路径为 `/exports/query-1-export`。
+ AWS区域（可选）– Amazon S3 存储桶所在的AWS区域。如果您未指定AWS区域值，则 Amazon RDS 会将文件保存到导出的数据库实例所在的同一AWS区域中的 Amazon S3 中。
**注意**  
目前，AWS 区域必须与导出的数据库实例的区域相同。

  有关 AWS 区域名称和关联值的列表，请参阅[区域、可用区和 Local Zones ](Concepts.RegionsAndAvailabilityZones.md)。

要保存有关导出的存储位置的 Amazon S3 文件信息，您可以使用 [aws\$1commons.create\$1s3\$1uri](postgresql-s3-export-functions.md#aws_commons.create_s3_uri) 函数创建一个 `aws_commons._s3_uri_1` 复合结构，如下所示。

```
psql=> SELECT aws_commons.create_s3_uri(
   'amzn-s3-demo-bucket',
   'sample-filepath',
   'us-west-2'
) AS s3_uri_1 \gset
```

稍后，您可以在对 `s3_uri_1` 函数的调用中将该 [aws\$1s3.query\$1export\$1to\$1s3](postgresql-s3-export-functions.md#aws_s3.export_query_to_s3) 值作为参数提供。有关示例，请参阅 [使用 aws\$1s3.query\$1export\$1to\$1s3 函数导出查询数据](postgresql-s3-export-examples.md)。

# 设置 Amazon S3 存储桶的访问权限
<a name="postgresql-s3-export-access-bucket"></a>

要将数据导出到 Amazon S3，请为 PostgreSQL 数据库实例提供权限以访问文件将保存到的 Amazon S3 存储桶。

为此，请使用以下过程。

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

1. 创建一个 IAM 策略。

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

   在创建此策略的过程中，请执行以下步骤：

   1. 在策略中包含以下必需操作，以允许将文件从 PostgreSQL 数据库实例传输到 Amazon S3 存储桶：
      + `s3:PutObject`
      + `s3:AbortMultipartUpload`

   1. 包含用于标识 Amazon S3 存储桶以及其中的对象的 Amazon Resource Name (ARN)。用于访问 Amazon S3 的 ARN 格式为：`arn:aws:s3:::amzn-s3-demo-bucket/*`

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

   以下 AWS CLI 命令使用这些选项创建一个名为 `rds-s3-export-policy` 的 IAM 策略。该策略授予对名为 *amzn-s3-demo-bucket* 的存储桶的访问权限。
**警告**  
我们建议您在一个私有 VPC 中设置数据库，该 VPC 配置了用于访问特定存储桶的端点策略。有关更多信息，请参阅 Amazon VPC 用户指南 中的[对 Amazon S3 使用端点策略](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints-s3.html#vpc-endpoints-policies-s3)。  
强烈建议您不要创建具有所有资源访问权限的策略。此访问权限可能会对数据安全造成威胁。如果您使用 `S3:PutObject` 创建一个向 `"Resource":"*"` 授予对所有资源的访问权限的策略，则具有导出特权的用户可以将数据导出到您账户中的所有存储桶。此外，用户可以将数据导出到 *AWS 区域内的任何可公开写入的存储桶*。

   在您创建策略之后，请记下策略的 Amazon Resource Name (ARN)。在将策略附加到 IAM 角色时，您在后面的步骤中需要使用 ARN。

   ```
   aws iam create-policy  --policy-name rds-s3-export-policy  --policy-document '{
        "Version": "2012-10-17",		 	 	 
        "Statement": [
          {
            "Sid": "s3export",
            "Action": [
              "s3:PutObject*",
              "s3:ListBucket",
              "s3:GetObject*",
              "s3:DeleteObject*",
              "s3:GetBucketLocation",
              "s3:AbortMultipartUpload"
            ],
            "Effect": "Allow",
            "Resource": [
              "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-export-role` 的角色来实现该目的。  
**Example**  

   对于 Linux、macOS 或 Unix：

   ```
   aws iam create-role  \
       --role-name rds-s3-export-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-export-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-export-role.` 的角色。请将 `your-policy-arn` 替换为您在前面的步骤中记下的策略 ARN。

   ```
   aws iam attach-role-policy  --policy-arn your-policy-arn  --role-name rds-s3-export-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. 在 **Connectivity & security (连接性和安全性)** 选项卡上的 **Manage IAM roles (管理 IAM 角色)** 部分中，在 **Add IAM roles to this instance (向此实例添加 IAM 角色)** 下选择要添加的角色。

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

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

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

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

  对于 Linux、macOS 或 Unix：

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

  对于：Windows

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

# 使用 aws\$1s3.query\$1export\$1to\$1s3 函数导出查询数据
<a name="postgresql-s3-export-examples"></a>

通过调用 [aws\$1s3.query\$1export\$1to\$1s3](postgresql-s3-export-functions.md#aws_s3.export_query_to_s3) 函数将 PostgreSQL 数据导出到 Amazon S3。

**Topics**
+ [先决条件](#postgresql-s3-export-examples-prerequisites)
+ [调用 aws\$1s3.query\$1export\$1to\$1s3](#postgresql-s3-export-examples-basic)
+ [导出到使用自定义分隔符的 CSV 文件](#postgresql-s3-export-examples-custom-delimiter)
+ [导出到具有编码的二进制文件](#postgresql-s3-export-examples-encoded)

## 先决条件
<a name="postgresql-s3-export-examples-prerequisites"></a>

在使用 `aws_s3.query_export_to_s3` 函数之前，请确保完成以下先决条件：
+ 安装所需的 PostgreSQL 扩展，如[将数据导出到 Amazon S3 概述](postgresql-s3-export.md#postgresql-s3-export-overview)中所述。
+ 确定要将数据导出到 Amazon S3 的位置，如[指定要导出到的 Amazon S3 文件路径](postgresql-s3-export.md#postgresql-s3-export-file)中所述。
+ 确保数据库实例具有 [设置 Amazon S3 存储桶的访问权限](postgresql-s3-export-access-bucket.md) 中所述的对 Amazon S3 的访问权限。

以下示例使用一个称作 `sample_table` 的数据库表。这些示例将数据导出到称为 *amzn-s3-demo-bucket* 的存储桶中。使用以下 SQL 语句在 psql 中创建示例表和数据。

```
psql=> CREATE TABLE sample_table (bid bigint PRIMARY KEY, name varchar(80));
psql=> INSERT INTO sample_table (bid,name) VALUES (1, 'Monday'), (2,'Tuesday'), (3, 'Wednesday');
```

## 调用 aws\$1s3.query\$1export\$1to\$1s3
<a name="postgresql-s3-export-examples-basic"></a>

下面说明了调用 [aws\$1s3.query\$1export\$1to\$1s3](postgresql-s3-export-functions.md#aws_s3.export_query_to_s3) 函数的基本方法。

这些示例使用变量 `s3_uri_1` 确定包含用于标识 Amazon S3 文件的信息的结构。使用 [aws\$1commons.create\$1s3\$1uri](postgresql-s3-export-functions.md#aws_commons.create_s3_uri) 函数可创建结构。

```
psql=> SELECT aws_commons.create_s3_uri(
   'amzn-s3-demo-bucket',
   'sample-filepath',
   'us-west-2'
) AS s3_uri_1 \gset
```

尽管以下两个 `aws_s3.query_export_to_s3` 函数调用的参数不同，但这些示例的结果是相同的。`sample_table` 表的所有行都将导出到称为 *amzn-s3-demo-bucket* 的存储桶中。

```
psql=> SELECT * FROM aws_s3.query_export_to_s3('SELECT * FROM sample_table', :'s3_uri_1');

psql=> SELECT * FROM aws_s3.query_export_to_s3('SELECT * FROM sample_table', :'s3_uri_1', options :='format text');
```

参数如下所述：
+ `'SELECT * FROM sample_table'` – 第一个参数是包含 SQL 查询的必需文本字符串。PostgreSQL 引擎将运行此查询。查询的结果将复制到其他参数中标识的 S3 存储桶。
+ `:'s3_uri_1'` – 此参数是标识 Amazon S3 文件的结构。此示例使用变量来标识先前创建的结构。相反，您可通过内联方式在 `aws_commons.create_s3_uri` 函数调用中包含 `aws_s3.query_export_to_s3` 函数调用来创建结构，如下所示。

  ```
  SELECT * from aws_s3.query_export_to_s3('select * from sample_table', 
     aws_commons.create_s3_uri('amzn-s3-demo-bucket', 'sample-filepath', 'us-west-2') 
  );
  ```
+ `options :='format text'` – `options` 参数是包含 PostgreSQL `COPY` 参数的可选文本字符串。复制过程使用 [PostgreSQL COPY](https://www.postgresql.org/docs/current/sql-copy.html) 命令的参数和格式。

如果指定的文件在 Amazon S3 存储桶中不存在，则会创建该文件。如果该文件已存在，则将覆盖该文件。以下是用于访问 Amazon S3 中的导出数据的语法。

```
s3-region://bucket-name[/path-prefix]/file-prefix
```

较大的导出将存储在多个文件中，每个文件的最大大小约为 6 GB。其他文件名具有相同的文件前缀，但追加了 `_partXX`。`XX` 表示 2，然后表示 3，依此类推。例如，假设您指定用于存储数据文件的路径，如下所示。

```
s3-us-west-2://amzn-s3-demo-bucket/my-prefix
```

如果导出必须创建三个数据文件，则 Amazon S3 存储桶将包含以下数据文件。

```
s3-us-west-2://amzn-s3-demo-bucket/my-prefix
s3-us-west-2://amzn-s3-demo-bucket/my-prefix_part2
s3-us-west-2://amzn-s3-demo-bucket/my-prefix_part3
```

有关此函数的完整参考以及其他调用方法，请参阅[aws\$1s3.query\$1export\$1to\$1s3](postgresql-s3-export-functions.md#aws_s3.export_query_to_s3)。有关访问 Amazon S3 中的文件的更多信息，请参阅 *Amazon Simple Storage Service 用户指南*中的[查看对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/OpeningAnObject.html)。

## 导出到使用自定义分隔符的 CSV 文件
<a name="postgresql-s3-export-examples-custom-delimiter"></a>

以下示例说明如何调用 [aws\$1s3.query\$1export\$1to\$1s3](postgresql-s3-export-functions.md#aws_s3.export_query_to_s3) 函数以将数据导出到使用自定义分隔符的文件。此示例使用 [PostgreSQL COPY](https://www.postgresql.org/docs/current/sql-copy.html) 命令的参数来指定逗号分隔值 (CSV) 格式和冒号 (:) 分隔符。

```
SELECT * from aws_s3.query_export_to_s3('select * from basic_test', :'s3_uri_1', options :='format csv, delimiter $$:$$');
```

## 导出到具有编码的二进制文件
<a name="postgresql-s3-export-examples-encoded"></a>

以下示例说明如何调用 [aws\$1s3.query\$1export\$1to\$1s3](postgresql-s3-export-functions.md#aws_s3.export_query_to_s3) 函数以将数据导出到具有 Windows-1253 编码的二进制文件。

```
SELECT * from aws_s3.query_export_to_s3('select * from basic_test', :'s3_uri_1', options :='format binary, encoding WIN1253');
```

# 函数参考
<a name="postgresql-s3-export-functions"></a>

**Topics**
+ [aws\$1s3.query\$1export\$1to\$1s3](#aws_s3.export_query_to_s3)
+ [aws\$1commons.create\$1s3\$1uri](#aws_commons.create_s3_uri)

## aws\$1s3.query\$1export\$1to\$1s3
<a name="aws_s3.export_query_to_s3"></a>

将 PostgreSQL 查询结果导出到 Amazon S3 存储桶。`aws_s3` 扩展提供 `aws_s3.query_export_to_s3` 函数。

两个必需的参数为 `query` 和 `s3_info`。这两个参数定义了要导出的查询，并标识了要导出到的 Amazon S3 存储桶。一个称作 `options` 的可选参数，用于定义各种导出参数。有关使用 `aws_s3.query_export_to_s3` 函数的示例，请参阅[使用 aws\$1s3.query\$1export\$1to\$1s3 函数导出查询数据](postgresql-s3-export-examples.md)。

**语法**

```
aws_s3.query_export_to_s3(
    query text,    
    s3_info aws_commons._s3_uri_1,    
    options text,
    kms_key text
)
```输入参数

*query*()  
一个必需的文本字符串，其中包含 PostgreSQL 引擎运行的 SQL 查询。此查询的结果将复制到 `s3_info` 参数中标识的 S3 存储桶。

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

  目前，此值必须是导出的数据库实例的同一个 AWS 区域。默认值为导出的数据库实例的 AWS 区域。
要创建 `aws_commons._s3_uri_1` 复合结构，请参阅 [aws\$1commons.create\$1s3\$1uri](#aws_commons.create_s3_uri) 函数。

*options*  
一个包含 PostgreSQL `COPY` 命令的参数的可选文本字符串。这些参数指定了在导出时复制数据的方式。有关更多详细信息，请参阅 [PostgreSQL COPY 文档](https://www.postgresql.org/docs/current/sql-copy.html)。

*kms\$1key 文本*  
一个可选文本字符串，其中包含要将数据导出到的 S3 存储桶的客户托管 KMS 密钥。

### 备用输入参数
<a name="aws_s3.export_query_to_s3-alternate-parameters"></a>

为帮助进行测试，您可以使用一组扩展的参数而非 `s3_info` 参数。下面是 `aws_s3.query_export_to_s3` 函数的其他语法变化。

不使用 `s3_info` 参数来标识 Amazon S3 文件，而使用 `bucket`、`file_path` 和 `region` 参数的组合。

```
aws_s3.query_export_to_s3(
    query text,    
    bucket text,    
    file_path text,    
    region text,    
    options text,
    kms_key text
)
```

*query*()  
一个必需的文本字符串，其中包含 PostgreSQL 引擎运行的 SQL 查询。此查询的结果将复制到 `s3_info` 参数中标识的 S3 存储桶。

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

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

*region*  
一个包含存储桶所在的 AWS 区域的可选文本字符串。有关 AWS 区域名称和关联值的列表，请参阅[区域、可用区和 Local Zones ](Concepts.RegionsAndAvailabilityZones.md)。  
目前，此值必须是导出的数据库实例的同一个 AWS 区域。默认值为导出的数据库实例的 AWS 区域。

*options*  
一个包含 PostgreSQL `COPY` 命令的参数的可选文本字符串。这些参数指定了在导出时复制数据的方式。有关更多详细信息，请参阅 [PostgreSQL COPY 文档](https://www.postgresql.org/docs/current/sql-copy.html)。

*kms\$1key 文本*  
一个可选文本字符串，其中包含要将数据导出到的 S3 存储桶的客户托管 KMS 密钥。

### 输出参数
<a name="aws_s3.export_query_to_s3-output-parameters"></a>

```
aws_s3.query_export_to_s3(
    OUT rows_uploaded bigint,
    OUT files_uploaded bigint,
    OUT bytes_uploaded bigint
)
```

*rows\$1uploaded*  
针对给定查询成功上传到 Amazon S3 的表行的数目。

*files\$1uploaded*  
已上传到 Amazon S3 的文件的数目。以约 6 GB 的大小创建文件。创建的每个附加文件的名称都追加了 `_partXX`。根据需要，`XX` 表示 2，然后表示 3，依此类推。

*bytes\$1uploaded*  
已上传到 Amazon S3 的字节的总数。

### 示例
<a name="aws_s3.export_query_to_s3-examples"></a>

```
psql=> SELECT * from aws_s3.query_export_to_s3('select * from sample_table', 'amzn-s3-demo-bucket', 'sample-filepath');
psql=> SELECT * from aws_s3.query_export_to_s3('select * from sample_table', 'amzn-s3-demo-bucket', 'sample-filepath','us-west-2');
psql=> SELECT * from aws_s3.query_export_to_s3('select * from sample_table', 'amzn-s3-demo-bucket', 'sample-filepath','us-west-2','format text');
```

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

创建 `aws_commons._s3_uri_1` 结构来保存 Amazon S3 文件信息。在 `aws_commons.create_s3_uri` 函数的 `s3_info` 参数中使用 [aws\$1s3.query\$1export\$1to\$1s3](#aws_s3.export_query_to_s3) 函数的结果。有关使用 `aws_commons.create_s3_uri` 函数的示例，请参阅[指定要导出到的 Amazon S3 文件路径](postgresql-s3-export.md#postgresql-s3-export-file)。

**语法**

```
aws_commons.create_s3_uri(
   bucket text,
   file_path text,
   region text
)
```输入参数

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

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

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

# Amazon S3 访问故障排除
<a name="postgresql-s3-export-troubleshoot"></a>

如果在尝试将数据导出到 Amazon S3 时遇到连接问题，请首先确认与数据库实例关联的 VPC 安全组的出站访问规则是否允许网络连接。具体而言，安全组必须有一条规则允许数据库实例将 TCP 流量发送到端口 443 和任何 IPv4 地址（0.0.0/0）。有关更多信息，请参阅 [通过创建安全组提供对 VPC 中的数据库实例的访问](CHAP_SettingUp.md#CHAP_SettingUp.SecurityGroup)。

另请参阅以下建议：
+ [对 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)

# 从 RDS for PostgreSQL 数据库实例中调用 AWS Lambda 函数
<a name="PostgreSQL-Lambda"></a>

AWS Lambda 是事件驱动型计算服务，无需您预置或管理服务器即可运行代码。该服务可与许多 AWS 服务搭配使用，其中包括 RDS for PostgreSQL。例如，您可以使用 Lambda 函数处理来自数据库的事件通知，或者在将新文件上传到 Amazon S3 时从文件中加载数据。若要了解 Lambda 的更多信息，请参阅《AWS Lambda 开发人员指南**》中的[什么是 AWS Lambda？](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 

**注意**  
这些 RDS for PostgreSQL 版本支持调用 AWS Lambda 函数：  
所有的 PostgreSQL 18 版本
所有 PostgreSQL 17 版本
所有 PostgreSQL 16 版本
所有 PostgreSQL 15 版本
PostgreSQL 14.1 及更高的次要版本
PostgreSQL 13.2 及更高的次要版本
PostgreSQL 12.6 及更高的次要版本

设置 RDS for PostgreSQL 使用 Lambda 函数的过程包含多个步骤，其中涉及 AWS Lambda、IAM、VPC 和 RDS for PostgreSQL 数据库实例。下文对必要步骤进行了总结。

有关 Lambda 函数的更多信息，请参阅《AWS 开发人员指南[https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html)》中的 [Lambda 入门](https://docs.aws.amazon.com/lambda/latest/dg/lambda-foundation.html)和 *AWS Lambda Lambda 函数*。

**Topics**
+ [步骤 1：配置 RDS for PostgreSQL 数据库实例，实现与 AWS Lambda 的出站连接](#PostgreSQL-Lambda-network)
+ [步骤 2：为 RDS for PostgreSQL 数据库实例和 AWS Lambda 配置 IAM](#PostgreSQL-Lambda-access)
+ [步骤 3：为 RDS for PostgreSQL 数据库实例安装 `aws_lambda` 扩展](#PostgreSQL-Lambda-install-extension)
+ [步骤 4：将 Lambda 帮助程序函数与 RDS for PostgreSQL 数据库实例搭配使用（可选）](#PostgreSQL-Lambda-specify-function)
+ [步骤 5：从 RDS for PostgreSQL 数据库实例调用 Lambda 函数](#PostgreSQL-Lambda-invoke)
+ [步骤 6：授予其他用户调用 Lambda 函数的权限](#PostgreSQL-Lambda-grant-users-permissions)
+ [示例：从 RDS for PostgreSQL 数据库实例调用 Lambda 函数](PostgreSQL-Lambda-examples.md)
+ [Lambda 函数错误消息](PostgreSQL-Lambda-errors.md)
+ [AWS Lambda 函数和参数参考](PostgreSQL-Lambda-functions.md)

## 步骤 1：配置 RDS for PostgreSQL 数据库实例，实现与 AWS Lambda 的出站连接
<a name="PostgreSQL-Lambda-network"></a>

Lambda 函数始终在 AWS Lambda 服务拥有的 Amazon VPC 中运行。Lambda 将向此 VPC 应用网络访问和安全规则，并且会自动维护和监控 VPC。RDS for PostgreSQL 数据库实例向 Lambda 服务的 VPC 发送网络流量。其配置方式取决于 数据库实例是公有实例，还是私有实例。
+ **公有 RDS for PostgreSQL 数据库实例** – 如果数据库实例位于 VPC 的公有子网中，并且该实例的“PublicyAccessible”属性为 `true`，则该实例是公有的。若要查找此属性的值，您可以使用 [describe-db-instances](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-instances.html) AWS CLI 命令。您也可以使用 AWS 管理控制台 打开 **Connectivity & security**（连接和安全性）选项卡，然后检查 **Publicly accessible**（公开访问）是否为 **Yes**（是）。要验证实例是否在您的 VPC 的公有子网中，您可以使用 AWS 管理控制台或 AWS CLI。

  要设置对 Lambda 的访问权限，您可以使用 AWS 管理控制台 或 AWS CLI 在 VPC 的安全组上创建出站规则。出站规则指定 TCP 可以使用端口 443 将数据包发送到任何 IPv4 地址（0.0.0.0/0）。
+ **私有 RDS for PostgreSQL数据库实例** – 在这种情况下，实例的“PublicyAccessible”属性为 `false` 或它位于私有子网中。要允许实例使用 Lambda，您可以使用网络地址转换（NAT）网关。有关更多信息，请参阅 [NAT 网关](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)。或者，您可以使用用于 Lambda 的 VPC 端点配置 VPC。有关更多信息，请参阅《Amazon VPC 用户指南》**中的 [VPC 端点](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints.html)。该端点响应 RDS for PostgreSQL 数据库实例对 Lambda 函数发出的调用。VPC 端点使用自己的私有 DNS 解析。在您将 `rds.custom_dns_resolution` 的值从其默认值 0（未启用）更改为 1 之前，RDS for PostgreSQL 无法使用 Lambda VPC 端点。为此，请执行以下操作：
  + 创建自定义数据库参数组。
  + 将 `rds.custom_dns_resolution` 参数的值由默认值 `0` 更改为 `1`。
  + 修改数据库实例以使用自定义数据库参数组。
  + 重启实例，使修改的参数生效。

您的 VPC 现在可以在网络级别与 AWS Lambda VPC 交互。接下来，您使用 IAM 配置权限。

## 步骤 2：为 RDS for PostgreSQL 数据库实例和 AWS Lambda 配置 IAM
<a name="PostgreSQL-Lambda-access"></a>

从 RDS for PostgreSQL 数据库实例调用 Lambda 函数需要特定权限。若要配置必要权限，建议创建允许调用 Lambda 函数的 IAM 策略，将该策略分配给一个角色，然后将该角色应用于数据库实例。这种方法授予数据库实例代表您调用指定 Lambda 函数的权限。以下步骤说明如何使用 AWS CLI 执行此操作。

**配置 IAM 权限以将Amazon RDS 实例与 Lambda 搭配使用**

1. 使用 [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) AWS CLI 命令创建允许 RDS for PostgreSQL 数据库实例调用指定 Lambda 函数的 IAM 策略。（语句 ID (Sid) 是策略语句的可选描述，对使用没有影响。） 此策略授予 数据库实例调用指定 Lambda 函数所需的最低权限。

   ```
   aws iam create-policy  --policy-name rds-lambda-policy --policy-document '{
       "Version": "2012-10-17",		 	 	 
       "Statement": [
           {
           "Sid": "AllowAccessToExampleFunction",
           "Effect": "Allow",
           "Action": "lambda:InvokeFunction",
           "Resource": "arn:aws:lambda:aws-region:444455556666:function:my-function"
           }
       ]
   }'
   ```

   您也可以使用允许您调用任何 Lambda 函数的预定义 `AWSLambdaRole` 策略。有关更多信息，请参阅 [Lambda 的基于身份的 IAM 策略](https://docs.aws.amazon.com/lambda/latest/dg/access-control-identity-based.html#access-policy-examples-aws-managed) 

1. 使用 [create-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) AWS CLI 命令创建该策略可在运行时担任的 IAM 角色。

   ```
   aws iam create-role  --role-name rds-lambda-role --assume-role-policy-document '{
       "Version": "2012-10-17",		 	 	 
       "Statement": [
           {
           "Effect": "Allow",
           "Principal": {
               "Service": "rds.amazonaws.com"
           },
           "Action": "sts:AssumeRole"
           }
       ]
   }'
   ```

1. 使用 [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) AWS CLI 命令将策略应用于角色。

   ```
   aws iam attach-role-policy \
       --policy-arn arn:aws:iam::444455556666:policy/rds-lambda-policy \
       --role-name rds-lambda-role --region aws-region
   ```

1. 使用  [add-role-to-db-instance](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/rds/add-role-to-db-instance.html) AWS CLI 命令，将该角色应用于 RDS for PostgreSQL 数据库实例。最后一步允许数据库实例的数据库用户调用 Lambda 函数。

   ```
   aws rds add-role-to-db-instance \
          --db-instance-identifier my-instance-name \
          --feature-name Lambda \
          --role-arn  arn:aws:iam::444455556666:role/rds-lambda-role   \
          --region aws-region
   ```

完成 VPC 和 IAM 配置后，便可以安装 `aws_lambda` 扩展。（请注意，您可以随时安装扩展，但只有在您设置正确的 VPC 支持和 IAM 权限之后，`aws_lambda` 扩展才会对 RDS for PostgreSQL 数据库实例的功能添加内容。）

## 步骤 3：为 RDS for PostgreSQL 数据库实例安装 `aws_lambda` 扩展
<a name="PostgreSQL-Lambda-install-extension"></a>

要将 AWS Lambda 与 RDS for PostgreSQL 数据库实例结合使用，请将 `aws_lambda` PostgreSQL 扩展添加到 RDS for PostgreSQL 数据库实例。此扩展允许 RDS for PostgreSQL 数据库实例能从 PostgreSQL 调用 Lambda 函数。

**在 RDS for PostgreSQL 数据库实例中安装 `aws_lambda` 扩展**

使用 PostgreSQL `psql` 命令行或 pgAdmin 工具连接到 RDS for PostgreSQL 数据库实例。

1. 以具有 `rds_superuser` 权限的用户身份，连接到 RDS for PostgreSQL 数据库实例。默认 `postgres` 用户如示例所示。

   ```
   psql -h instance.444455556666.aws-region.rds.amazonaws.com -U postgres -p 5432
   ```

1. 安装 `aws_lambda` 扩展。`aws_commons` 扩展也是必要项。其为 PostgreSQL 的 `aws_lambda` 和许多其他 Aurora 扩展提供帮助程序函数。如果其尚未安装到 RDS for PostgreSQL 数据库实例上，则会按如下所示一并安装该扩展和 `aws_lambda`。

   ```
   CREATE EXTENSION IF NOT EXISTS aws_lambda CASCADE;
   NOTICE:  installing required extension "aws_commons"
   CREATE EXTENSION
   ```

`aws_lambda` 扩展已安装在 数据库实例中。现在，您可以创建易于使用结构来调用 Lambda 函数。

## 步骤 4：将 Lambda 帮助程序函数与 RDS for PostgreSQL 数据库实例搭配使用（可选）
<a name="PostgreSQL-Lambda-specify-function"></a>

您可以使用 `aws_commons` 扩展中的帮助程序函数来准备实体，以便更轻松地从 PostgreSQL 调用这些实体。为此，您需要获得有关 Lambda 函数的以下信息：
+ **Function name**（函数名称）：Lambda 函数的名称、Amazon Resource Name (ARN)、版本或别名。在 [步骤 2：为实例和 Lambda 配置 IAM](#PostgreSQL-Lambda-access) 中创建的 IAM 策略需要 ARN，所以建议您使用函数的 ARN。
+ **AWS 区域** —（可选）如果与 RDS for PostgreSQL 数据库实例不在同一个区域中，则此区域为 Lambda 函数所在的 AWS 区域。

您可以使用 [aws\$1commons.create\$1lambda\$1function\$1arn](PostgreSQL-Lambda-functions.md#aws_commons.create_lambda_function_arn) 函数保存 Lambda 函数名称信息。此帮助程序函数创建了 `aws_commons._lambda_function_arn_1` 复合结构，其中包含调用函数所需的详细信息。在下文中，您可以找到三种替代方法来设置此复合结构。

```
SELECT aws_commons.create_lambda_function_arn(
   'my-function',
   'aws-region'
) AS aws_lambda_arn_1 \gset
```

```
SELECT aws_commons.create_lambda_function_arn(
   '111122223333:function:my-function',
   'aws-region'
) AS lambda_partial_arn_1 \gset
```

```
SELECT aws_commons.create_lambda_function_arn(
   'arn:aws:lambda:aws-region:111122223333:function:my-function'
) AS lambda_arn_1 \gset
```

这些值均可用于 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 函数调用。有关示例，请参阅 [步骤 5：从 RDS for PostgreSQL 数据库实例调用 Lambda 函数](#PostgreSQL-Lambda-invoke)。

## 步骤 5：从 RDS for PostgreSQL 数据库实例调用 Lambda 函数
<a name="PostgreSQL-Lambda-invoke"></a>

`aws_lambda.invoke` 函数采用同步还是异步调用方式取决于 `invocation_type`。此参数的两个可用选项分别为 `RequestResponse`（默认）和 `Event`，如下所示。
+ **`RequestResponse`**：此为*同步*调用类型。如果调用时未指定调用类型，默认此调用方式。响应有效负载包含 `aws_lambda.invoke` 函数的结果。如果工作流程需要接收 Lambda 函数的结果才能继续进行操作，请使用此调用类型。
+ **`Event`**：此为*异步*调用类型。响应不包含包含结果的有效负载。如果工作流程不需要 Lambda 函数的结果即可继续进行操作，请使用此调用类型。

要对设置进行简单测试，您可以使用 `psql` 连接到数据库实例，然后从命令行调用示例函数。假设在 Lambda 服务上设置了一个基本函数，例如下面屏幕截图中所示的简单 Python 函数。

![\[AWS Lambda 的 AWS CLI 中显示的示例 Lambda 函数\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/lambda_simple_function.png)


**调用示例函数**

1. 使用 `psql` 或 pgAdmin 连接到数据库实例。

   ```
   psql -h instance.444455556666.aws-region.rds.amazonaws.com -U postgres -p 5432
   ```

1. 使用函数的 ARN 调用该函数。

   ```
   SELECT * from aws_lambda.invoke(aws_commons.create_lambda_function_arn('arn:aws:lambda:aws-region:444455556666:function:simple', 'us-west-1'), '{"body": "Hello from Postgres!"}'::json );
   ```

   响应如下所示。

   ```
   status_code |                        payload                        | executed_version | log_result
   -------------+-------------------------------------------------------+------------------+------------
            200 | {"statusCode": 200, "body": "\"Hello from Lambda!\""} | $LATEST          |
   (1 row)
   ```

如果调用尝试不成功，请参阅 [Lambda 函数错误消息](PostgreSQL-Lambda-errors.md)。

## 步骤 6：授予其他用户调用 Lambda 函数的权限
<a name="PostgreSQL-Lambda-grant-users-permissions"></a>

在程序的这一步骤中，仅当您是 `rds_superuser` 才能调用 Lambda 函数。要允许其他用户调用您创建的任何函数，您需要向他们授予权限。

**要授予调用 Lambda 函数的其他权限，请执行以下操作：**

1. 使用 `psql` 或 pgAdmin 连接到数据库实例。

   ```
   psql -h instance.444455556666.aws-region.rds.amazonaws.com -U postgres -p 5432
   ```

1. 运行以下 SQL 命令：

   ```
   postgres=>  GRANT USAGE ON SCHEMA aws_lambda TO db_username;
   GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA aws_lambda TO db_username;
   ```

# 示例：从 RDS for PostgreSQL 数据库实例调用 Lambda 函数
<a name="PostgreSQL-Lambda-examples"></a>

在下文中，您可以找到调用 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 函数的一些示例。大多数示例都使用您在 [步骤 4：将 Lambda 帮助程序函数与 RDS for PostgreSQL 数据库实例搭配使用（可选）](PostgreSQL-Lambda.md#PostgreSQL-Lambda-specify-function) 中创建的复合结构 `aws_lambda_arn_1` 来简化函数详细信息的传递。有关异步调用的示例，请参阅 [示例：Lambda 函数的异步（事件）调用](#PostgreSQL-Lambda-Event)。列出的其他示例均使用同步调用。

要了解有关 Lambda 调用类型的更多信息，请参阅《AWS Lambda 开发人员指南**》中的[调用 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html)。有关 `aws_lambda_arn_1` 的更多信息，请参阅[aws\$1commons.create\$1lambda\$1function\$1arn](PostgreSQL-Lambda-functions.md#aws_commons.create_lambda_function_arn)。

**Topics**
+ [示例：Lambda 函数的同步 (RequestResponse) 调用](#PostgreSQL-Lambda-RequestResponse)
+ [示例：Lambda 函数的异步（事件）调用](#PostgreSQL-Lambda-Event)
+ [示例：在函数响应中捕获 Lambda 执行日志](#PostgreSQL-Lambda-log-response)
+ [示例：在 Lambda 函数中包含客户端上下文](#PostgreSQL-Lambda-client-context)
+ [示例：调用 Lambda 函数的特定版本](#PostgreSQL-Lambda-function-version)

## 示例：Lambda 函数的同步 (RequestResponse) 调用
<a name="PostgreSQL-Lambda-RequestResponse"></a>

以下是 Lambda 函数同步调用的两个示例。这些 `aws_lambda.invoke` 函数调用的结果相同。

```
SELECT * FROM aws_lambda.invoke('aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json);
```

```
SELECT * FROM aws_lambda.invoke('aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse');
```

参数如下所述：
+ `:'aws_lambda_arn_1'`：此参数使用 `aws_commons.create_lambda_function_arn` 帮助程序函数标识在 [步骤 4：将 Lambda 帮助程序函数与 RDS for PostgreSQL 数据库实例搭配使用（可选）](PostgreSQL-Lambda.md#PostgreSQL-Lambda-specify-function) 中创建的复合结构。您还可以通过内联方式在 `aws_lambda.invoke` 调用中创建此结构，如下所示。

  ```
  SELECT * FROM aws_lambda.invoke(aws_commons.create_lambda_function_arn('my-function', 'aws-region'),
  '{"body": "Hello from Postgres!"}'::json
  );
  ```
+ `'{"body": "Hello from PostgreSQL!"}'::json` – 要传递到 Lambda 函数的 JSON 负载。
+ `'RequestResponse'` – Lambda 调用类型。

## 示例：Lambda 函数的异步（事件）调用
<a name="PostgreSQL-Lambda-Event"></a>

以下是异步 Lambda 函数调用的示例。`Event` 调用类型使用指定的输入负载计划 Lambda 函数调用并立即返回。在某些不依赖于 Lambda 函数结果的工作流程中使用 `Event` 调用类型。

```
SELECT * FROM aws_lambda.invoke('aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'Event');
```

## 示例：在函数响应中捕获 Lambda 执行日志
<a name="PostgreSQL-Lambda-log-response"></a>

您可以使用 `aws_lambda.invoke` 函数调用中的 `log_type` 参数，在函数响应中包含执行日志的最后 4 kB。默认情况下，此参数设置为 `None`，但您可以指定 `Tail` 在响应中捕获 Lambda 执行日志的结果，如下所示。

```
SELECT *, select convert_from(decode(log_result, 'base64'), 'utf-8') as log FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse', 'Tail');
```

将 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 函数的 `log_type` 参数设置为 `Tail`，以在响应中包含执行日志。`log_type` 参数的默认值为 `None`。

返回的 `log_result` 是 `base64` 编码的字符串。您可以使用 `decode` 和 `convert_from` PostgreSQL 函数的组合来解码内容。

有关 `log_type` 的更多信息，请参阅[aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke)。

## 示例：在 Lambda 函数中包含客户端上下文
<a name="PostgreSQL-Lambda-client-context"></a>

`aws_lambda.invoke` 函数具有 `context` 参数，可用于传递独立于有效负载的信息，如下所示。

```
SELECT *, convert_from(decode(log_result, 'base64'), 'utf-8') as log FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse', 'Tail');
```

要包含客户端上下文，请将 JSON 对象用于 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 函数的 `context` 参数。

有关 `context` 参数的更多信息，请参阅 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 参考。

## 示例：调用 Lambda 函数的特定版本
<a name="PostgreSQL-Lambda-function-version"></a>

通过在 `aws_lambda.invoke` 调用中包含 `qualifier` 参数，您可以指定 Lambda 函数的特定版本。在下文中，您可以找到一个使用 `'custom_version'` 作为版本别名完成此操作的示例。

```
SELECT * FROM aws_lambda.invoke('aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse', 'None', NULL, 'custom_version');
```

您还可以改为提供包含 Lambda 函数名称详细信息的 Lambda 函数限定符，如下所示。

```
SELECT * FROM aws_lambda.invoke(aws_commons.create_lambda_function_arn('my-function:custom_version', 'us-west-2'),
'{"body": "Hello from Postgres!"}'::json);
```

有关 `qualifier` 和其他参数的详细信息，请参阅 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 参考。

# Lambda 函数错误消息
<a name="PostgreSQL-Lambda-errors"></a>

在下面的列表中，您可以找到有关错误消息的信息，以及可能的原因和解决方案。
+ **VPC 配置问题**

  在尝试连接时，VPC 配置问题可能会引发以下错误消息：

  ```
  ERROR:  invoke API failed
  DETAIL: AWS Lambda client returned 'Unable to connect to endpoint'.
  CONTEXT:  SQL function "invoke" statement 1
  ```

  导致此错误的常见原因是 VPC 安全组配置不当。确保在 VPC 安全组的端口 443 上打开 TCP 的出站规则，以便 VPC 能够连接到 Lambda VPC。

  如果数据库实例为私有实例，请检查 VPC 的私有 DNS 设置。确保将 `rds.custom_dns_resolution` 参数设置为 1 并按照 [步骤 1：配置 RDS for PostgreSQL 数据库实例，实现与 AWS Lambda 的出站连接](PostgreSQL-Lambda.md#PostgreSQL-Lambda-network) 所述设置 AWS PrivateLink。有关更多信息，请参阅[接口 VPC 端点 (AWS PrivateLink)](https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html#vpce-private-dns)。
+ **缺乏调用 Lambda 函数所需的权限**

  如果看到以下任一错误消息，说明调用此函数的用户（角色）没有适当的权限。

  ```
  ERROR:  permission denied for schema aws_lambda
  ```

  ```
  ERROR:  permission denied for function invoke
  ```

  必须向用户（角色）授予特定权限才能调用 Lambda 函数。有关更多信息，请参阅 [步骤 6：授予其他用户调用 Lambda 函数的权限](PostgreSQL-Lambda.md#PostgreSQL-Lambda-grant-users-permissions)。
+ **对 Lambda 函数中的错误处理不当**

  如果 Lambda 函数在请求处理过程中抛出异常，则 `aws_lambda.invoke` 会失败并显示 PostgreSQL 错误，如下所示。

  ```
  SELECT * FROM aws_lambda.invoke('aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json);
  ERROR:  lambda invocation failed
  DETAIL:  "arn:aws:lambda:us-west-2:555555555555:function:my-function" returned error "Unhandled", details: "<Error details string>".
  ```

  务必处理 Lambda 函数或 PostgreSQL 应用程序中的错误。

# AWS Lambda 函数和参数参考
<a name="PostgreSQL-Lambda-functions"></a>

以下是通过 RDS for PostgreSQL 调用 Lambda 所用函数和参数的参考。

**Topics**
+ [aws\$1lambda.invoke](#aws_lambda.invoke)
+ [aws\$1commons.create\$1lambda\$1function\$1arn](#aws_commons.create_lambda_function_arn)
+ [aws\$1lambda 参数](#aws_lambda.parameters)

## aws\$1lambda.invoke
<a name="aws_lambda.invoke"></a>

为 RDS for PostgreSQL 数据库实例 运行 Lambda 函数。

有关调用 Lambda 函数的更多详细信息，另请参阅 *AWS Lambda 开发人员指南*中的[调用](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html)。

**语法**

------
#### [ JSON ]

```
aws_lambda.invoke(
IN function_name TEXT,
IN payload JSON,
IN region TEXT DEFAULT NULL,
IN invocation_type TEXT DEFAULT 'RequestResponse',
IN log_type TEXT DEFAULT 'None',
IN context JSON DEFAULT NULL,
IN qualifier VARCHAR(128) DEFAULT NULL,
OUT status_code INT,
OUT payload JSON,
OUT executed_version TEXT,
OUT log_result TEXT)
```

```
aws_lambda.invoke(
IN function_name aws_commons._lambda_function_arn_1,
IN payload JSON,
IN invocation_type TEXT DEFAULT 'RequestResponse',
IN log_type TEXT DEFAULT 'None',
IN context JSON DEFAULT NULL,
IN qualifier VARCHAR(128) DEFAULT NULL,
OUT status_code INT,
OUT payload JSON,
OUT executed_version TEXT,
OUT log_result TEXT)
```

------
#### [ JSONB ]

```
aws_lambda.invoke(
IN function_name TEXT,
IN payload JSONB,
IN region TEXT DEFAULT NULL,
IN invocation_type TEXT DEFAULT 'RequestResponse',
IN log_type TEXT DEFAULT 'None',
IN context JSONB DEFAULT NULL,
IN qualifier VARCHAR(128) DEFAULT NULL,
OUT status_code INT,
OUT payload JSONB,
OUT executed_version TEXT,
OUT log_result TEXT)
```

```
aws_lambda.invoke(
IN function_name aws_commons._lambda_function_arn_1,
IN payload JSONB,
IN invocation_type TEXT DEFAULT 'RequestResponse',
IN log_type TEXT DEFAULT 'None',
IN context JSONB DEFAULT NULL,
IN qualifier VARCHAR(128) DEFAULT NULL,
OUT status_code INT,
OUT payload JSONB,
OUT executed_version TEXT,
OUT log_result TEXT
)
```

------输入参数

**function\$1name**  
Lambda 函数的标识名称。该值可以是函数名称、ARN 或部分 ARN。有关可能的格式的列表，请参阅 *AWS Lambda 开发人员指南*中的 [Lambda 函数名称格式](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestParameters)。

*payload*  
Lambda 函数的输入。格式可以是 JSON 或 JSONB。有关更多信息，请参阅 PostgreSQL 文档中的 [JSON 类型](https://www.postgresql.org/docs/current/datatype-json.html)。

*区域*  
（可选）函数的 Lambda 区域。默认情况下，RDS 会从 `function_name` 的完整 ARN 中解析 AWS 区域，或使用 RDS for PostgreSQL 数据库实例区域。如果此区域值与 `function_name` ARN 中提供的值冲突，则会引发错误。

*invocation\$1type*  
Lambda 函数的调用类型。 值区分大小写。可能的值包括：  
+ `RequestResponse` – 默认值。Lambda 函数的这种调用类型是同步的，并在结果中返回响应负载。当工作流程依赖于立即接收 Lambda 函数结果时，请使用 `RequestResponse` 调用类型。
+ `Event` – Lambda 函数的这种调用类型是异步的，并在没有返回负载的情况下立即返回。如果您不需要在工作流程开始之前了解 Lambda 函数的结果，请使用 `Event` 调用类型。
+ `DryRun` – 这种类型的调用在不允许 Lambda 函数的情况下测试访问权限。

*log\$1type*  
要在 `log_result` 输出参数中返回的 Lambda 日志类型。 值区分大小写。可能的值包括：  
+ Tail – 返回的 `log_result` 输出参数将包含执行日志的最后 4 kB。
+ None – 未返回 Lambda 日志信息。

*context*  
JSON 或 JSONB 格式的客户端上下文。要使用的字段包括 `custom` 和 `env`。

*限定符*  
标识要调用的 Lambda 函数版本的限定符。如果此值与 `function_name` ARN 中提供的值冲突，则会引发错误。输出参数

*status\$1code*  
HTTP 状态响应代码。有关更多信息，请参阅 *AWS Lambda 开发人员指南*中的 [Lambda 调用响应元素](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseElements)。

*payload*  
从运行的 Lambda 函数返回的信息。格式为 JSON 或 JSONB。

*executed\$1version*  
运行的 Lambda 函数的版本。

*log\$1result*  
如果 `log_type` 值在调用 Lambda 函数时为 `Tail`，则会返回执行日志信息。结果包含以 Base64 编码的执行日志的最后 4 kB。

## aws\$1commons.create\$1lambda\$1function\$1arn
<a name="aws_commons.create_lambda_function_arn"></a>

创建一个 `aws_commons._lambda_function_arn_1` 结构来保存 Lambda 函数名称信息。您可以在 aws\$1lambda.invoke `aws_commons.create_lambda_function_arn` 函数的 `function_name` 参数中使用 [aws\$1lambda.invoke](#aws_lambda.invoke) 函数的结果。

**语法**

```
aws_commons.create_lambda_function_arn(
    function_name TEXT,
    region TEXT DEFAULT NULL
    )
    RETURNS aws_commons._lambda_function_arn_1
```输入参数

*function\$1name*  
包含 Lambda 函数名称的必需文本字符串。该值可以是函数名称、部分 ARN 或完整 ARN。

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

## aws\$1lambda 参数
<a name="aws_lambda.parameters"></a>

在该表中，您可以找到与 `aws_lambda` 函数关联的参数。


| 参数 | 描述 | 
| --- | --- | 
| `aws_lambda.connect_timeout_ms` | 这是一个动态参数，用于设置连接到 AWS Lambda 时的最大等待时间。默认值为 `1000`。此参数允许的值为 1 - 900000。 | 
| `aws_lambda.request_timeout_ms` | 这是一个动态参数，它设置了等待来自 AWS Lambda 的响应时的最大等待时间。默认值为 `3000`。此参数允许的值为 1 - 900000。 | 
| `aws_lambda.endpoint_override` | 指定可用于连接到 AWS Lambda 的端点。空字符串会选择该区域的默认 AWS Lambda 端点。必须重启数据库，此静态参数更改才能生效。 | 

# Amazon RDS for PostgreSQL 的数据库管理员常见任务
<a name="Appendix.PostgreSQL.CommonDBATasks"></a>

数据管理员 (DBA) 在管理 Amazon RDS for PostgreSQL 数据库实例时执行各种任务。如果您是一个已经熟悉 PostgreSQL 的 DBA，那么您需要注意在硬件上运行 PostgreSQL 和 RDS for PostgreSQL 之间的一些重要区别。例如，由于它是托管服务，Amazon RDS 不允许对数据库实例进行 Shell 访问。这意味着您无法直接访问 `pg_hba.conf` 和其他配置文件。对于 RDS for PostgreSQL，通常对本地实例的 PostgreSQL 配置文件所做的更改是针对与 RDS for PostgreSQL 数据库实例关联的自定义数据库参数组做出的。有关更多信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

您也不能以与访问本地 PostgreSQL 实例相同的方式访问日志文件。要了解有关日志记录的更多信息，请参阅[RDS for PostgreSQL 数据库日志文件](USER_LogAccess.Concepts.PostgreSQL.md)。

再例如，您无法访问 PostgreSQL `superuser` 账户。在 RDS for PostgreSQL 上，`rds_superuser` 角色是权限最高的角色，它在设置时被授予 `postgres`。无论您是熟悉使用本地 PostgreSQL 还是对 RDS for PostgreSQL 完全陌生，我们都建议您了解 `rds_superuser` 角色，以及如何使用角色、用户、组和权限。有关更多信息，请参阅 [了解 PostgreSQL 角色和权限](Appendix.PostgreSQL.CommonDBATasks.Roles.md)。

以下是 RDS for PostgreSQL 的一些数据库管理员常见任务。

**Topics**
+ [RDS for PostgreSQL 中支持的排序规则](PostgreSQL-Collations.md)
+ [了解 PostgreSQL 角色和权限](Appendix.PostgreSQL.CommonDBATasks.Roles.md)
+ [PostgreSQL 中的失效连接处理](Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.md)
+ [在 Amazon RDS for PostgreSQL 上使用 PostgreSQL autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md)
+ [管理 Amazon RDS for PostgreSQL 中的高对象计数](PostgreSQL.HighObjectCount.md)
+ [管理 Amazon RDS for PostgreSQL 中的 TOAST OID 争用](Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.md)
+ [使用 RDS for PostgreSQL 支持的日志记录机制](#Appendix.PostgreSQL.CommonDBATasks.Auditing)
+ [使用 PostgreSQL 管理临时文件](PostgreSQL.ManagingTempFiles.md)
+ [将用于日志分析的 pgBadger 与 PostgreSQL 结合使用](#Appendix.PostgreSQL.CommonDBATasks.Badger)
+ [使用 PGSnapper 监控 PostgreSQL](#Appendix.PostgreSQL.CommonDBATasks.Snapper)
+ [在 RDS for PostgreSQL 中管理自定义强制转换](PostgreSQL.CustomCasts.md)
+ [RDS for PostgreSQL 中并行查询的最佳实践](PostgreSQL.ParallelQueries.md)
+ [在 RDS for PostgreSQL 数据库实例上使用参数](Appendix.PostgreSQL.CommonDBATasks.Parameters.md)

# RDS for PostgreSQL 中支持的排序规则
<a name="PostgreSQL-Collations"></a>

排序规则是一组规则，用于确定如何对存储在数据库中的字符串进行排序和比较。排序规则在计算机系统中起着重要作用，并作为操作系统的一部分包含在其中。当向语言中添加新字符或排序规则发生变化时，排序规则会随着时间的推移而变化。

排序规则库为排序规则定义特定的规则和算法。PostgreSQL 中最常用的排序规则库是 GNU C（Glibc）和 Unicode 国际化组件（ICU）。原定设置情况下，RDS for PostgreSQL 使用 Glibc 排序规则，其中包括适用于多字节字符序列的 Unicode 字符排序顺序。

当您在 RDS for PostgreSQL 中创建新的数据库实例时，它将检查操作系统中是否有可用的排序规则。`CREATE DATABASE` 命令的 PostgreSQL 参数 `LC_COLLATE` 和 `LC_CTYPE` 用于指定排序规则，该排序规则是该数据库中的原定设置排序规则。或者，您也可以在 `CREATE DATABASE` 中使用 `LOCALE` 参数来设置这些参数。这决定了数据库中字符串的原定设置排序规则以及将字符分类为字母、数字或符号的规则。您也可以选择用于列、索引或查询的排序规则。

RDS for PostgreSQL 依赖于操作系统中的 Glibc 库来提供排序规则支持。RDS for PostgreSQL 实例定期使用最新版本的操作系统进行更新。这些更新有时包含较新版本的 Glibc 库。较新版本的 Glibc 很少会更改某些字符的排序顺序或排序规则，这可能会导致数据的排序方式不同或生成无效的索引条目。如果您在更新期间发现用于排序规则的排序顺序有问题，则可能需要重建索引。

为了减少 Glibc 更新可能产生的影响，RDS for PostgreSQL 现在包含一个独立的原定设置排序规则库。这个排序规则库在 RDS for PostgreSQL 14.6、13.9、12.13、11.18、10.23 和更高的次要版本中可用。它与 Glibc 2.26-59.amzn2 兼容，并提供排序顺序稳定性以防止错误的查询结果。

# 了解 PostgreSQL 角色和权限
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles"></a>

在使用 AWS 管理控制台 创建 RDS for PostgreSQL 数据库实例时，将同时创建管理员账户。默认情况下，其名称为 `postgres`，如以下屏幕截图所示：

![\[Create database（创建数据库）页面中凭据的默认登录身份是 postgres。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/default-login-identity-apg-rpg.png)


您可以选择其他名称，而不是接受默认值（`postgres`)。如果这样做，您选择的名称必须以字母开头，并且必须介于 1 到 16 个字母数字字符之间。为简单起见，在整个指南中，我们将使用默认值 (`postgres`) 来指代此主用户账户。

如果您使用 `create-db-instance` AWS CLI 而不是 AWS 管理控制台，则可以通过将名称传递给命令中的 `master-username` 参数来创建名称。有关更多信息，请参阅 [创建 Amazon RDS 数据库实例](USER_CreateDBInstance.md)。

无论您是使用 AWS 管理控制台、AWS CLI 还是 Amazon RDS API，也无论您是使用默认 `postgres` 名称还是选择其他名称，这第一个数据库用户账户都是 `rds_superuser` 组的成员并具有 `rds_superuser` 权限。

**Topics**
+ [了解 rds\$1superuser 角色](Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser.md)
+ [控制用户对 PostgreSQL 数据库的访问](Appendix.PostgreSQL.CommonDBATasks.Access.md)
+ [委托和控制用户密码管理](Appendix.PostgreSQL.CommonDBATasks.RestrictPasswordMgmt.md)
+ [使用 SCRAM 进行 PostgreSQL 密码加密](PostgreSQL_Password_Encryption_configuration.md)

# 了解 rds\$1superuser 角色
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser"></a>

在 PostgreSQL 中，*角色*可以针对数据库中的各种对象定义一个用户、一个组或一组授予组或用户的特定权限。PostgreSQL 命令 `CREATE USER` 和 `CREATE GROUP` 已替换为更通用的 `CREATE ROLE`，并使用特定属性来区分数据库用户。数据库用户可以被视为具有 LOGIN 权限的角色。

**注意**  
仍然可以使用 `CREATE USER` 和 `CREATE GROUP` 命令。有关更多信息，请参阅 PostgreSQL 文档中的[数据库角色](https://www.postgresql.org/docs/current/user-manag.html)。

`postgres` 用户是您的 RDS for PostgreSQL 数据库实例上权限最高的数据库用户。它具有以下 `CREATE ROLE` 语句所定义的特征。

```
CREATE ROLE postgres WITH LOGIN NOSUPERUSER INHERIT CREATEDB CREATEROLE NOREPLICATION VALID UNTIL 'infinity'
```

属性 `NOSUPERUSER`、`NOREPLICATION`、`INHERIT` 和 `VALID UNTIL 'infinity'` 是 CREATE ROLE 的默认选项，除非另有说明。

默认情况下，`postgres` 拥有授予 `rds_superuser` 角色的权限以及创建角色和数据库的权限。`rds_superuser` 角色允许 `postgres` 用户执行以下操作：
+ 添加可用于 Amazon RDS 的扩展。有关更多信息，请参阅 [使用 Amazon RDS for PostgreSQL 支持的 PostgreSQL 功能](PostgreSQL.Concepts.General.FeatureSupport.md) 
+ 为用户创建角色并向用户授予权限。有关更多信息，请参阅 PostgreSQL 文档中的 [CREATE ROLE](https://www.postgresql.org/docs/current/sql-createrole.html) 和 [GRANT](https://www.postgresql.org/docs/14/sql-grant.html)。
+ 创建数据库。有关更多信息，请参阅 PostgreSQL 文档中的 [CREATE DATABASE](https://www.postgresql.org/docs/14/sql-createdatabase.html)。
+ 将 `rds_superuser` 权限授予没有这些权限的用户角色，并根据需要撤销权限。建议您仅向执行超级用户任务的那些用户授予此角色。换句话说，您可以将此角色授予数据库管理员 (DBA) 或系统管理员。
+ 向没有 `rds_superuser` 角色的数据库用户授予（和撤销）`rds_replication` 角色。
+ 向没有 `rds_superuser` 角色的数据库用户授予（和撤销）`rds_password` 角色。
+ 通过使用 `pg_stat_activity` 视图获取有关所有数据库连接的状态信息。需要时，`rds_superuser` 可以通过使用 `pg_terminate_backend` 或 `pg_cancel_backend` 停止任何连接。

在 `CREATE ROLE postgres...` 语句中，您可以看到 `postgres` 用户角色明确禁止 PostgreSQL `superuser` 权限。RDS for PostgreSQL 是一项托管服务，因此您无法访问主机操作系统，也无法使用 PostgreSQL `superuser` 账户进行连接。许多需要独立 PostgreSQL 上的 `superuser` 访问权限的任务都由 Amazon RDS 自动管理。

有关授权权限的更多信息，请参阅 PostgreSQL 文档中的 [GRANT](http://www.postgresql.org/docs/current/sql-grant.html)。

`rds_superuser` 角色是 中的几个*预定义*角色之一。RDS for PostgreSQL 数据库实例。

**注意**  
在 PostgreSQL 13 和更早版本中，*预定义*角色称为*默认*角色。

在下面的列表中，您可以找到为新 自动创建的一些其他预定义角色。RDS for PostgreSQL 数据库实例。无法更改预定义角色及其权限。无法删除、重命名或修改这些预定义角色的权限。此类尝试会导致错误。
+ **rds\$1password** – 可以为数据库用户更改密码和设置密码限制的角色。默认情况下，`rds_superuser` 角色被授予此角色，并且可以将此角色授予数据库用户。有关更多信息，请参阅 [控制用户对 PostgreSQL 数据库的访问控制用户对 PostgreSQL 的访问](Appendix.PostgreSQL.CommonDBATasks.Access.md)。
  + 对于早于 14 的 RDS for PostgreSQL 版本，`rds_password` 角色可以为数据库用户和具有 `rds_superuser` 角色的用户更改密码和设置密码限制。在 RDS for PostgreSQL 14 及更高版本中，`rds_password` 角色只能为数据库用户更改密码和设置密码限制。只有具有 `rds_superuser` 角色的用户才能对具有 `rds_superuser` 角色的其他用户执行这些操作。
+ **rdsadmin** – 具有 `superuser` 权限的管理员将对独立的 PostgreSQL 数据库执行许多管理任务，此角色专为处理这些管理任务而创建。此角色由 RDS for PostgreSQL 在内部用于许多管理任务。
+ **rdstopmgr** – Amazon RDS 在内部用于支持多可用区部署的角色。
+ **rds\$1reserved** – Amazon RDS 在内部用于保留数据库连接的角色。

# 查看角色及其权限
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles.View"></a>

根据您的 PostgreSQL 版本，您可以使用不同的命令在 RDS for PostgreSQL 数据库实例中查看预定义角色及其权限。要查看所有预定义角色，可以连接到 RDS for PostgreSQL 数据库实例，并使用 `psql` 运行以下命令。

**对于 `psql` 15 及更早版本**

连接到 RDS for PostgreSQL 数据库实例，并在 psql 中使用 `\du` 命令：

```
postgres=> \du
                                                               List of roles
    Role name    |                         Attributes                         |                          Member of
-----------------+------------------------------------------------------------+------------------------------------------------------
 postgres        | Create role, Create DB                                    +| {rds_superuser}
                 | Password valid until infinity                              |
 rds_ad          | Cannot login                                               | {}
 rds_iam         | Cannot login                                               | {}
 rds_password    | Cannot login                                               | {}
 rds_replication | Cannot login                                               | {}
 rds_superuser   | Cannot login                                               | {pg_monitor,pg_signal_backend,rds_password,rds_replication}
 rdsadmin        | Superuser, Create role, Create DB, Replication, Bypass RLS+| {}
                 | Password valid until infinity                              |
```

**对于 `psql` 16 及更高版本**

```
postgres=> \drg+
                             List of role grants
   Role name   |          Member of          |       Options       | Grantor
---------------+-----------------------------+---------------------+----------
 postgres      | rds_superuser               | INHERIT, SET        | rdsadmin
 rds_superuser | pg_checkpoint               | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | pg_monitor                  | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | pg_signal_backend           | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | pg_use_reserved_connections | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | rds_password                | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | rds_replication             | ADMIN, INHERIT, SET | rdsadmin
```

要检查没有版本依赖关系的角色成员资格，可以使用以下 SQL 查询：

```
SELECT m.rolname AS "Role name", r.rolname AS "Member of"
FROM pg_catalog.pg_roles m
JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)
LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)
LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)
WHERE m.rolname !~ '^pg_'
ORDER BY 1, 2;
```

在输出中，您可以看到 `rds_superuser` 不是数据库用户角色（无法登录），但它具有许多其他角色的权限。您还可以看到数据库用户 `postgres` 是 `rds_superuser` 角色的成员。如前所述，`postgres` 是 Amazon RDS 控制台的 **Create database**（创建数据库）页面中的默认值。如果您选择了另一个名称，则该名称将显示在角色列表中。

# 控制用户对 PostgreSQL 数据库的访问
<a name="Appendix.PostgreSQL.CommonDBATasks.Access"></a>

PostgreSQL 中的新数据库始终使用数据库 `public` 架构中的一组默认权限创建，允许所有数据库用户和角色创建对象。例如，这些权限使数据库用户能够连接数据库，并在连接后创建临时表格。

为了更好地控制用户对您在 RDS for PostgreSQL 数据库实例上创建的数据库实例的访问，我们建议您撤消这些默认 `public` 权限。撤消后，您可以更精确地为数据库用户授权，如以下过程中所示。

**为新数据库实例设置角色和权限**

假设您正在新创建的 RDS for PostgreSQL 数据库实例上设置数据库，以供几位研究人员使用，他们都需要对数据库的读写访问权限。

1. 使用 `psql`（或 pgAdmin）连接到 RDS for PostgreSQL 数据库实例：

   ```
   psql --host=your-db-instance.666666666666.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

   出现提示时请输入密码。`psql` 客户端会建立连接并显示默认的管理连接数据库 `postgres=>`，作为提示符。

1. 要阻止数据库用户在 `public` 架构中创建对象，执行以下操作：

   ```
   postgres=> REVOKE CREATE ON SCHEMA public FROM PUBLIC;
   REVOKE
   ```

1. 接下来，创建一个新数据库实例：

   ```
   postgres=> CREATE DATABASE lab_db;
   CREATE DATABASE
   ```

1. 在这个新数据库上，撤消 `PUBLIC` 架构的所有权限。

   ```
   postgres=> REVOKE ALL ON DATABASE lab_db FROM public;
   REVOKE
   ```

1. 为数据库用户创建角色。

   ```
   postgres=> CREATE ROLE lab_tech;
   CREATE ROLE
   ```

1. 为具有此角色的数据库用户提供连接到数据库的能力。

   ```
   postgres=> GRANT CONNECT ON DATABASE lab_db TO lab_tech;
   GRANT
   ```

1. 向具有 `lab_tech` 角色的所有用户授予对此数据库的所有权限。

   ```
   postgres=> GRANT ALL PRIVILEGES ON DATABASE lab_db TO lab_tech;
   GRANT
   ```

1. 创建数据库用户，如下所示：

   ```
   postgres=> CREATE ROLE lab_user1 LOGIN PASSWORD 'change_me';
   CREATE ROLE
   postgres=> CREATE ROLE lab_user2 LOGIN PASSWORD 'change_me';
   CREATE ROLE
   ```

1. 向这两个用户授予与 lab\$1tech 角色关联的权限：

   ```
   postgres=> GRANT lab_tech TO lab_user1;
   GRANT ROLE
   postgres=> GRANT lab_tech TO lab_user2;
   GRANT ROLE
   ```

此时，`lab_user1` 和 `lab_user2` 可以连接到 `lab_db` 数据库。此示例未遵循企业使用的最佳实践，其中可能包括创建多个数据库实例、不同的架构和授予有限权限。有关更多完整信息和其他方案，请参阅[管理 PostgreSQL 用户和角色](https://aws.amazon.com/blogs//database/managing-postgresql-users-and-roles/)。

有关 PostgreSQL 数据库中特权的更多信息，请参阅 PostgreSQL 文档中的 [GRANT](https://www.postgresql.org/docs/current/static/sql-grant.html) 命令。

# 委托和控制用户密码管理
<a name="Appendix.PostgreSQL.CommonDBATasks.RestrictPasswordMgmt"></a>

作为 DBA，您可能需要委托用户密码的管理。或者，您可能希望防止数据库用户更改其密码或重新配置密码限制，例如密码生命周期。要确保只有您选择的数据库用户才能更改密码设置，可以启用受限密码管理特征。激活此特征时，只有那些已被授予 `rds_password` 角色的数据库用户可以管理密码。

**注意**  
要使用受限密码管理，您的 RDS for PostgreSQL 数据库实例必须运行 PostgreSQL 10.6 或更高版本。

默认情况下，此特征为 `off`，如下所示：

```
postgres=> SHOW rds.restrict_password_commands;
  rds.restrict_password_commands
--------------------------------
 off
(1 row)
```

要启用此特征，请使用自定义参数组并将 `rds.restrict_password_commands` 的设置更改为 1。一定要重新启动 RDS for PostgreSQL 数据库实例，此设置才能生效。

激活此特征后，以下 SQL 命令需要 `rds_password` 权限：

```
CREATE ROLE myrole WITH PASSWORD 'mypassword';
CREATE ROLE myrole WITH PASSWORD 'mypassword' VALID UNTIL '2023-01-01';
ALTER ROLE myrole WITH PASSWORD 'mypassword' VALID UNTIL '2023-01-01';
ALTER ROLE myrole WITH PASSWORD 'mypassword';
ALTER ROLE myrole VALID UNTIL '2023-01-01';
ALTER ROLE myrole RENAME TO myrole2;
```

如果密码使用 MD5 哈希算法，重命名角色 (`ALTER ROLE myrole RENAME TO newname`) 也会受到限制。

激活此特征后，在没有 `rds_password` 角色权限的情况下尝试这些 SQL 命令中的任何一个都会生成以下错误：

```
ERROR: must be a member of rds_password to alter passwords
```

我们建议您仅将 `rds_password` 授予少数几个仅用于密码管理的角色。如果您将 `rds_password` 权限授予没有 `rds_superuser` 权限的数据库用户，则还需要授他们 `CREATEROLE` 属性。

请确保您验证了密码要求，例如客户端上的过期时间以及所需的复杂性。如果您使用自己的客户端实用程序进行与密码相关的更改，则该实用程序需要是 `rds_password` 的成员并具有 `CREATE ROLE` 权限。

# 使用 SCRAM 进行 PostgreSQL 密码加密
<a name="PostgreSQL_Password_Encryption_configuration"></a>

在对密码进行加密时，*加盐质询响应身份验证机制（SCRAM）*是 PostgreSQL 的默认消息摘要（MD5）算法的替代方案。―般认为 SCRAM 身份验证机制比 MD5 更安全。要了解有关这两种不同的密码保护方法的更多信息，请参阅 PostgreSQL 文档中的[密码身份验证](https://www.postgresql.org/docs/14/auth-password.html)。

我们建议您使用 SCRAM 而不是 MD5 作为您的 RDS for PostgreSQL 数据库实例的密码加密方案。这是一种加密质询-响应机制，它使用 scram-sha-256 算法进行密码身份验证和加密。

要支持 SCRAM，您可能需要更新客户端应用程序的库。例如，42.2.0 之前的 JDBC 版本不支持 SCRAM。有关更多信息，请参阅 PostgreSQL JDBC 驱动程序文档中的 [PostgreSQL JDBC 驱动程序](https://jdbc.postgresql.org/changelogs/2018-01-17-42.2.0-release/)。有关其他 PostgreSQL 驱动程序和 SCRAM 支持的列表，请参阅 PostgreSQL 文档中的[驱动程序列表](https://wiki.postgresql.org/wiki/List_of_drivers)。

RDS for PostgreSQL 版本 13.1 和更高版本支持 scram-sha-256。这些版本还可让您将数据库实例配置为需要 SCRAM，如以下过程所述。

## 设置 RDS for PostgreSQL 数据库实例以要求使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.preliminary"></a>

您可以要求 RDS for PostgreSQL 数据库实例仅接受使用 scram-sha-256 算法的密码。

**重要**  
对于带有 PostgreSQL 数据库的现有 RDS 代理，如果您将数据库身份验证修改为仅使用 `SCRAM`，代理将在长达 60 秒的时间内不可用。要避免此问题，请执行以下操作之一：  
确保数据库同时允许 `SCRAM` 和 `MD5` 身份验证。
要仅使用 `SCRAM` 身份验证，请创建一个新代理，将应用程序流量迁移到新代理，然后删除先前与数据库关联的代理。

在对系统进行更改之前，请务必了解完整的过程，如下所示：
+ 获取有关所有数据库用户的所有角色和密码加密的信息。
+ 仔细检查 RDS for PostgreSQL 数据库实例的参数设置，以了解用于控制密码加密的参数。
+ 如果您的 RDS for PostgreSQL 数据库实例使用默认参数组，您需要创建自定义数据库参数组，然后将其应用到您的 RDS for PostgreSQL 数据库实例，以便您可以在需要时修改参数。如果您的 RDS for PostgreSQL 数据库实例使用自定义参数组，您可以稍后根据需要在此过程中修改必要的参数。
+ 将 `password_encryption` 参数更改为 `scram-sha-256`。
+ 通知所有数据库用户他们需要更新密码。对您的 `postgres` 账户执行相同的操作。使用 scram-sha-256 算法对新密码进行加密和存储。
+ 验证是否使用加密类型对所有密码加密。
+ 如果所有密码都使用 scram-sha-256，您可以将 `rds.accepted_password_auth_method` 参数从 `md5+scram` 更改为 `scram-sha-256`。

**警告**  
仅将 `rds.accepted_password_auth_method` 更改为 scram-sha-256 之后，使用 `md5` 加密的密码的任何用户（角色）都将无法连接。

### 做好准备，以要求 RDS for PostgreSQL 数据库实例使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.getting-ready"></a>

在对 RDS for PostgreSQL 数据库实例进行任何更改之前，检查所有现有的数据库用户账户。另外，请检查用于密码的加密类型。您可以使用 `rds_tools` 扩展来执行这些任务。要了解哪些 PostgreSQL 版本支持 `rds_tools`，请参阅 [Extension versions for Amazon RDS for PostgreSQL](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)。

**获取数据库用户（角色）和密码加密方法的列表**

1. 使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，如下所示。

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

1. 安装 `rds_tools` 扩展。

   ```
   postgres=> CREATE EXTENSION rds_tools;
   CREATE EXTENSION
   ```

1. 获取角色和加密的列表。

   ```
   postgres=> SELECT * FROM 
         rds_tools.role_password_encryption_type();
   ```

   您将看到类似以下内容的输出。

   ```
          rolname        | encryption_type
   ----------------------+-----------------
    pg_monitor           |
    pg_read_all_settings |
    pg_read_all_stats    |
    pg_stat_scan_tables  |
    pg_signal_backend    |
    lab_tester           | md5
    user_465             | md5
    postgres             | md5
   (8 rows)
   ```

### 创建自定义数据库参数组
<a name="PostgreSQL_Password_Encryption_configuration.custom-parameter-group"></a>

**注意**  
如果您的 RDS for PostgreSQL 数据库实例已使用自定义参数组，您不需要创建新参数组。

有关 Amazon RDS 的参数组的概述，请参阅[在 RDS for PostgreSQL 数据库实例上使用参数](Appendix.PostgreSQL.CommonDBATasks.Parameters.md)。

用于密码的密码加密类型在一个参数（即 `password_encryption`）中设置。 RDS for PostgreSQL 数据库实例允许的加密在另一个参数 `rds.accepted_password_auth_method` 中设置。更改其中任何一个的默认值都要求您创建自定义数据库参数组，然后将其应用到您的实例。

也可以使用 AWS 管理控制台 或 RDS API 创建自定义数据库参数组。有关更多信息，请参阅。

现在可以将自定义参数组与数据库实例关联。

**创建自定义数据库参数组**

1. 使用 CLI 命令 `[create-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-parameter-group.html) ` 创建自定义数据库参数组。此示例使用 `postgres13` 作为此自定义参数组的来源。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds create-db-parameter-group --db-parameter-group-name 'docs-lab-scram-passwords' \
     --db-parameter-group-family postgres13  --description 'Custom parameter group for SCRAM'
   ```

   对于：Windows

   ```
   aws rds create-db-parameter-group --db-parameter-group-name "docs-lab-scram-passwords" ^
     --db-parameter-group-family postgres13  --description "Custom DB parameter group for SCRAM"
   ```

1. 使用 CLI 命令 `[modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html)` 将此自定义参数组应用于 RDS for PostgreSQL 数据库集群。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds modify-db-instance --db-instance-identifier 'your-instance-name' \
           --db-parameter-group-name "docs-lab-scram-passwords
   ```

   对于：Windows

   ```
   aws rds modify-db-instance --db-instance-identifier "your-instance-name" ^
           --db-parameter-group-name "docs-lab-scram-passwords
   ```

   要将 RDS for PostgreSQL 数据库实例与您的自定义数据库参数组重新同步，您需要重启集群的主实例和所有其他实例。为了尽量减少对用户的影响，请安排在常规维护时段内执行此操作。

### 配置密码加密以使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.configure-password-encryption"></a>

RDS for PostgreSQL 数据库实例使用的密码加密机制在数据库参数组的 `password_encryption` 参数中设置。允许的值为未设置、`md5` 或 `scram-sha-256`。默认值取决于 RDS for PostgreSQL 版本，如下所示：
+ RDS for PostgreSQL 14 和更高版本 – 默认为 `scram-sha-256`
+ RDS for PostgreSQL 13 – 默认为 `md5`

使用附加到 RDS for PostgreSQL 数据库实例的自定义数据库参数组，您可以修改密码加密参数的值。

![\[接下来，RDS 控制台显示 RDS for PostgreSQL 的 password_encryption 参数的默认值。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/rpg-pwd-encryption-md5-scram-1.png)


**将密码加密设置更改为 scram-sha-256**
+ 将密码加密的值更改为 scram-sha-256，如下所示。可以立即应用更改，因为参数是动态的，这样，无需重新启动即可使更改生效。

  对于 Linux、macOS 或 Unix：

  ```
  aws rds modify-db-parameter-group --db-parameter-group-name \
    'docs-lab-scram-passwords' --parameters 'ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate'
  ```

  对于：Windows

  ```
  aws rds modify-db-parameter-group --db-parameter-group-name ^
    "docs-lab-scram-passwords" --parameters "ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate"
  ```

### 将用户角色的密码迁移到 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.migrating-users"></a>

您可以将用户角色的密码迁移到 SCRAM，如下所述。

**将数据库用户（角色）密码从 MD5 迁移到 SCRAM**

1. 以管理员用户身份（默认用户名 `postgres`）登录，如下所示。

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

1. 通过使用以下命令，在 RDS for PostgreSQL 数据库实例上检查 `password_encryption` 参数的设置。

   ```
   postgres=> SHOW password_encryption;
    password_encryption
   ---------------------
    md5
    (1 row)
   ```

1. 将此参数的值更改为 scram-sha-256。有关更多信息，请参阅 [配置密码加密以使用 SCRAM](#PostgreSQL_Password_Encryption_configuration.configure-password-encryption)。

1.  再次检查该值，以确保它现在已设置为 `scram-sha-256`，如下所示。

   ```
   postgres=> SHOW password_encryption;
    password_encryption
   ---------------------
    scram-sha-256
    (1 row)
   ```

1. 通知所有数据库用户更改其密码。请确保还要更改您自己的用于 `postgres` 账户的密码（具有 `rds_superuser` 权限的数据库用户）。

   ```
   labdb=> ALTER ROLE postgres WITH LOGIN PASSWORD 'change_me';
   ALTER ROLE
   ```

1. 对于您的 RDS for PostgreSQL 数据库实例上的所有数据库重复此过程。

### 更改参数以要求使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.require-scram"></a>

这是该过程的最后一步。在以下过程中进行更改后，任何仍对密码使用 `md5` 加密的用户账户（角色）都将无法登录到 RDS for PostgreSQL 数据库实例。

`rds.accepted_password_auth_method` 指定 RDS for PostgreSQL 数据库实例在登录过程中接受的用户密码加密方法。默认值为 `md5+scram`，这意味着可以接受任一种方法。在下面的图中，您可以找到此参数的默认设置。

![\[RDS 控制台显示 rds.accepted_password_auth_method 参数的默认值和允许的值。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/pwd-encryption-md5-scram-2.png)


此参数允许的值仅为 `md5+scram` 或 `scram`。如果将此参数值更改为 `scram`，则必须使用这种方法。

**更改参数值以要求对密码进行 SCRAM 身份验证**

1. 验证 RDS for PostgreSQL 数据库实例上所有数据库的所有数据库用户密码是否使用 `scram-sha-256` 进行密码加密。为此，查询 `rds_tools` 以获得角色（用户）和加密类型，如下所示。

   ```
   postgres=> SELECT * FROM rds_tools.role_password_encryption_type();
     rolname        | encryption_type
     ----------------------+-----------------
     pg_monitor           |
     pg_read_all_settings |
     pg_read_all_stats    |
     pg_stat_scan_tables  |
     pg_signal_backend    |
     lab_tester           | scram-sha-256
     user_465             | scram-sha-256
     postgres             | scram-sha-256
     ( rows)
   ```

1. 在您的 RDS for PostgreSQL 数据库实例中的所有数据库实例中重复此查询。

   如果所有密码都使用 scram-sha-256，您可以继续操作。

1. 将接受的密码身份验证的值更改为 scram-sha-256，如下所示。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds modify-db-parameter-group --db-parameter-group-name 'docs-lab-scram-passwords' \
     --parameters 'ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate'
   ```

   对于：Windows

   ```
   aws rds modify-db-parameter-group --db-parameter-group-name "docs-lab-scram-passwords" ^
     --parameters "ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate"
   ```

# PostgreSQL 中的失效连接处理
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling"></a>

当客户端应用程序已放弃或异常终止，但数据库会话在服务器上仍保持活动状态时，就会出现失效连接。当客户端进程崩溃或意外终止，但没有正确地关闭其数据库连接或取消正在进行的请求时，通常会出现这种情况。

当服务器进程处于空闲状态或试图向客户端发送数据时，PostgreSQL 可以高效地识别和清理失效连接。但是，对于处于空闲状态、等待客户端输入或当前正在运行查询的会话，检测过程颇具挑战性。为了处理这些情况，PostgreSQL 提供了 `tcp_keepalives_*`、`tcp_user_timeout` 和 `client_connection_check_interval` 参数。

**Topics**
+ [了解 TCP keepalive](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Understanding)
+ [RDS for PostgreSQL 中的关键 TCP keepalive 参数](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Parameters)
+ [TCP keepalive 设置的使用案例](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases)
+ [最佳实践](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.BestPractices)

## 了解 TCP keepalive
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Understanding"></a>

TCP Keepalive 是一种协议级机制，有助于保持和验证连接完整性。每个 TCP 连接都保持内核级别的设置，这些设置控制着 keepalive 行为。当 keepalive 计时器到期时，系统会执行以下操作：
+ 发送一个没有数据且设置了 ACK 标志的探测数据包。
+ 根据 TCP/IP 规范，期待来自远程端点的响应。
+ 根据响应或无响应来管理连接状态。

## RDS for PostgreSQL 中的关键 TCP keepalive 参数
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Parameters"></a>


| 参数 | 说明 | 默认值 | 
| --- |--- |--- |
| tcp\$1keepalives\$1idle | Specifies number of seconds of inactivity before sending keepalive message. | 300 | 
| tcp\$1keepalives\$1interval | Specifies number of seconds between retransmissions of unacknowledged keepalive messages. | 30 | 
| tcp\$1keepalives\$1count | Maximum lost keepalive messages before declaring connection dead | 2 | 
| tcp\$1user\$1timeout | Specifies how long (in Milliseconds) unacknowledged data can remain before forcibly closing the connection. | 0 | 
| client\$1connection\$1check\$1interval | Sets the interval (in Milliseconds) for checking client connection status during long-running queries. This ensures quicker detection of closed connections. | 0 | 

## TCP keepalive 设置的使用案例
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases"></a>

### 使空闲会话保持连接状态
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases.KeepingAlive"></a>

为防止空闲连接因处于非活动状态而被防火墙或路由器终止：
+ 配置 `tcp_keepalives_idle` 定期发送 keepalive 数据包。

### 检测失效连接
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases.DetectingDead"></a>

要迅速检测失效连接：
+ 调整 `tcp_keepalives_idle`、`tcp_keepalives_interval` 和 `tcp_keepalives_count`。例如，使用 Aurora PostgreSQL 默认值，检测到失效连接大约需要一分钟（2 次探测 × 30 秒）。降低这些值可以加快检测速度。
+ 使用 `tcp_user_timeout` 来指定等待确认的最长时间。

TCP keepalive 设置有助于内核检测失效连接，但在使用套接字之前，PostgreSQL 可能无法执行操作。如果会话正在运行长时间的查询，则可能只有在查询完成后才能检测到失效连接。在 PostgreSQL 14 及更高版本中，`client_connection_check_interval` 可以通过在查询执行期间定期轮询套接字来加快失效连接检测。

## 最佳实践
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.BestPractices"></a>
+ **设置合理的 keepalive 间隔：**调整 `tcp_user_timeout`、`tcp_keepalives_idle`、`tcp_keepalives_count` 和 `tcp_keepalives_interval`，以平衡检测速度与资源用量。
+ **针对环境进行优化：**使设置与网络行为、防火墙策略和会话需求相一致。
+ **利用 PostgreSQL 功能**：在 PostgreSQL 14 及更高版本中使用 `client_connection_check_interval` 来进行高效的连接检查。

# 在 Amazon RDS for PostgreSQL 上使用 PostgreSQL autovacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum"></a>

我们强烈建议您使用 Autovacuum 功能来保持 PostgreSQL 数据库实例正常运行。Autovacuum 自动启动 VACUUM 和 ANALYZE 命令。它会检查包含大量插入的、更新的或删除的元组的表。进行此检查后，它会通过从 PostgreSQL 数据库中删除过时的数据或元组来回收存储。

在使用任何默认 PostgreSQL 数据库参数组创建的 RDS for PostgreSQL 数据库实例上，会默认启用 autovacuum。默认情况下，还会设置与 Autovacuum 功能关联的其他配置参数。这些默认值是通用值，因此可以针对特定工作负载优化与 Autovacuum 功能关联的某些参数。

在下文中，您可以了解有关 autovacuum 功能以及如何为 RDS for PostgreSQL 数据库实例优化其部分参数的更多信息。有关高级信息，请参阅[使用 PostgreSQL 的最佳实践](CHAP_BestPractices.md#CHAP_BestPractices.PostgreSQL)。

**Topics**
+ [为 Autovacuum 分配内存](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory)
+ [减少事务 ID 重叠的可能性](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)
+ [确定数据库中的表是否需要 vacuum 操作](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.NeedVacuuming.md)
+ [确定哪些表当前符合 Autovacuum 条件](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.EligibleTables.md)
+ [确定 Autovacuum 当前是否正在运行以及运行时长](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AutovacuumRunning.md)
+ [执行手动 vacuum 冻结](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md)
+ [在 Autovacuum 正在运行时重新为表建立索引](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Reindexing.md)
+ [使用大型索引管理 autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md)
+ [其他影响 Autovacuum 的参数](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.OtherParms.md)
+ [设置表级别 Autovacuum 参数](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.TableParameters.md)
+ [记录 autovacuum 和 vacuum 活动](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging.md)
+ [了解对无效数据库使用 autovacuum 的行为](appendix.postgresql.commondbatasks.autovacuumbehavior.md)
+ [识别并解决 RDS for PostgreSQL 中的积极真空拦截器](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.md)

## 为 Autovacuum 分配内存
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory"></a>

影响Autovacuum 性能的最重要参数之一是 [https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM) 参数。在 RDS for PostgreSQL 版本 14 及更早版本中，`autovacuum_work_mem` 参数设置为 -1，表示改用 `maintenance_work_mem` 的设置。对于所有其它版本，`autovacuum_work_mem` 由 GREATEST(\$1DBInstanceClassMemory/32768\$1, 65536) 决定。

手动 vacuum 操作始终使用 `maintenance_work_mem` 设置，默认设置为 GREATEST(\$1DBInstanceClassMemory/63963136\$11024\$1, 65536)，也可以使用 `SET` 命令在会话级别对其进行调整，以进行更有针对性的手动 `VACUUM` 操作。

`autovacuum_work_mem` 确定 autovacuum 在对索引执行 vacuum 操作时，用于容纳无效元组 (`pg_stat_all_tables.n_dead_tup`) 的标识符的内存。

当执行计算以确定 `autovacuum_work_mem` 参数的值时，请注意以下事项：
+ 如果将此参数设得过低，则 vacuum 过程可能必须扫描表多次才能完成其工作。此类多次扫描可能会对性能产生负面影响。对于较大的实例，将 `maintenance_work_mem` 或 `autovacuum_work_mem` 设置为至少 1 GB，可以提高对包含大量无效元组的表执行 vacuum 操作的性能。但是，在 PostgreSQL 版本 16 及更早版本中，vacuum 的内存使用量上限为 1 GB，这足以单次处理大约 1.79 亿个无效元组。如果表的无效元组比这更多，vacuum 将需要多次遍历表的索引，从而显著增加所需的时间。从 PostgreSQL 版本 17 开始，没有 1 GB 的限制，自动真空可以使用基数树处理超过 1.79 亿个元组。

  元组标识符的大小为 6 个字节。要估算对表的索引执行 vacuum 操作所需的内存，请查询 `pg_stat_all_tables.n_dead_tup` 来找到无效元组的数量，然后将该数字乘以 6，以确定单次对索引执行 vacuum 操作所需的内存。您可以使用以下查询：

  ```
  SELECT
      relname AS table_name,
      n_dead_tup,
      pg_size_pretty(n_dead_tup * 6) AS estimated_memory
  FROM
      pg_stat_all_tables
  WHERE
      relname = 'name_of_the_table';
  ```
+ `autovacuum_work_mem` 参数可与 `autovacuum_max_workers` 参数结合使用。`autovacuum_max_workers` 中的每个工作进程均可使用您分配的内存。如果您有多个小型表，请分配更多的 `autovacuum_max_workers` 和更少的 `autovacuum_work_mem`。如果您拥有大型表（大于 100 GB），请分配更多内存和更少的工作进程。您需要分配有足够的内存才能对最大的表成功完成操作。因此，请确保工作进程和内存的组合等于要分配的总内存。

## 减少事务 ID 重叠的可能性
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming"></a>

在一些情况下，与 Autovacuum 相关的参数组设置可能不够积极，无法阻止事务 ID 重叠。为解决此问题，RDS for PostgreSQL 提供了自动调整 Autovacuum 参数值的机制。*适应性 autovacuum* 是 RDS for PostgreSQL 的一项功能。在 PostgreSQL 文档中找到了 [TransactionID 重叠](https://www.postgresql.org/docs/current/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)的详细说明。

默认情况下，动态参数 `rds.adaptive_autovacuum` 设置为 ON 的 RDS for PostgreSQL 实例启用适应性 autovacuum。强烈建议您保持启用此选项。不过，要关闭适应性 Autovacuum 参数优化，请将 `rds.adaptive_autovacuum` 参数设置为 0 或 OFF。

即使在 Amazon RDS 优化 Autovacuum 参数时，仍可能出现事务 ID 重叠。鼓励您为事务 ID 重叠实施 Amazon CloudWatch 警报。有关更多信息，请参阅 AWS 数据库博客上的贴子[在 RDS for PostgreSQL 中为事务 ID 重叠实施预警系统](https://aws.amazon.com/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/)。

启用适应性 autovacuum 参数优化后，当 CloudWatch 指标 `MaximumUsedTransactionIDs` 达到 `autovacuum_freeze_max_age` 参数值或 500000000 中的较大值时，Amazon RDS 将开始调整 autovacuum 参数。

如果表继续倾向于事务 ID 重叠，则 Amazon RDS 将继续调整 autovacuum 的参数。其中每次调整都会将更多资源专用于 Autovacuum 以避免重叠。Amazon RDS 更新以下与 Autovacuum 相关的参数：
+ [Autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)
+ [ Autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)
+  [https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM) 
+  [Autovacuum\$1naptime](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-NAPTIME) 

仅当新值使 Autovacuum 更积极时，RDS 才会修改这些参数。在数据库实例上的内存中修改参数。不会更改参数组中的值。要查看当前内存中的设置，请使用 PostgreSQL [SHOW](https://www.postgresql.org/docs/current/sql-show.html) SQL 命令。

当 Amazon RDS 修改其中任何 autovacuum 参数时，它会为受影响的数据库实例生成事件。此事件在 AWS 管理控制台 上和通过 Amazon RDS API 显示。在 `MaximumUsedTransactionIDs` CloudWatch 指标返回的值低于阈值后，Amazon RDS 会将内存中与 autovacuum 相关的参数重置回参数组中指定的值。然后，它会生成另一个与此更改对应的事件。

# 确定数据库中的表是否需要 vacuum 操作
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.NeedVacuuming"></a>

您可以使用以下查询显示数据库中解冻事务的数目。数据库的 `datfrozenxid` 行的 `pg_database` 列是显示在该数据库中的正常事务 ID 的下限。此列是数据库中每个表的 `relfrozenxid` 值的最小值。

```
SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY age(datfrozenxid) desc limit 20;
```

例如，运行上述查询的结果可能如下所示。

```
datname    | age
mydb       | 1771757888
template0  | 1721757888
template1  | 1721757888
rdsadmin   | 1694008527
postgres   | 1693881061
(5 rows)
```

当数据库的期限达到 20 亿个事务 ID 时，事务 ID (XID) 重叠将出现，并且数据库将变成只读状态。您可以使用此查询来生成指标，并且一天可运行几次。默认情况下，将设置 Autovacuum 以确保事务期限不超过 200000000 ()。[https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE)

示例监控策略可能类似于：
+ 将 `autovacuum_freeze_max_age` 值设置为 2 亿个事务。
+ 如果表中的解冻事务达到 5 亿个，则会触发低严重性警报。这不是一个不合理的值，但它可能指示 Autovacuum 未保持同步。
+ 如果表期限为 10 亿，这应被视为要采取操作的警报。通常，您出于性能原因，需要使期限更接近 `autovacuum_freeze_max_age`。建议您使用以下建议进行调查。
+ 如果表达到 15 亿个未执行 vacuum 操作的事务，则这会触发高严重性警报。根据数据库使用事务 ID 的频率，此警报将指示系统运行 Autovacuum 的时间不多了。在这种情况下，建议您立即解决此问题。

如果表持续违反这些阈值，请进一步修改 autovacuum 参数。默认情况下，手动使用 VACUUM（已禁用基于成本的延迟）比使用默认的 Autovacuum 更积极，但对整个系统来说也更具侵入性。

我们建议执行下列操作：
+ 了解和启用监控机制，以便您了解最早的事务的期限。

  有关创建提醒您事务 ID 重叠的过程的信息，请参阅 AWS 数据库博客帖子 [Implement an early warning system for transaction ID wraparound in Amazon RDS for PostgreSQL](https://aws.amazon.com/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/)。
+ 对于更复杂的表，在维护时段内定期执行手动 vacuum 冻结操作，并依赖 Autovacuum。有关执行手动 vacuum 冻结的信息，请参阅[执行手动 vacuum 冻结](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md)。

# 确定哪些表当前符合 Autovacuum 条件
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.EligibleTables"></a>

通常，它是需要执行 vacuum 操作的一个或两个表。其 `relfrozenxid` 值大于 `autovacuum_freeze_max_age` 中的事务数的表始终是 Autovacuum 的目标。否则，如果元组数因上一个 VACUUM 超出 vacuum 阈值而变得过时，则对表执行 vacuum 操作。

[Autovacuum 阈值](https://www.postgresql.org/docs/current/static/routine-vacuuming.html#AUTOVACUUM)的定义如下：

```
Vacuum-threshold = vacuum-base-threshold + vacuum-scale-factor * number-of-tuples
```

其中，`vacuum base threshold` 为 `autovacuum_vacuum_threshold`，`vacuum scale factor` 为 `autovacuum_vacuum_scale_factor`，而 `number of tuples` 为 `pg_class.reltuples`。

在连接到数据库时，运行以下查询可查看 autovacuum 认为有资格执行 vacuum 操作的表的列表。

```
WITH vbt AS (SELECT setting AS autovacuum_vacuum_threshold FROM 
pg_settings WHERE name = 'autovacuum_vacuum_threshold'),
vsf AS (SELECT setting AS autovacuum_vacuum_scale_factor FROM 
pg_settings WHERE name = 'autovacuum_vacuum_scale_factor'), 
fma AS (SELECT setting AS autovacuum_freeze_max_age FROM pg_settings WHERE name = 'autovacuum_freeze_max_age'),
sto AS (select opt_oid, split_part(setting, '=', 1) as param,
split_part(setting, '=', 2) as value from (select oid opt_oid, unnest(reloptions) setting from pg_class) opt)
SELECT '"'||ns.nspname||'"."'||c.relname||'"' as relation,
pg_size_pretty(pg_table_size(c.oid)) as table_size,
age(relfrozenxid) as xid_age,
coalesce(cfma.value::float, autovacuum_freeze_max_age::float) autovacuum_freeze_max_age,
(coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) +
coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples)
AS autovacuum_vacuum_tuples, n_dead_tup as dead_tuples FROM
pg_class c join pg_namespace ns on ns.oid = c.relnamespace 
join pg_stat_all_tables stat on stat.relid = c.oid join vbt on (1=1) join vsf on (1=1) join fma on (1=1)
left join sto cvbt on cvbt.param = 'autovacuum_vacuum_threshold' and c.oid = cvbt.opt_oid 
left join sto cvsf on cvsf.param = 'autovacuum_vacuum_scale_factor' and c.oid = cvsf.opt_oid
left join sto cfma on cfma.param = 'autovacuum_freeze_max_age' and c.oid = cfma.opt_oid
WHERE c.relkind = 'r' and nspname <> 'pg_catalog'
AND (age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float)
OR coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * 
c.reltuples <= n_dead_tup)
ORDER BY age(relfrozenxid) DESC LIMIT 50;
```

# 确定 Autovacuum 当前是否正在运行以及运行时长
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AutovacuumRunning"></a>

如果需要手动对表执行 vacuum 操作，确保确定 autovacuum 当前是否正在运行。如果它当前正在运行，则您可能需要调整参数以使其更高效地运行，或者暂时禁用 autovacuum 以便手动运行 VACUUM。

使用以下查询来确定 Autovacuum 是否正在运行、它已运行的时长以及它是否正在等待其他会话。

```
SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query
FROM pg_stat_activity 
WHERE upper(query) LIKE '%VACUUM%' 
ORDER BY xact_start;
```

在运行查询后，您应看到类似以下内容的输出。

```
 datname | usename  |  pid  | state  | wait_event |      xact_runtime       | query  
 --------+----------+-------+--------+------------+-------------------------+--------------------------------------------------------------------------------------------------------
 mydb    | rdsadmin | 16473 | active |            | 33 days 16:32:11.600656 | autovacuum: VACUUM ANALYZE public.mytable1 (to prevent wraparound)
 mydb    | rdsadmin | 22553 | active |            | 14 days 09:15:34.073141 | autovacuum: VACUUM ANALYZE public.mytable2 (to prevent wraparound)
 mydb    | rdsadmin | 41909 | active |            | 3 days 02:43:54.203349  | autovacuum: VACUUM ANALYZE public.mytable3
 mydb    | rdsadmin |   618 | active |            | 00:00:00                | SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query+
         |          |       |        |            |                         | FROM pg_stat_activity                                                                                 +
         |          |       |        |            |                         | WHERE query like '%VACUUM%'                                                                           +
         |          |       |        |            |                         | ORDER BY xact_start;                                                                                  +
```

有多个问题可能会导致长时间运行 Autovacuum 会话（即，多天）。最常见的问题是，对于表的大小或更新速率来说，设置的 [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) 参数值太小。

建议您使用以下公式来设置 `maintenance_work_mem` 参数值。

```
GREATEST({DBInstanceClassMemory/63963136*1024},65536)
```

短时间运行的 Autovacuum 会话还可以指示以下问题：
+ 它可以指示，对于工作负载而言，`autovacuum_max_workers` 不足。在这种情况下，您将需要指示工作线程数。
+ 它可以指示存在索引损坏（autovacuum 将发生崩溃并在同一关系上重新启动，但毫无进展）。在这种情况下，运行手动 `vacuum freeze verbose table` 以查看准确原因。

# 执行手动 vacuum 冻结
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze"></a>

您可能需要对已具有正在运行的 vacuum 进程的表执行手动 vacuum 操作。如果您已使用接近 20 亿个事务（或高于您监控的任何阈值）的期限标识表，则这会很有用。

以下步骤是指导原则，此过程存在几种变化。例如，在测试期间，假设您发现设定的 [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) 参数值过小，并且您需要立即对表采取措施。不过，可能您不希望此时恢复实例。通过使用前几节中的查询，您可以确定哪个表存在问题，并找到长时间运行的 Autovacuum 会话。您知道您需要更改 `maintenance_work_mem` 参数设置，但您还需要立即采取行动，对有问题的表执行 vacuum 操作。以下过程说明了在此情况下应采取的措施。

**手动执行 vacuum 冻结**

1. 打开针对包含要执行 vacuum 操作的表的数据库的两个会话。对于第二个会话，使用“screen”或其他维护会话的实用工具 (如果您的连接已中断)。

1. 在第一个会话中，获取正在表上运行的 autovacuum 会话的进程 ID (PID)。

   运行以下查询可获取 Autovacuum 会话的 PID。

   ```
   SELECT datname, usename, pid, current_timestamp - xact_start 
   AS xact_runtime, query
   FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' ORDER BY 
   xact_start;
   ```

1. 在第二个会话中，计算该操作所需的内存量。在此示例中，我们确定自己最多可以为该操作使用 2GB 的内存，因此，我们将当前会话的 [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) 设置为 2 GB。

   ```
   SET maintenance_work_mem='2 GB';
   SET
   ```

1. 在第二个会话中，为表发出 `vacuum freeze verbose` 命令。详细设置很有用，因为虽然 PostgreSQL 中当前没有进度报告，但您可以查看活动。

   ```
   \timing on
   Timing is on.
   vacuum freeze verbose pgbench_branches;
   ```

   ```
   INFO:  vacuuming "public.pgbench_branches"
   INFO:  index "pgbench_branches_pkey" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  index "pgbench_branches_test_index" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  "pgbench_branches": found 0 removable, 50 nonremovable row versions 
        in 43 out of 43 pages
   DETAIL:  0 dead row versions cannot be removed yet.
   There were 9347 unused item pointers.
   0 pages are entirely empty.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   VACUUM
   Time: 2.765 ms
   ```

1. 在第一个会话中，如果 autovacuum 阻止 vacuum 会话，`pg_stat_activity` 显示 vacuum 会话的等待为 `T`。在此情况下，您需要终止 autovacuum 进程，如下所示。

   ```
   SELECT pg_terminate_backend('the_pid'); 
   ```
**注意**  
某些较低版本的 Amazon RDS 无法使用上述命令终止 autovacuum 进程，并且会失败，显示以下错误：`ERROR: 42501: must be a superuser to terminate superuser process LOCATION: pg_terminate_backend, signalfuncs.c:227`。

   此时，您的会话将开始。由于此表可能位于其工作列表中的最高位置，因此 Autovacuum 将立即重新启动。

1. 在第二个会话中启动您的 `vacuum freeze verbose` 命令，然后终止第一个会话中的 autovacuum 过程。

# 在 Autovacuum 正在运行时重新为表建立索引
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Reindexing"></a>

如果索引已损坏，Autovacuum 将继续处理表并失败。在此情况下，如果您尝试执行手动 vacuum 操作，您将收到一条与以下内容类似的错误消息。

```
postgres=>  vacuum freeze pgbench_branches;
ERROR: index "pgbench_branches_test_index" contains unexpected 
   zero page at block 30521
HINT: Please REINDEX it.
```

当索引损坏并且 autovacuum 尝试在表上运行时，您将处理已经正在运行的 autovacuum 会话。在您发出 [REINDEX](https://www.postgresql.org/docs/current/static/sql-reindex.html) 命令时，将删除表上的排他锁。将阻止写入操作以及使用该特定索引的读取操作。

**在对表运行 Autovacuum 时重新为表建立索引**

1. 打开针对包含要执行 vacuum 操作的表的数据库的两个会话。对于第二个会话，使用“screen”或其他维护会话的实用工具 (如果您的连接已中断)。

1. 在第一个会话中，获取正在表上运行的 Autovacuum 会话的 PID。

   运行以下查询可获取 Autovacuum 会话的 PID。

   ```
   SELECT datname, usename, pid, current_timestamp - xact_start 
   AS xact_runtime, query
   FROM pg_stat_activity WHERE upper(query) like '%VACUUM%' ORDER BY 
   xact_start;
   ```

1. 在第二个会话中，发出 reindex 命令。

   ```
   \timing on
   Timing is on.
   reindex index pgbench_branches_test_index;
   REINDEX
     Time: 9.966 ms
   ```

1. 在第一个会话中，如果 autovacuum 阻止该过程，您将在 `pg_stat_activity` 中看到 vacuum 会话的等待为“T”。在此情况下，您将终止 autovacuum 过程。

   ```
   SELECT pg_terminate_backend('the_pid');
   ```

   此时，您的会话将开始。由于此表可能位于其工作列表中的最高位置，因此，了解 Autovacuum 将立即重新启动很重要。

1. 在第二个会话中启动您的命令，然后终止第一个会话中的 autovacuum 过程。

# 使用大型索引管理 autovacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes"></a>

作为其操作的一部分，在对表运行 *autovacuum* 时会执行多个 [vacuum 阶段](https://www.postgresql.org/docs/current/progress-reporting.html#VACUUM-PHASES)。在清理表之前，首先对所有索引执行 vacuum 操作。删除多个大型索引时，此阶段会消耗大量的时间和资源。因此，作为最佳实践，请务必控制表上的索引数量并消除未使用的索引。

对于此过程，请先检查总体索引大小。然后，确定是否存在可以删除的潜在未使用索引，如以下示例所示。

**检查表及其索引的大小**

```
postgres=> select pg_size_pretty(pg_relation_size('pgbench_accounts'));
pg_size_pretty
6404 MB
(1 row)
```

```
postgres=> select pg_size_pretty(pg_indexes_size('pgbench_accounts'));
pg_size_pretty
11 GB
(1 row)
```

在此示例中，索引的大小大于表的大小。这种差异可能会导致性能问题，因为索引膨胀或未使用，这会影响 autovacuum 以及插入操作。

**检查是否有未使用的索引**

使用 [https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW) 视图，您可以检查 `idx_scan` 列使用索引的频率。在以下示例中，未使用索引的 `idx_scan` 值为 `0`。

```
postgres=> select * from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc;
    
relid  | indexrelid | schemaname | relname          | indexrelname          | idx_scan | idx_tup_read | idx_tup_fetch
-------+------------+------------+------------------+-----------------------+----------+--------------+---------------
16433  | 16454      | public     | pgbench_accounts | index_f               | 6        | 6            | 0
16433  | 16450      | public     | pgbench_accounts | index_b               | 3        | 199999       | 0
16433  | 16447      | public     | pgbench_accounts | pgbench_accounts_pkey | 0        | 0            | 0
16433  | 16452      | public     | pgbench_accounts | index_d               | 0        | 0            | 0
16433  | 16453      | public     | pgbench_accounts | index_e               | 0        | 0            | 0
16433  | 16451      | public     | pgbench_accounts | index_c               | 0        | 0            | 0
16433  | 16449      | public     | pgbench_accounts | index_a               | 0        | 0            | 0
(7 rows)
```

```
postgres=> select schemaname, relname, indexrelname, idx_scan from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc;
    
schemaname  | relname          | indexrelname          | idx_scan
------------+------------------+-----------------------+----------
public      | pgbench_accounts | index_f               | 6
public      | pgbench_accounts | index_b               | 3
public      | pgbench_accounts | pgbench_accounts_pkey | 0
public      | pgbench_accounts | index_d               | 0
public      | pgbench_accounts | index_e               | 0
public      | pgbench_accounts | index_c               | 0
public      | pgbench_accounts | index_a               | 0
(7 rows)
```

**注意**  
这些统计数据自统计数据重置之时起开始递增。假设您的索引仅用于业务季度末或仅用于特定报告。自从统计数据重置后，此索引可能就没有使用过。有关更多信息，请参阅[统计数据函数](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-STATS-FUNCTIONS)。用于强制唯一性的索引不会执行扫描，也不应被标识为未使用的索引。要识别未使用的索引，您应该对应用程序及其查询有深入的了解。

要检查数据库上次重置统计数据的时间，请使用 [ https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW]( https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW)

```
postgres=> select datname, stats_reset from pg_stat_database where datname = 'postgres';
    
datname   | stats_reset
----------+-------------------------------
postgres  | 2022-11-17 08:58:11.427224+00
(1 row)
```

## 尽快对表执行 vacuum 操作
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.Executing"></a>

**RDS for PostgreSQL 12 及更高版本**

如果大型表中的索引过多，则您的数据库实例可能接近事务 ID 重叠（XID），也就是 XID 计数器变为零时。如果不进行检查，这种情况可能导致数据丢失。但是，您可以在不清理索引的情况下快速对表执行 vacuum 操作。在 RDS for PostgreSQL 12 及更高版本中，可以将 VACUUM 与 [https://www.postgresql.org/docs/current/sql-vacuum.html](https://www.postgresql.org/docs/current/sql-vacuum.html) 子句结合使用。

```
postgres=> VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) pgbench_accounts;
        
INFO: vacuuming "public.pgbench_accounts"
INFO: table "pgbench_accounts": found 0 removable, 8 nonremovable row versions in 1 out of 819673 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 7517
Skipped 0 pages due to buffer pins, 0 frozen pages.
CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s.
```

如果 autovacuum 会话已在运行，则必须将其终止才能开始手动 VACUUM。有关执行手动 vacuum 冻结的信息，请参阅[执行手动 vacuum 冻结](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md)。

**注意**  
定期跳过索引清理会导致索引膨胀，这会降低扫描性能。索引保留死行，而表保留死行指针。因此，`pg_stat_all_tables.n_dead_tup` 会一直增加，直到 autovacuum 或带有索引清理功能的手动 VACUUM 运行。作为最佳实践，请仅使用此过程来防止事务 ID 重叠。

**RDS for PostgreSQL 11 及更低版本**

但是，在 RDS for PostgreSQL 11 及更低版本中，让 vacuum 过程更快地完成的唯一方法是减少表上的索引数量。删除索引可能会影响查询计划。我们建议您先删除未使用的索引，然后在 XID 重叠非常接近时删除索引。vacuum 过程完成后，您可以重新创建这些索引。

# 其他影响 Autovacuum 的参数
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.OtherParms"></a>

以下查询将显示直接影响 Autovacuum 及其行为的一些参数的值。PostgreSQL 文档中完整介绍了 [Autovacuum 参数](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html)。

```
SELECT name, setting, unit, short_desc
FROM pg_settings
WHERE name IN (
'autovacuum_max_workers',
'autovacuum_analyze_scale_factor',
'autovacuum_naptime',
'autovacuum_analyze_threshold',
'autovacuum_analyze_scale_factor',
'autovacuum_vacuum_threshold',
'autovacuum_vacuum_scale_factor',
'autovacuum_vacuum_threshold',
'autovacuum_vacuum_cost_delay',
'autovacuum_vacuum_cost_limit',
'vacuum_cost_limit',
'autovacuum_freeze_max_age',
'maintenance_work_mem',
'vacuum_freeze_min_age');
```

所有这些参数都会影响 Autovacuum，其中一些最重要的参数为：
+ [maintenance\$1work\$1mem](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE_WORK_MEM)
+ [Autovacuum\$1freeze\$1max\$1age](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE)
+ [Autovacuum\$1max\$1workers](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MAX-WORKERS)
+ [Autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)
+ [ Autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)

# 设置表级别 Autovacuum 参数
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.TableParameters"></a>

您可以在表级别设置与 autovacuum 相关的[存储参数](https://www.postgresql.org/docs/current/static/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS)，这可能优于更改整个数据库的行为。对于大型表，您可能需要设置主动设置，并且可能不希望 Autovacuum 对所有表的行为都相同。

以下查询将显示哪些表当前拥有表级别选项。

```
SELECT relname, reloptions
FROM pg_class
WHERE reloptions IS NOT null;
```

例如，对于比您的其他表大得多的表，这可能会很有用。假设您具有一个 300GB 表和另外 30 个小于 1GB 的表。在这种情况下，可以为大型表设置一些特定的参数，这样便无需更改整个系统的行为。

```
ALTER TABLE mytable set (autovacuum_vacuum_cost_delay=0);
```

这样便可通过使用系统中的更多资源来禁用此表的基于成本的 autovacuum 延迟。通常，每次达到 `autovacuum_cost_limit` 时，autovacuum 会暂停 `autovacuum_vacuum_cost_delay`。有关更多详细信息，请参阅 PostgreSQL 文档中有关[基于成本的 vacuum 操作](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST)的内容。

# 记录 autovacuum 和 vacuum 活动
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging"></a>

根据 `rds.force_autovacuum_logging_level` 参数中指定的级别，有关 autovacuum 活动的信息将发送到 `postgresql.log`。以下是此参数允许的值以及该值为默认设置的 PostgreSQL 版本：
+ `disabled`（PostgreSQL 10、PostgreSQL 9.6）
+ `debug5`, `debug4`, `debug3`, `debug2`, `debug1`
+ `info`（PostgreSQL 12、PostgreSQL 11）
+ `notice`
+ `warning`（PostgreSQL 13 及更高版本）
+ `error`、日志、`fatal`、`panic`

`rds.force_autovacuum_logging_level` 与 `log_autovacuum_min_duration` 参数结合使用。`log_autovacuum_min_duration` 参数的值为阈值（以毫秒为单位），超出该值后将记录 autovacuum 操作。设置为 `-1` 不会记录任何内容，而设置 0 将记录所有操作。和 `rds.force_autovacuum_logging_level` 一样，`log_autovacuum_min_duration` 的默认值取决于版本，如下所示：
+ `10000 ms` - PostgreSQL 14、PostgreSQL 13、PostgreSQL 12 和 PostgreSQL 11 
+ `(empty)` - PostgreSQL 10 和 PostgreSQL 9.6 没有默认值

建议您将 `rds.force_autovacuum_logging_level` 设置为 `WARNING`。我们还建议您将 `log_autovacuum_min_duration` 设置为 1000 到 5000 之间的值。设置为 5000 的记录活动耗时将超过 5000 毫秒。如果由于冲突锁定或并行删除关系跳过了 autovacuum 操作，则并非 -1 的任何其他设置也会记录消息。有关更多信息，请参阅 PostgreSQL 文档中的 [Automatic Vacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html)。

要对问题进行故障排除，可以将 `rds.force_autovacuum_logging_level` 参数更改为调试级别之一，从 `debug1` 到最高 `debug5` 以获取最详细的信息。我们建议您在短时间内使用调试设置，并且仅用于故障排除目的。要了解更多信息，请参阅 PostgreSQL 文档中的[何时记录](https://www.postgresql.org/docs/current/static/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHEN)。

**注意**  
PostgreSQL 允许 `rds_superuser` 账户查看 `pg_stat_activity` 中的 Autovacuum 会话。例如，您可识别并结束阻止命令运行或运行速度慢于手动发出的 vacuum 命令的 Autovacuum 会话。

# 了解对无效数据库使用 autovacuum 的行为
<a name="appendix.postgresql.commondbatasks.autovacuumbehavior"></a>

 在 `pg_database` 目录的 `datconnlimit` 列中引入了一个新值 `-2`，来指示在 DROP DATABASE 操作过程中已被中断的数据库为无效的。

 以下 RDS for PostgreSQL 版本中提供了这个新值：
+ 15.4 及所有更高版本
+ 14.9 及更高版本
+ 13.12 及更高版本
+ 12.16 及更高版本
+ 11.21 及更高版本

无效的数据库不会影响 autovacuum 冻结有效数据库的功能的能力。Autovacuum 会忽略无效的数据库。因此，对于 PostgreSQL 环境中的所有有效数据库，常规 vacuum 操作将继续正常且高效地运行。

**Topics**
+ [监控事务 ID](#appendix.postgresql.commondbatasks.autovacuum.monitorxid)
+ [调整监控查询](#appendix.postgresql.commondbatasks.autovacuum.monitoradjust)
+ [解决无效的数据库问题](#appendix.postgresql.commondbatasks.autovacuum.connissue)

## 监控事务 ID
<a name="appendix.postgresql.commondbatasks.autovacuum.monitorxid"></a>

 `age(datfrozenxid)` 函数常用于监控数据库的事务 ID（XID）期限，以防止事务 ID 重叠。

 由于无效数据库被排除在 autovacuum 之外，因此其事务 ID（XID）计数器可以达到最大值 `2 billion`，重叠到 `- 2 billion`，并无限期地继续此循环。监控事务 ID 重叠的典型查询可能如下所示：

```
SELECT max(age(datfrozenxid)) FROM pg_database;
```

但是，在为 `datconnlimit` 引入 -2 值后，无效的数据库可能会扭曲此查询的结果。由于这些数据库无效，而不应作为定期维护检查的一部分，因此它们可能会导致误报，致使您认为 `age(datfrozenxid)` 高于实际值。

## 调整监控查询
<a name="appendix.postgresql.commondbatasks.autovacuum.monitoradjust"></a>

 为确保准确的监控，应调整监控查询来排除无效的数据库。请遵循这一建议的查询：

```
SELECT
    max(age(datfrozenxid))
FROM
    pg_database
WHERE
    datconnlimit <> -2;
```

此查询可确保在 `age(datfrozenxid)` 计算中只考虑有效的数据库，从而真实地反映整个 PostgreSQL 环境中的事务 ID 期限。

## 解决无效的数据库问题
<a name="appendix.postgresql.commondbatasks.autovacuum.connissue"></a>

 当尝试连接到无效的数据库时，可能会遇到类似于以下内容的错误消息：

```
postgres=> \c db1
connection to server at "mydb.xxxxxxxxxx.us-west-2.rds.amazonaws.com" (xx.xx.xx.xxx), port xxxx failed: FATAL:  cannot connect to invalid database "db1"
HINT:  Use DROP DATABASE to drop invalid databases.
Previous connection kept
```

 此外，如果 `log_min_messages` 参数设置为 `DEBUG2` 或更高，您可能会注意到以下日志条目，表明 autovacuum 进程正在跳过无效的数据库：

```
       
2024-07-30 05:59:00 UTC::@:[32000]:DEBUG:  autovacuum: skipping invalid database "db6"
2024-07-30 05:59:00 UTC::@:[32000]:DEBUG:  autovacuum: skipping invalid database "db1"
```

要解决此问题，请按照尝试连接期间提供的 `HINT` 进行操作。使用 RDS 主账户或具有 `rds_superuser` 角色的数据库账户连接到任何有效的数据库，然后删除无效的数据库。

```
SELECT
    'DROP DATABASE ' || quote_ident(datname) || ';'
FROM
    pg_database
WHERE
    datconnlimit = -2 \gexec
```

# 识别并解决 RDS for PostgreSQL 中的积极真空拦截器
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring"></a>

在 PostgreSQL 中，清理对于确保数据库良好运行状况至关重要，因为它可以回收存储并防止出现[事务 ID 重叠](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)问题。但是，有时可能会阻止真空清理操作按预期运行，这样可能会导致性能下降、存储膨胀，甚至会因事务 ID 重叠而影响您的数据库实例的可用性。因此，识别和解决这些问题对于实现最佳数据库性能和可用性具有至关重要的意义。阅读[了解 Amazon RDS for PostgreSQL 环境中的自动真空功能](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)，以了解有关自动真空的更多信息。

`postgres_get_av_diag()` 函数可用于识别会阻止或延迟积极 vacuum 进度的问题。提供了建议，其中可能包括用于解决可识别问题的命令，或者在无法识别问题时提供进一步诊断的指导。当龄期超过 RDS 的 5 亿个事务 ID 的[自适应自动真空](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)阈值时，将报告积极真空拦截器。

**事务 ID 的龄期是多少？**

事务 ID 的 `age()` 函数会计算自数据库 (`pg_database.datfrozenxid`) 或表 (`pg_class.relfrozenxid`) 的最早解冻事务 ID 以来发生的事务数。此值表示自上次积极真空操作以来的数据库活动，并突出显示即将到来的真空进程可能出现的工作负载。

**什么是积极真空？**

积极真空操作会对表中的所有页面进行全面扫描，包括在常规真空期间通常跳过的页面。这种彻底的扫描旨在“冻结”接近其最大龄期的事务 ID，从而有效地防止出现被称为[事务 ID 重叠](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)的情况。

要使 `postgres_get_av_diag()` 报告拦截器，拦截器必须至少有 5 亿个事务。

**Topics**
+ [在 RDS for PostgreSQL 中安装 autovacuum 监控和诊断工具](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)
+ [RDS for PostgreSQL 中的 postgres\$1get\$1av\$1diag() 函数](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions.md)
+ [在 RDS for PostgreSQL 中解决可识别的真空拦截器](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md)
+ [在 RDS for PostgreSQL 中解除无法识别的真空拦截器](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers.md)
+ [解决 RDS for PostgreSQL 中的真空性能问题](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md)
+ [RDS for PostgreSQL 中的通知消息说明](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)

# 在 RDS for PostgreSQL 中安装 autovacuum 监控和诊断工具
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation"></a>

`postgres_get_av_diag()` 函数目前在以下 RDS for PostgreSQL 版本中可用：
+ 17.2 及更高的 17 版本
+ 16.7 及更高的 16 版本
+ 15.11 及更高的 15 版本
+ 14.16 及更高的 14 版本
+ 13.19 及更高的 13 版本

 要使用 `postgres_get_av_diag()`，请创建 `rds_tools` 扩展。

```
postgres=> CREATE EXTENSION rds_tools ;
CREATE EXTENSION
```

验证是否已安装扩展。

```
postgres=> \dx rds_tools
             List of installed extensions
   Name    | Version |  Schema   |                    Description
 ----------+---------+-----------+----------------------------------------------------------
 rds_tools |   1.8   | rds_tools | miscellaneous administrative functions for RDS PostgreSQL
 1 row
```

验证是否已创建函数。

```
postgres=> SELECT
    proname function_name,
    pronamespace::regnamespace function_schema,
    proowner::regrole function_owner
FROM
    pg_proc
WHERE
    proname = 'postgres_get_av_diag';
    function_name     | function_schema | function_owner
----------------------+-----------------+----------------
 postgres_get_av_diag | rds_tools       | rds_superuser
(1 row)
```

# RDS for PostgreSQL 中的 postgres\$1get\$1av\$1diag() 函数
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions"></a>

`postgres_get_av_diag()` 函数会检索有关 RDS for PostgreSQL 数据库中阻止或滞后的 autovacuum 进程的诊断信息。为了获得准确的结果，需要在具有最早事务 ID 的数据库中执行查询。有关使用具有最早事务 ID 的数据库的更多信息，请参阅[未连接到具有最早事务 ID 龄期的数据库](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)

```
SELECT
    blocker,
    DATABASE,
    blocker_identifier,
    wait_event,
    TO_CHAR(autovacuum_lagging_by, 'FM9,999,999,999') AS autovacuum_lagging_by,
    suggestion,
    suggested_action
FROM (
    SELECT
        *
    FROM
        rds_tools.postgres_get_av_diag ()
    ORDER BY
        autovacuum_lagging_by DESC) q;
```

`postgres_get_av_diag()` 函数将返回一个包含以下信息的表：

**blocker**  
指定阻止真空的数据库活动的类别。  
+ [活动语句](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [事务中空闲](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [准备好的事务](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [逻辑复制槽](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [带有物理复制槽的只读副本](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [使用流式复制的只读副本](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [临时表](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

**database**  
在适用和支持的情况下指定数据库的名称。这是其中活动正在进行并正在阻止或将阻止自动真空的数据库。这是您需要连接并执行操作的数据库。

**blocker\$1identifier**  
指定正在阻止或将阻止自动真空的活动的标识符。该标识符可以是进程 ID 以及 SQL 语句、准备好的事务、只读副本的 IP 地址以及复制槽的名称（逻辑或物理）。

**wait\$1event**  
指定阻止会话的[等待事件](PostgreSQL.Tuning.md)，适用于以下拦截器：  
+ 活动语句
+ 事务中空闲

**autovacum\$1lagging\$1by**  
指定自动真空在每个类别的积压工作中滞后的事务数。

**suggestion**  
指定解除拦截器的建议。这些说明包括活动所在的数据库的名称（如果适用）、会话的进程 ID（PID）（如果适用）以及要执行的操作。

**suggested\$1action**  
建议需要执行哪些操作来解除拦截器。

# 在 RDS for PostgreSQL 中解决可识别的真空拦截器
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers"></a>

自动真空会执行积极真空操作，并将事务 ID 的龄期降低到低于由 RDS 实例的 `autovacuum_freeze_max_age` 参数指定的阈值。您可以使用 Amazon CloudWatch 指标 `MaximumUsedTransactionIDs` 跟踪此龄期。

要查找 Amazon RDS 实例的 `autovacuum_freeze_max_age` 设置（默认为 2 亿个事务 ID），您可以使用以下查询：

```
SELECT
    TO_CHAR(setting::bigint, 'FM9,999,999,999') autovacuum_freeze_max_age
FROM
    pg_settings
WHERE
    name = 'autovacuum_freeze_max_age';
```

请注意，`postgres_get_av_diag()` 仅在龄期超过 Amazon RDS 的 5 亿个事务 ID 的[自适应自动真空](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)阈值时检查积极真空拦截器。要使 `postgres_get_av_diag()` 检测拦截器，拦截器必须至少有 5 亿个事务。

`postgres_get_av_diag()` 函数可识别以下类型的拦截器：

**Topics**
+ [活动语句](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [事务中空闲](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [准备好的事务](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [逻辑复制槽](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [只读副本](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [临时表](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

## 活动语句
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement"></a>

在 PostgreSQL 中，活动语句是数据库当前正在执行的 SQL 语句。这包括查询、事务或任何正在进行的操作。通过 `pg_stat_activity` 进行监控时，状态列指示具有相应 PID 的进程处于活动状态。

`postgres_get_av_diag()` 函数在识别系活动语句的语句时会显示类似于以下内容的输出。

```
blocker               | Active statement
database              | my_database
blocker_identifier    | SELECT pg_sleep(20000);
wait_event            | Timeout:PgSleep
autovacuum_lagging_by | 568,600,871
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (29621);"}
```

**建议采取的措施**

按照 `suggestion` 列中的指导，用户可以连接到存在活动语句的数据库，并按照 `suggested_action` 列中的指定，建议仔细查看终止会话的选项。如果终止是安全的，则可以使用 `pg_terminate_backend()` 函数终止会话。此操作可由管理员（如 RDS 主账户）或具有所需 `pg_terminate_backend()` 权限的用户执行。

**警告**  
已终止的会话将撤消 (`ROLLBACK`) 其所做的更改。根据您的要求，您可能需要重新运行相应语句。但是，建议只有在自动真空过程完成其积极真空操作之后才这样做。

## 事务中空闲
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction"></a>

事务中空闲语句是指已打开显式事务（例如通过发出 `BEGIN` 语句）、执行了一些工作，并且现在正在等待客户端传递更多工作或通过发出 `COMMIT`、`ROLLBACK` 或 `END`（这将导致隐式 `COMMIT`）来发出事务结束信号的任何会话。

`postgres_get_av_diag()` 函数在将 `idle in transaction` 语句识别为拦截器时，显示类似于以下内容的输出。

```
blocker               | idle in transaction
database              | my_database
blocker_identifier    | INSERT INTO tt SELECT * FROM tt;
wait_event            | Client:ClientRead
autovacuum_lagging_by | 1,237,201,759
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (28438);"}
```

**建议采取的措施**

如 `suggestion` 列中所示，您可以连接到存在事务中空闲会话的数据库，并使用 `pg_terminate_backend()` 函数终止会话。该用户可以是您的管理员（RDS 主账户）用户或具有 `pg_terminate_backend()` 权限的用户。

**警告**  
已终止的会话将撤消 (`ROLLBACK`) 其所做的更改。根据您的要求，您可能需要重新运行相应语句。但是，建议只有在自动真空过程完成其积极真空操作之后才这样做。

## 准备好的事务
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction"></a>

PostgreSQL 允许属于称为[准备好的事务](https://www.postgresql.org/docs/current/sql-prepare-transaction.html)的两阶段提交策略一部分的事务。通过将 `max_prepared_transactions` 参数设置为非零值即可启用这些功能。准备好的事务旨在确保事务的持久性，即使在数据库崩溃、重启或客户端断开连接后仍可用。与定期事务一样，它们会被分配一个事务 ID，并且可能会影响自动真空。如果保持已准备状态，则自动真空将无法执行冻结，这样可能会导致事务 ID 重叠。

当事务被无限期地准备而没有被事务管理器解决时，它们将成为孤立的已准备事务。解决此问题的唯一方法是分别使用 `COMMIT PREPARED` 或 `ROLLBACK PREPARED` 命令提交或回滚事务。

**注意**  
请注意，在准备事务期间进行的备份在还原后仍将包含该事务。有关如何查找和关闭此类事务的信息，请参阅以下信息。

`postgres_get_av_diag()` 函数在识别出系已准备事务的拦截器时显示以下输出。

```
blocker               | Prepared transaction
database              | my_database
blocker_identifier    | myptx
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database" and consider either COMMIT or ROLLBACK the prepared transaction using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"COMMIT PREPARED 'myptx';",[OR],"ROLLBACK PREPARED 'myptx';"}
```

**建议采取的措施**

如建议列中所述，连接到已准备事务所在的数据库。根据 `suggested_action` 列，仔细查看是执行 `COMMIT` 还是 `ROLLBACK`，并执行适当的操作。

为了总体上监控已准备事务，PostgreSQL 提供了一个名为 `pg_prepared_xacts` 的目录视图。您可以使用以下查询来查找已准备事务。

```
SELECT
    gid,
    prepared,
    owner,
    database,
    transaction AS oldest_xmin
FROM
    pg_prepared_xacts
ORDER BY
    age(transaction) DESC;
```

## 逻辑复制槽
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot"></a>

复制槽的用途是保存未使用的更改，直到它们被复制到目标服务器。有关更多信息，请参阅 PostgreSQL 的 [Logical replication](https://www.postgresql.org/docs/current/logical-replication.html)。

有两种类型的逻辑复制槽。

**非活动逻辑复制槽**

复制终止后，无法删除未使用的事务日志，且复制槽变为非活动状态。尽管订阅用户当前未使用非活动逻辑复制槽，但它仍保留在服务器上，从而保留 WAL 文件并防止删除旧的事务日志。这样会增加磁盘使用量，特别是阻止自动真空清理内部目录表，因为系统必须保护 LSN 信息不被覆盖。如果不加以解决，可能会导致目录臃肿、性能下降和重叠真空风险增加，从而可能导致事务停机。

**活动但速度较慢的逻辑复制槽**

有时，由于逻辑复制的性能下降，目录中无效元组的删除会延迟。这种复制延迟会减慢 `catalog_xmin` 的更新速度，并可能导致目录臃肿和重叠真空。

`postgres_get_av_diag()` 函数在找到逻辑复制槽作为拦截器时，会显示类似于以下内容的输出。

```
blocker               | Logical replication slot
database              | my_database
blocker_identifier    | slot1
wait_event            | Not applicable
autovacuum_lagging_by | 1,940,103,068
suggestion            | Ensure replication is active and resolve any lag for the slot if active. If inactive, consider dropping it using the command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_drop_replication_slot('slot1') FROM pg_replication_slots WHERE active = 'f';"}
```

**建议采取的措施**

要解决此问题，请检查复制配置中是否存在可能终止应用进程的目标架构或数据问题。最常见的原因如下：
+ 缺少列
+ 数据类型不兼容
+ 数据不匹配
+ 缺少表

如果该问题与基础设施问题有关：
+ 网络问题 – [如何解决 Amazon RDS 数据库处于不兼容网络状态的问题？](https://repost.aws/knowledge-center/rds-incompatible-network)。
+ 数据库或数据库实例不可用的原因如下：
  + 副本实例用尽存储空间 – 有关添加存储的信息，请查看 [Amazon RDS DB 实例存储空间不足](https://repost.aws/knowledge-center/rds-out-of-storage)。
  + 不兼容参数 – 有关如何能够解决该问题的更多信息，请查看[如何修复一直处于不兼容参数状态的 Amazon RDS 数据库实例问题？](https://repost.aws/knowledge-center/rds-incompatible-parameters)。

如果您的实例位于 AWS 网络之外或 AWS EC2 上，请咨询您的管理员，了解如何解决可用性或基础设施相关问题。

**删除非活动槽**

**警告**  
注意：在删除复制槽之前，请仔细确保其没有正在进行的复制、处于非活动状态且处于不可恢复状态。过早删除槽可能会中断复制或导致数据丢失。

确认不再需要复制槽后，将其删除以允许自动真空继续运行。条件 `active = 'f'` 可确保仅删除非活动槽。

```
SELECT pg_drop_replication_slot('slot1') WHERE active ='f'
```

## 只读副本
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas"></a>

为 [Amazon RDS 只读副本](USER_PostgreSQL.Replication.ReadReplicas.md)启用 `hot_standby_feedback` 设置后，它会阻止主数据库上的自动真空删除只读副本上运行的查询可能仍需要的死行。这样会影响所有类型的物理只读副本，包括那些带有或不带由复制槽管理的只读副本。此行为是必需的，因为在备用副本上运行的查询要求这些行在主副本上保持可用，从而防止发生[查询冲突](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT)和取消。

**带有物理复制槽的只读副本**  
带有物理复制槽的只读副本可显著增强 RDS for PostgreSQL 中复制的可靠性和稳定性。这些槽可确保主数据库保留基本的预写日志文件，直到副本处理它们，即使在网络中断期间也能保持数据一致性。

从 RDS for PostgreSQL 版本 14 开始，所有副本均使用复制槽。在早期版本中，只有跨区域副本使用复制槽。

`postgres_get_av_diag()` 函数在找到以物理复制槽作为拦截器的只读副本时，会显示类似于以下内容的输出。

```
blocker               | Read replica with physical replication slot
database              |
blocker_identifier    | rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxxx
wait_event            | Not applicable
autovacuum_lagging_by | 554,080,689
suggestion            | Run the following query on the replica "rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxx" to find the long running query:                           
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;                                                       
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                 +                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;","                                                                                 +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                   +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Delete the read replica if not needed"}
```

**使用流式复制的只读副本**  
Amazon RDS 允许在较旧版本（最高为版本 13）中设置不带物理复制槽的只读副本。这种方法通过允许主数据库更积极地回收 WAL 文件来减少开销，这在磁盘空间有限的环境中是有利的，并可以容忍偶尔发生的 ReplicaLag。但是，如果没有槽，备用副本必须保持同步，以免丢失 WAL 文件。Amazon RDS 使用已存档的 WAL 文件来帮助副本在落后时赶上，但是此过程需要仔细监控，而且可能速度很慢。

`postgres_get_av_diag()` 函数在找到作为拦截器的流式只读副本时，会显示类似于以下内容的输出。

```
blocker               | Read replica with streaming replication slot
database              | Not applicable
blocker_identifier    | xx.x.x.xxx/xx
wait_event            | Not applicable
autovacuum_lagging_by | 610,146,760
suggestion            | Run the following query on the replica "xx.x.x.xxx" to find the long running query:                                                                                                                                                         +
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;                                                                                                                                                     +
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                       +
                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;","                                                                                                                        +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                                                          +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Delete the read replica if not needed"}
```

**建议采取的措施**

按照 `suggested_action` 列中的建议，仔细查看用于解除阻止自动真空的这些选项。
+ **终止查询** – 按照建议列中的指导，您可以连接到只读副本，如 suggested\$1action 列中指定，建议仔细查看终止会话的选项。如果终止被视为是安全的，则可以使用 `pg_terminate_backend()` 函数终止会话。此操作可由管理员（如 RDS 主账户）或具有所需 pg\$1terminate\$1backend() 权限的用户执行。

  您可以在只读副本上运行以下 SQL 命令来终止用于阻止主数据库上的真空清理旧行的查询。在函数的输出中报告 `backend_xmin` 的值：

  ```
  SELECT
      pg_terminate_backend(pid)
  FROM
      pg_catalog.pg_stat_activity
  WHERE
      backend_xmin::text::bigint = backend_xmin;
  ```
+ **禁用热备用反馈** – 如果 `hot_standby_feedback` 参数会导致明显的真空延迟，请考虑禁用该参数。

  `hot_standby_feedback` 参数允许只读副本将其查询活动通知主数据库，从而防止主数据库对备用数据库上使用的表或行执行清理操作。虽然这样可以确保备用数据库上的查询稳定性，但它可能会显著延迟主数据库上的清理时间。禁用此功能允许主数据库继续进行清理，而无需等待备用数据库赶上。但是，如果备用数据库尝试访问已被主数据库清理的行，则可能导致备用数据库上的查询取消或失败。
+ **如果不需要只读副本，请将其删除** – 如果不再需要只读副本，则可以将其删除。这将消除相关的复制开销，并允许主数据库在不受副本阻碍的情况下回收事务日志。

## 临时表
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables"></a>

使用 `TEMPORARY` 关键字创建的[临时表](https://www.postgresql.org/docs/current/sql-createtable.html)驻留在临时架构中，例如 pg\$1temp\$1xxx，并且只能由创建它们的会话访问。会话结束时会删除临时表。但是，这些表对于 PostgreSQL 的自动真空流程是不可见的，必须由创建它们的会话手动清理。尝试从另一个会话中清空临时表是无效的。

在特殊情况下，存在一个临时表，但没有活动会话拥有该表。如果所属会话由于致命崩溃、网络问题或类似事件而意外结束，则可能无法清理临时表，从而会将其留作为“孤立”表。当 PostgreSQL 自动真空进程检测到孤立的临时表时，它会记录以下消息：

```
LOG: autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"
```

`postgres_get_av_diag()` 函数在将临时表识别为拦截器时，会显示类似于以下内容的输出。要使该函数正确显示与临时表相关的输出，需要在存在这些表的同一数据库中执行该函数。

```
blocker               | Temporary table
database              | my_database
blocker_identifier    | pg_temp_14.ttemp
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database". Review carefully, you may consider dropping temporary table using command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"DROP TABLE ttemp;"}
```

**建议采取的措施**

按照输出的 `suggestion` 列中提供的说明识别并删除阻止自动真空运行的临时表。使用以下命令删除由 `postgres_get_av_diag()` 报告的临时表。根据 `postgres_get_av_diag()` 函数提供的输出替换表名称。

```
DROP TABLE my_temp_schema.my_temp_table;
```

以下查询可用于识别临时表：

```
SELECT
    oid,
    relname,
    relnamespace::regnamespace,
    age(relfrozenxid)
FROM
    pg_class
WHERE
relpersistence = 't'
ORDER BY
    age(relfrozenxid) DESC;
```

# 在 RDS for PostgreSQL 中解除无法识别的真空拦截器
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers"></a>

本节探讨了可能阻碍清理取得进展的其他原因。`postgres_get_av_diag()` 函数目前无法直接识别这些问题。

**Topics**
+ [页面无效](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)
+ [索引不一致](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency)
+ [事务速率异常高](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate)

## 页面无效
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages"></a>

当 PostgreSQL 在访问页面时检测到该页面的校验和不匹配时，就会出现无效页面错误。内容无法读取，从而阻止自动真空冻结元组。这样实际上会停止清理过程。PostgreSQL 的日志中写入了以下错误：

```
WARNING:  page verification failed, calculated checksum YYYYY but expected XXXX
ERROR:  invalid page in block ZZZZZ of relation base/XXXXX/XXXXX
CONTEXT:  automatic vacuum of table myschema.mytable
```

**确定对象类型**

```
ERROR: invalid page in block 4305910 of relation base/16403/186752608 
WARNING: page verification failed, calculated checksum 50065 but expected 60033
```

从错误消息中，路径 `base/16403/186752608` 提供以下信息：
+ “base”是 PostgreSQL 数据目录下的目录名称。
+ “16403”是数据库 OID，您可以在 `pg_database` 系统目录中进行查找。
+ “186752608”是 `relfilenode`，您可以使用它在 `pg_class` 系统目录中查找架构和对象名称。

通过在受影响的数据库中检查以下查询的输出，可以确定对象类型。以下查询会检索 oid 为 186752608 的对象信息。将该 OID 替换为与您遇到的错误相关的 OID。

```
SELECT
    relname AS object_name,
    relkind AS object_type,
    nspname AS schema_name
FROM
    pg_class c
    JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE
    c.oid = 186752608;
```

有关更多信息，请参阅 PostgreSQL 文档 [https://www.postgresql.org/docs/current/catalog-pg-class.html](https://www.postgresql.org/docs/current/catalog-pg-class.html)，以了解所有支持的对象类型，如 `pg_class` 中的 `relkind` 列所示。

**指南**

此问题的最有效解决方案取决于特定 Amazon RDS 实例的配置以及受不一致页面影响的数据类型。

**如果对象类型是索引：**

建议重建索引。
+ **使用 `CONCURRENTLY` 选项** – 在 PostgreSQL 版本 12 之前，重建索引需要独占的表锁定，从而限制对表的访问。在 PostgreSQL 版本 12 及更高版本中，`CONCURRENTLY` 选项允许行级别锁定，从而显著提高表的可用性。命令如下：

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  虽然 `CONCURRENTLY` 的破坏性较小，但在繁忙的表中其速度可能会变慢。如果可能，可以考虑在流量较低的时段构建索引。

  有关更多信息，请参阅 PostgreSQL [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html) 文档。
+ **使用 `INDEX_CLEANUP FALSE` 选项** – 如果索引很大并且估计需要大量时间才能完成，则您可以通过在排除索引的同时执行手动 `VACUUM FREEZE` 来解除阻止 autovacuum。PostgreSQL 版本 12 及更高版本中提供了此功能。

  绕过索引将允许您跳过索引不一致的真空过程并缓解重叠问题。但是，这样并不能解决潜在的无效页面问题。要完全应对和解决无效页面问题，您仍然需要重建索引。

**如果对象类型为实体化视图：**

如果实体化视图上出现无效页面错误，请登录到受影响的数据库并刷新以解决无效的页面：

刷新实体化视图：

```
REFRESH MATERIALIZED VIEW schema_name.materialized_view_name;
```

如果刷新失败，请尝试重新创建：

```
DROP MATERIALIZED VIEW schema_name.materialized_view_name;
CREATE MATERIALIZED VIEW schema_name.materialized_view_name AS query;
```

刷新或重新创建实体化视图可在不影响基础表数据的情况下还原该视图。

**对于所有其他对象类型：**

对于所有其他对象类型，请联系 AWS 支持。

## 索引不一致
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency"></a>

逻辑上不一致的索引可能会阻碍自动真空取得进展。在索引的真空阶段或 SQL 语句访问索引时，将记录以下错误或类似错误。

```
ERROR: right sibling's left-link doesn't match:block 5 links to 10 instead of expected 2 in index ix_name
```

```
ERROR: failed to re-find parent key in index "XXXXXXXXXX" for deletion target page XXX
CONTEXT:  while vacuuming index index_name of relation schema.table
```

**指南**

在手动 `VACUUM FREEZE` 上使用 `INDEX_CLEANUP` 重建索引或跳过索引。有关如何重建索引的信息，请参阅[如果对象类型是索引](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)。
+ **使用 CONCURRENTLY 选项** – 在 PostgreSQL 版本 12 之前，重建索引需要独占的表锁定，从而限制对表的访问。在 PostgreSQL 版本 12 及更高版本中，CONCURRENTLY 选项允许行级别锁定，从而显著提高表的可用性。命令如下：

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  虽然 CONCURRENTLY 的破坏性较小，但在繁忙的表中其速度可能会变慢。如果可能，可以考虑在流量较低的时段构建索引。有关更多信息，请参阅 *PostgreSQL* 文档中的 [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)。
+ **使用 INDEX\$1CLEANUP FALSE 选项** – 如果索引很大并且估计需要大量时间才能完成，则您可以通过在排除索引的同时执行手动 VACUUM FREEZE 来解除阻止 autovacuum。PostgreSQL 版本 12 及更高版本中提供了此功能。

  绕过索引将允许您跳过索引不一致的真空过程并缓解重叠问题。但是，这样并不能解决潜在的无效页面问题。要完全应对和解决无效页面问题，您仍然需要重建索引。

## 事务速率异常高
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate"></a>

在 PostgreSQL 中，事务速率高会显著影响自动真空的性能，从而导致无效元组的清理速度变慢，并增加事务 ID 重叠的风险。您可以通过衡量两个时间段之间的 `max(age(datfrozenxid))` 差异（通常为每秒）来监控事务速率。此外，您还可以使用 RDS 性能详情中的以下计数器指标来衡量事务速率（xact\$1commit 与 xact\$1rollback 之和），即事务总数。


|  计数器  |  类型  |  单位  |  指标  | 
| --- | --- | --- | --- | 
|  xact\$1commit  |  事务  |  每秒提交数  |  db.Transactions.xact\$1commit  | 
|  xact\$1rollback  |  事务  |  每秒回滚数  |  db.Transactions.xact\$1rollback  | 

快速增加表示高事务负载，这可能会使自动真空不堪重负，从而导致膨胀、锁争用和潜在的性能问题。这样可能会以多种方式对自动真空进程产生负面影响：
+ **表活动：**正在经历清理操作的特定表可能会遇到大量事务，从而导致延迟。
+ **系统资源：**整个系统可能会过载，使自动真空难以访问必要的资源以便高效运行。

请考虑以下策略，以允许自动真空更有效地运行并跟上其任务：

1. 如果可能，请降低事务速率。请考虑在可行的情况下对类似的事务进行批处理或分组。

1. 在非高峰时段，每晚、每周或每两周通过手动 `VACUUM FREEZE` 操作来定位频繁更新的表。

1. 请考虑扩展您的实例类以分配更多系统资源来处理高事务量和自动真空操作。

# 解决 RDS for PostgreSQL 中的真空性能问题
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance"></a>

本节讨论经常导致真空性能变慢的因素以及如何解决这些问题。

**Topics**
+ [清理大型索引](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes)
+ [需要清理的表或数据库太多](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables)
+ [正在运行积极真空（以防止重叠）](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)

## 清理大型索引
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes"></a>

VACUUM 按以下阶段顺序运行：初始化、堆扫描、索引和堆真空清理、索引清理、堆截断和最终清理。在堆扫描期间，该过程修剪页面、整理碎片并冻结它们。完成堆扫描后，VACUUM 将清理索引，将空页返回到操作系统，并执行最终的清理任务，例如对空闲空间映射表执行真空清理和更新统计信息。

对索引执行真空清理操作时，如果 `maintenance_work_mem`（或 `autovacuum_work_mem`）不足以处理索引，则可能需要多次扫描。在 PostgreSQL 16 及更早版本中，用于存储无效元组 ID 存在 1 GB 内存限制，对于大型索引通常需要多次扫描。PostgreSQL 17 引入了 `TidStore`，这会动态分配内存，而不是使用单一分配数组。此功能消除了 1 GB 限制，可以更高效地利用内存，并减少了每次索引操作中进行多次索引扫描的需求。

在 PostgreSQL 17 中，对于大型索引，如果可用内存无法一次性容纳整个索引的处理需求，那么仍可能需要多次扫描。通常，更大的索引往往包含更多需要多次扫描的无效元组。

**检测缓慢的 vacuum 操作**

`postgres_get_av_diag()` 函数可以检测 vacuum 操作何时因内存不足而运行缓慢。有关此函数的更多信息，请参阅[在 RDS for PostgreSQL 中安装 autovacuum 监控和诊断工具](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)。

当可用内存不足以一次性完成索引 vacuum 时，`postgres_get_av_diag()` 函数会发出以下通知。

**`rds_tools` 1.8**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is "XXX" and might not be sufficient. Consider increasing the setting, and if necessary, scaling up the Amazon RDS instance class for more memory. 
        Additionally, review the possibility of manual vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;).
```

**`rds_tools` 1.9**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is XX might not be sufficient. Consider increasing the setting to XXX, and if necessary, scaling up the RDS instance class for more 
        memory. The suggested value is an estimate based on the current number of dead tuples for the table being vacuumed, which might not fully reflect the latest state. Additionally, review the possibility of manual 
        vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;). For more information, see 
        [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)
        .
```

**注意**  
`postgres_get_av_diag()` 函数依靠 `pg_stat_all_tables.n_dead_tup` 来估计索引清理所需的内存量。

当 `postgres_get_av_diag()` 函数识别出由于 `autovacuum_work_mem` 不足而需要多次索引扫描的慢速 vacuum 操作时，它将生成以下消息：

```
NOTICE: Your vacuum is performing multiple index scans due to insufficient autovacuum_work_mem:XXX for index vacuuming. 
        For more information, see [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html).
```

**指南**

您可以使用手动 `VACUUM FREEZE` 应用以下解决方法来加快表的冻结速度。

**增加用于清理的内存**

正如 `postgres_get_av_diag()` 函数所建议的那样，建议增加 `autovacuum_work_mem` 参数以解决实例级别的潜在内存限制问题。虽然 `autovacuum_work_mem` 是一个动态参数，但请务必注意，要使新的内存设置生效，自动真空进程守护程序需要重新启动其工作线程。要实现这一点，请执行以下操作：

1. 确认新设置已落实到位。

1. 终止当前运行自动真空的进程。

这种方法可确保将调整后的内存分配应用于新的自动真空操作。

为了获得更直接的结果，请考虑在会话中手动执行 `VACUUM FREEZE` 操作，并增加 `maintenance_work_mem` 设置：

```
SET maintenance_work_mem TO '1GB';
VACUUM FREEZE VERBOSE table_name;
```

如果您使用的是 Amazon RDS，并且发现需要额外的内存来支持更高的 `maintenance_work_mem` 或 `autovacuum_work_mem` 值，请考虑升级到具有更多内存的实例类。这样可以提供必要的资源来增强手动和自动清理操作，从而提高整体真空和数据库性能。

**禁用 INDEX\$1CLEANUP**

PostgreSQL 版本 12 及更高版本中的手动 `VACUUM` 允许跳过索引清理阶段，而 PostgreSQL 版本 14 及更高版本中的紧急自动真空会根据 [https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE) 参数自动执行此操作。

**警告**  
跳过索引清理会导致索引膨胀并对查询性能产生负面影响。为了缓解这种情况，可以考虑在维护时段内对受影响的索引重建索引或清理受影响的索引。

有关处理大型索引的更多指导，请参阅[使用大型索引管理 autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md)中的文档。

**并行索引清理**

从 PostgreSQL 13 开始，默认情况下，可以使用手动 `VACUUM` 并行对索引进行清理，并为每个索引分配一个真空工件进程。但是，要使 PostgreSQL 确定真空操作是否符合并行执行的条件，必须满足特定标准：
+ 必须至少有两个索引。
+ `max_parallel_maintenance_workers` 参数应至少设置为 2。
+ 索引大小必须超过 `min_parallel_index_scan_size` 限制，默认为 512 KB。

您可以根据 Amazon RDS 实例上可用的 vCPU 数量和表上的索引数量来调整 `max_parallel_maintenance_workers` 设置，以优化清理周转时间。

有关更多信息，请参阅 [Parallel vacuuming in Amazon RDS for PostgreSQL and Amazon Aurora PostgreSQL](https://aws.amazon.com/blogs/database/parallel-vacuuming-in-amazon-rds-for-postgresql-and-amazon-aurora-postgresql/)。

## 需要清理的表或数据库太多
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables"></a>

如 PostgreSQL 的[自动真空进程守护程序](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM')文档中所述，自动真空进程守护程序通过多个进程运行。这包括一个持久性自动真空启动程序，负责为系统中的每个数据库启动自动真空工件进程。该启动程序安排这些工件大约每个数据库每 `autovacuum_naptime` 秒启动一次。

对于“N”个数据库，大约每 [`autovacuum_naptime`/N 秒] 就会有一个新工件开始工作。但是，并发工件的总数受 `autovacuum_max_workers` 设置的限制。如果需要清理的数据库或表的数量超过此限制，则一旦有工件可用，就会立即处理下一个数据库或表。

当许多大型表或数据库需要同时执行清理操作时，所有可用的自动真空工件可能会长时间被占用，从而会延迟其他表和数据库的维护。在事务速率较高的环境中，此瓶颈可能会迅速升级，并可能导致 Amazon RDS 实例中出现重叠真空问题。

当 `postgres_get_av_diag()` 检测到大量表或数据库时，它会提供以下建议：

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_max_workers:3 might not be sufficient. Consider increasing the setting and, if necessary, consider scaling up the Amazon RDS instance class for more workers.
```

**指南**

**增加 autovacuum\$1max\$1workers**

为了加快清理速度，我们建议调整 `autovacuum_max_workers` 参数以允许更多并发自动真空工件。如果性能瓶颈仍然存在，请考虑将 Amazon RDS 实例扩展到具有更多 vCPU 的类，这样可以进一步提高并行处理能力。

## 正在运行积极真空（以防止重叠）
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum"></a>

PostgreSQL 中数据库（MaximumUsedTransactionIDs）的龄期仅会在成功完成积极真空（以防止重叠）时减少。在此真空结束之前，龄期将继续增加，具体取决于事务速率。

`postgres_get_av_diag()` 函数在检测到积极真空时会生成以下 `NOTICE`。但是，只有在真空处于活动状态至少两分钟后，它才会触发此输出。

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```

有关积极真空的更多信息，请参阅[当积极真空已经在运行时](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)。

您可以使用以下查询验证是否正在进行主动清理：

```
SELECT
    a.xact_start AS start_time,
    v.datname "database",
    a.query,
    a.wait_event,
    v.pid,
    v.phase,
    v.relid::regclass,
    pg_size_pretty(pg_relation_size(v.relid)) AS heap_size,
    (
        SELECT
            string_agg(pg_size_pretty(pg_relation_size(i.indexrelid)) || ':' || i.indexrelid::regclass || chr(10), ', ')
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS index_sizes,
    trunc(v.heap_blks_scanned * 100 / NULLIF(v.heap_blks_total, 0)) AS step1_scan_pct,
    v.index_vacuum_count || '/' || (
        SELECT
            count(*)
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS step2_vacuum_indexes,
    trunc(v.heap_blks_vacuumed * 100 / NULLIF(v.heap_blks_total, 0)) AS step3_vacuum_pct,
    age(CURRENT_TIMESTAMP, a.xact_start) AS total_time_spent_sofar
FROM
    pg_stat_activity a
    INNER JOIN pg_stat_progress_vacuum v ON v.pid = a.pid;
```

您可以通过检查输出中的查询列来确定这是否为积极真空（以防止重叠）。“防止重叠”一词表示这是一个积极真空。

```
query                  | autovacuum: VACUUM public.t3 (to prevent wraparound)
```

例如，假设您有一个事务龄期为 10 亿的拦截器，还有一个需要积极真空的表，以防止在相同的事务龄期出现重叠。此外，在事务龄期为 7.5 亿时，还有另一个拦截器。在事务龄期为 10 亿时清除拦截器后，事务龄期不会立即下降到 7.5 亿。它将保持较高的状态，直到需要积极真空或任何龄期超过 7.5 亿的事务完成为止。在此期间，PostgreSQL 集群的事务龄期将持续提高。真空过程完成后，事务龄期将降至 7.5 亿，但在进一步的清理完成之前，事务龄期将再次开始增加。只要这些条件仍然存在，此循环就会继续，直到事务龄期最终下降到为您的 Amazon RDS 实例配置的级别（由 `autovacuum_freeze_max_age` 指定）。

# RDS for PostgreSQL 中的通知消息说明
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE"></a>

 `postgres_get_av_diag()` 函数提供以下通知消息：

**当龄期尚未达到监控阈值时**  
默认情况下，`postgres_get_av_diag()` 识别拦截器的监控阈值为 5 亿个事务。如果 `postgres_get_av_diag()` 生成以下通知，则表示事务龄期尚未达到此阈值。  

```
NOTICE: postgres_get_av_diag() checks for blockers that prevent aggressive vacuums only, it does so only after exceeding dvb_threshold which is 500,000,000 and age of this PostgreSQL cluster is currently at 2.
```

**未连接到具有最早事务 ID 龄期的数据库**  
当连接到具有最早事务 ID 龄期的数据库时，`postgres_get_av_diag()` 函数可提供最准确的输出。`postgres_get_av_diag()` 报告的具有最早事务 ID 龄期的数据库将不同于您的案例中的“my\$1database”。如果您未连接到正确的数据库，则会生成以下通知：  

```
NOTICE: You are not connected to the database with the age of oldest transaction ID. Connect to my_database database and run postgres_get_av_diag() for accurate reporting.
```
出于以下原因，连接到具有最早事务龄期的数据库非常重要：  
+ **识别临时表拦截器：**由于临时表的元数据特定于每个数据库，因此它们通常位于在其中创建临时表的数据库中。但是，如果临时表恰好是最重要的拦截器，并且位于具有最早事务的数据库中，则可能会产生误导。连接到正确的数据库可确保准确识别临时表拦截器。
+ **诊断缓慢真空：**索引元数据和表计数信息是特定于数据库的，是诊断缓慢真空问题所必需的。

**按龄期计算具有最早事务的数据库位于 rdsadmin 或 template0 数据库中**  
在某些情况下，`rdsadmin` 或 `template0` 数据库可能会被标识为具有最早事务 ID 龄期的数据库。如果发生这种情况，`postgres_get_av_diag()` 将发出以下通知：  

```
NOTICE: The database with the age of oldest transaction ID is rdsadmin or template0, reach out to support if the reported blocker is in rdsadmin or template0.
```
验证列出的拦截器是否不是来自这两个数据库中的任何一个。如果据报告 `rdsadmin` 或 `template0` 中存在拦截器，请联系支持部门，因为这些数据库对用户不可访问，需要干预。  
`rdsadmin` 或 `template0` 数据库包含最重要拦截器的可能性极小。

**当积极真空已经在运行时**  
`postgres_get_av_diag()` 函数旨在报告何时正在运行积极真空进程，但它仅在真空处于活动状态至少 1 分钟后触发此输出。这种有意的延迟有助于减少误报的可能性。通过等待，该函数可确保仅报告有效、重要的真空，从而可更准确、更可靠地监控真空活动。  
`postgres_get_av_diag()` 函数在检测到一个或多个正在进行的积极真空时会生成以下通知。  

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```
如通知中所述，请继续监控真空的性能。有关积极真空的更多信息，请参阅[正在运行积极真空（以防止重叠）](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)

**当自动真空关闭时**  
如果数据库实例上禁用了自动真空，则 `postgres_get_av_diag()` 函数会生成以下通知：  

```
NOTICE: Autovacuum is OFF, we strongly recommend to enable it, no restart is necessary.
```
Autovacuum 是 RDS for PostgreSQL 数据库实例的一项关键功能，可确保数据库顺畅运行。它会自动删除旧的行版本，回收存储空间，并防止表膨胀，从而帮助保持表和索引的高效性，以实现最佳性能。此外，它还可以防止发生事务 ID 重叠，这可能会停止 Amazon RDS 实例上的事务。禁用自动真空会导致数据库性能和稳定性的长期下降。建议您始终将其保持开启状态。有关更多信息，请参阅 [Understanding autovacuum in RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)。  
关闭自动真空并不会阻止积极真空。一旦您的表达到 `autovacuum_freeze_max_age` 阈值，仍会发生这种情况。

**剩余的事务数严重不足**  
`postgres_get_av_diag()` 函数会在即将发生重叠真空时生成以下通知。当您的 Amazon RDS 实例距离可能拒绝新事务还有 1 亿个事务时，将发出此通知。  

```
WARNING: Number of transactions remaining is critically low, resolve issues with autovacuum or perform manual VACUUM FREEZE before your instance stops accepting transactions.
```
需要立即采取行动以免发生数据库停机。您应该密切监控真空操作，并考虑在受影响的数据库上手动启动 `VACUUM FREEZE` 以防止事务失败。

# 管理 Amazon RDS for PostgreSQL 中的高对象计数
<a name="PostgreSQL.HighObjectCount"></a>

虽然 PostgreSQL 限制是理论上的，但数据库中的对象计数极高会对各种操作造成明显的性能影响。本文档介绍几种常见的对象类型，当对象的总计数较高时，可能会导致多种可能的影响。

下表概述了对象类型及其潜在影响：


**对象类型和潜在影响**  

| 对象的类型 | Autovacuum | 逻辑复制 | 主要版本升级 | pg\$1dump/pg\$1restore | 一般性能 | 实例重启 | 
| --- | --- | --- | --- | --- | --- | --- | 
| [关系](#PostgreSQL.HighObjectCount.Relations) | x |  | x | x | x |  | 
| [临时表](#PostgreSQL.HighObjectCount.TempTables)。 | x |  |  |  | x |  | 
| [未记录表](#PostgreSQL.HighObjectCount.UnloggedTables) |  | x |  |  |  | x | 
| [分区](#PostgreSQL.HighObjectCount.Partitions) |  |  |  |  | x |  | 
| [临时文件](#PostgreSQL.HighObjectCount.TempFiles) |  |  |  |  | x |  | 
| [序列](#PostgreSQL.HighObjectCount.Sequences) |  | x |  |  |  |  | 
| [大型对象](#PostgreSQL.HighObjectCount.LargeObjects) |  | x | x |  |  |  | 

## 关系
<a name="PostgreSQL.HighObjectCount.Relations"></a>

对 PostgreSQL 数据库中表的数量没有具体的硬性限制。理论上限极高，但在数据库设计过程中还需要记住其它实际限制。

**影响：Autovacuum 滞后**  
由于工作线程不足以应对繁重的工作量，Autovacuum 可能难以跟上事务 ID 的增长或表膨胀。  
**建议的操作：**要使 autovacuum 能够适应给定数量的表和给定的工作负载，需考虑多个调优因素。有关如何确定适当的 autovacuum 设置的建议，请参阅[使用 PostgreSQL autovacuum 的最佳实践](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)。使用 [postgres\$1get\$1av\$1diag utility](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions.html) 来监控事务 ID 增长问题。

**影响：主要版本升级/pg\$1dump 和还原**  
Amazon RDS 在 pg\$1upgrade 执行期间使用“--link”选项来避免必须复制数据文件，但仍需要将架构元数据还原到新版本的数据库中。即使使用并行 pg\$1restore，但如果存在大量的关系，这也将增加停机时间。

**影响：一般性能降级**  
由于目录大小，导致一般性能降级。每个表及其关联的列将添加到 `pg_attribute`、`pg_class` 和 `pg_depend` 表中，这些表在常规数据库操作中频繁使用。不会显示特定的等待事件，但共享缓冲区效率会受到影响。  
**建议的操作：**定期检查这些特定表的表膨胀情况，偶尔对这些特定的表执行 `VACUUM FULL`。请注意，对目录表执行 `VACUUM FULL` 需要 `ACCESS EXCLUSIVE` 锁，这意味着在操作完成之前，任何其它查询都无法访问这些表。

**影响：文件描述符耗尽**  
错误：“out of file descriptors: Too many open files in system; release and retry”。PostgreSQL `max_files_per_process` 参数决定了每个进程可以打开多少个文件。如果有大量的连接加入大量的表，则有可能达到此限制。  
**建议的操作：**  
+ 降低 `max_files_per_process` 参数的值可能有助于缓解此错误。每个进程和子进程（例如，并行查询）可以打开此数量的文件，如果查询要联接多个表，则此限制可能会耗尽。
+ 减少连接总数并使用连接池程序，例如 [Amazon RDS 代理](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)或其它解决方案（如 PgBouncer）。要了解更多信息，请参阅 [PGBouncer](https://www.pgbouncer.org/) 网站。

**影响：索引节点耗尽**  
错误：“设备上没有剩余空间”。如果在有充足的可用存储空间时观察到这种情况，则这是由于索引节点用完所致。[Amazon RDS 增强监控](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)会显示正在使用的索引节点以及可用于主机的最大数量。

**近似阈值：**[百万](#PostgreSQL.HighObjectCount.Note)

## 临时表
<a name="PostgreSQL.HighObjectCount.TempTables"></a>

使用临时表对测试数据或中间结果很有用，这是许多数据库引擎中常见的模式。必须了解在 PostgreSQL 中大量使用的影响，以避免一些陷阱。每个临时表创建和删除都会向系统目录表中添加行，当它们变得膨胀时，这将导致一般性能问题。

**影响：Autovacuum 滞后**  
临时表不会被 autovacuum 清空，但会在它们存在期间保留事务 ID，如果不移除，可能会导致环绕。  
**建议的操作：**临时表将在创建临时表的会话持续时间内生效，也可以手动删除它们。避免使用临时表执行长时间运行的事务的最佳实践，可防止这些表促成已用事务 ID 增长达到最大程度。

**影响：一般性能降级**  
由于目录大小，导致一般性能降级。当会话不断地创建和删除临时表时，将会增加 `pg_attribute`、`pg_class` 和 `pg_depend` 表的大小，正常数据库操作中会频繁使用这些表。不会显示特定的等待事件，但共享缓冲区效率会受到影响。  
**建议的操作：**  
+ 定期检查这些特定表的表膨胀情况，偶尔对这些特定的表执行 `VACUUM FULL`。请注意，对目录表执行 `VACUUM FULL` 需要 `ACCESS EXCLUSIVE` 锁，这意味着在操作完成之前，任何其它查询都无法访问这些表。
+ 如果大量使用临时表，则在主要版本升级之前，强烈建议对这些特定的目录表执行 `VACUUM FULL`，以减少停机时间。

**一般最佳实践：**
+ 通过使用公用表表达式生成中间结果，减少临时表的使用。这些有时会使所需的查询复杂化，但会消除上面列出的影响。
+ 通过使用 `TRUNCATE` 命令清除内容，而不是执行删除/创建步骤，重用临时表。这也将消除由临时表导致的事务 ID 增长问题。

**近似阈值：**[数万](#PostgreSQL.HighObjectCount.Note)

## 未记录表
<a name="PostgreSQL.HighObjectCount.UnloggedTables"></a>

未记录的表可以提高性能，因为它们不会生成任何 WAL 信息。必须谨慎使用这些表，原因在于，它们在数据库崩溃恢复期间不会提供持久性，因为这些表会被截断。在 PostgreSQL 中，这是一项代价高昂的操作，因为每个未记录的表都会依次被截断。虽然对于少量未记录的表来说，此操作速度很快，但当它们的数量达到数千个时，可能会在启动过程中开始增加明显的延迟。

**影响：逻辑复制**  
逻辑复制中通常不包括未记录的表，包括[蓝绿部署](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)，因为逻辑复制依赖于 WAL 来捕获和传输更改。

  


**影响：恢复期间的停机时间延长**  
在任何涉及数据库崩溃恢复的数据库状态（例如带失效转移的多可用区重启、Amazon RDS 时间点故障恢复和 Amazon RDS 主要版本升级）期间，都会发生截断未记录表的序列化操作。这可能导致停机时间比预期长很多。  
**建议的操作：**  
+ 尽量减少将未记录的表仅用于在数据库崩溃恢复操作期间可以接受丢失的数据。
+ 尽量减少使用未记录的表，因为当前的串行截断行为可能会导致数据库花费大量时间来启动。

**一般最佳实践：**
+ 未记录的表不具备崩溃安全功能。在 PostgreSQL 中，启动涉及崩溃恢复的时间点故障恢复需要花大量的时间，因为这是一个截断每个表的串行进程。

**近似阈值：**[数千](#PostgreSQL.HighObjectCount.Note)

## 分区
<a name="PostgreSQL.HighObjectCount.Partitions"></a>

分区可以提高查询性能并提供数据的逻辑组织。在理想情况下，分区的组织方式是为了便于在查询计划和执行期间使用分区修剪。使用过多的分区可能会对查询性能和数据库维护产生负面影响。应谨慎选择如何对表进行分区，因为不良的设计可能会对查询计划和执行的性能产生负面影响。有关分区的详细信息，请参阅 [PostgreSQL 文档](https://www.postgresql.org/docs/current/ddl-partitioning.html)。

**影响：一般性能降级**  
有时，计划时间开销会增加，并且查询的解释计划会变得更加复杂，因此很难确定调优机会。对于版本 18 之前的 PostgreSQL 版本，许多工作负载较高的分区可能会导致 `LWLock:LockManager` 等待。  
**建议的操作：**确定最少的分区数量，这样您既能完成数据的整理，同时又能提供高性能的查询执行。

**影响：维护复杂性**  
分区数量过多会带来维护困难，例如预创建和移除。Autovacuum 会将分区视为正常关系，必须执行定期清理，因此需要足够的工作线程来完成该任务。  
**建议的操作：**  
+ 确保预先创建分区，以便在需要新分区（例如，基于月度的分区）和回滚旧分区时不会阻塞工作负载。
+ 确保有足够的 autovacuum 工作线程来对所有分区进行正常的清理维护。

**近似阈值：**[数百](#PostgreSQL.HighObjectCount.Note)

## 临时文件
<a name="PostgreSQL.HighObjectCount.TempFiles"></a>

与上述临时表不同，当一个复杂的查询可能同时执行多个排序或哈希操作时，PostgreSQL 会创建临时文件，每个操作都使用实例内存来存储结果，直至达到在 `work_mem` 参数中指定的值。当实例内存不足时，会创建临时文件来存储结果。有关临时文件的更多详细信息，请参阅[管理临时文件](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.ManagingTempFiles.html)。如果您的工作负载生成了大量此类文件，则可能会产生多种影响。

  


**影响：文件描述符耗尽**  
错误：“out of file descriptors: Too many open files in system; release and retry”。PostgreSQL `max_files_per_process` 参数决定了每个进程可以打开多少个文件。如果有大量的连接加入大量的表，则有可能达到此限制。  
**建议的操作：**  
+ 降低 `max_files_per_process` 参数的值可能有助于缓解此错误。每个进程和子进程（例如，并行查询）可以打开此数量的文件，如果查询要联接多个表，则此限制可能会耗尽。
+ 减少连接总数并使用连接池程序（例如 [Amazon RDS 代理](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)）或其它解决方案（如 PgBouncer）。要了解更多信息，请参阅 [PGBouncer](https://www.pgbouncer.org/) 网站。

**影响：索引节点耗尽**  
错误：“设备上没有剩余空间”。如果在有充足的可用存储空间时观察到这种情况，则这是由于索引节点用完所致。[Amazon RDS 增强监控](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)会显示正在使用的索引节点以及可用于主机的最大数量。

**一般最佳实践：**
+ 使用[性能详情](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PerfInsights.html)监控临时文件使用情况。
+ 调优生成大量临时文件的查询，以查看是否可能减少临时文件总数。

**近似阈值：**[数千](#PostgreSQL.HighObjectCount.Note)

## 序列
<a name="PostgreSQL.HighObjectCount.Sequences"></a>

序列是 PostgreSQL 中用于自动递增列的底层对象，它们为数据提供了唯一性和密钥。这些序列可以在单独的表上使用，在正常操作期间不会产生任何后果，但逻辑复制除外。

在 PostgreSQL 中，逻辑复制当前不会将序列的当前值复制到任何订阅用户。要了解更多信息，请参阅 [PostgreSQL 文档中的“Restrictions”页面](https://www.postgresql.org/docs/current/logical-replication-restrictions.html)。

**影响：切换时间延长**  
如果您计划使用[ Amazon RDS 蓝绿部署](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)进行任何类型的配置更改或升级，请务必了解大量的序列对切换的影响。切换的最后阶段之一会同步序列的当前值，如果数量达几千个，这将增加总体切换时间。  
**建议的操作：**如果您的数据库工作负载支持使用共享 UUID 而不是按表排序的方法，这将削减切换期间的同步步骤。

**近似阈值：**[数千](#PostgreSQL.HighObjectCount.Note)

## 大型对象
<a name="PostgreSQL.HighObjectCount.LargeObjects"></a>

大型对象存储在名为 pg\$1largeobject 的单个系统表中。每个大型对象在系统表 pg\$1largeobject\$1metadata 中也有一个条目。这些对象的创建、修改和清理方式与标准关系大不相同。大型对象不是通过 autovacuum 处理，而必须通过名为 vacuumlo 的单独进程定期清理。有关管理大型对象的示例，请参阅“使用 lo 模块管理大型对象”。

**影响：逻辑复制**  
在逻辑复制期间，当前不会在 PostgreSQL 中复制大型对象。要了解更多信息，请参阅 [PostgreSQL 文档中的“Restrictions”页面](https://www.postgresql.org/docs/current/logical-replication-restrictions.html)。在[蓝绿](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)配置中，这意味着蓝色环境中的大型对象不会复制到绿色环境中。

**影响：主要版本升级**  
如果有数百万个大型对象，并且实例在升级期间无法处理它们，则升级可能会耗尽内存并失败。PostgreSQL 主要版本升级过程包括两个主要阶段：通过 pg\$1dump 转储架构和通过 pg\$1restore 还原架构。如果数据库具有数百万个大型对象，则您需要确保实例具有足够的内存，可在升级期间处理 pg\$1dump 和 pg\$1restore，并将其扩展到更大的实例类型。

**一般最佳实践：**
+ 定期使用 vacuumlo 实用程序移除您可能拥有的任何孤立的大型对象。
+ 考虑使用 BYTEA 数据类型来将大型对象存储在数据库中。

**近似阈值：**[百万](#PostgreSQL.HighObjectCount.Note)

## 近似阈值
<a name="PostgreSQL.HighObjectCount.Note"></a>

本主题中提到的近似阈值仅用于估算特定资源可以扩展到多大程度。它们代表了更有可能受到上述影响的一般范围，但实际行为取决于您的特定工作负载、实例大小和配置。虽然可能超过这些估算值，但必须坚持谨慎行事并进行维护，以避免所列的影响。

# 管理 Amazon RDS for PostgreSQL 中的 TOAST OID 争用
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID"></a>

TOAST（超大属性存储技术）是一项 PostgreSQL 功能，旨在处理超过典型 8KB 数据库块大小的大数据值。PostgreSQL 不允许物理行跨越多个块。块大小是行大小的上限。TOAST 通过将较大的字段值拆分为较小的块来克服这一限制。它将这些块单独存储在链接到主表的专用 TOAST 表中。有关更多信息，请参阅 [PostgreSQL TOAST storage mechanism and implementation documentation](https://www.postgresql.org/docs/current/storage-toast.html)。

**Topics**
+ [了解 TOAST 操作](#Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.HowWorks)
+ [识别性能方面的挑战](#Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.PerformanceChallenges)
+ [建议](#Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.Recommendations)
+ [监控](#Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.Monitoring)

## 了解 TOAST 操作
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.HowWorks"></a>

TOAST 行压缩并将大字段值存储在行外。TOAST 为存储在 TOAST 表中的每个超大数据块分配一个唯一的 OID（对象标识符）。主表在页面上存储 TOAST 值的 ID 和关系 ID，以引用 TOAST 表中相应的行。这使得 PostgreSQL 能够高效地定位和管理这些 TOAST 数据块。然而，随着 TOAST 表的增长，系统面临耗尽可用 OID 的风险，进而导致性能下降，甚至因 OID 耗尽而引发潜在的停机。

### TOAST 中的对象标识符
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.ObjectIdentifiers"></a>

对象标识符（OID）是 PostgreSQL 中用于引用数据库对象（如表、索引和函数）的一种系统范围内唯一标识符。这些标识符在 PostgreSQL 的内部操作中发挥着关键作用，使数据库能够高效地定位和管理对象。

对于符合 TOAST 条件的数据表，PostgreSQL 会为存储在相关 TOAST 表中的每个超大数据块分配一个 OID，用于唯一标识该数据块。系统还会为每个数据块关联一个 `chunk_id`，以便 PostgreSQL 在 TOAST 表中高效地组织和定位这些数据块。

## 识别性能方面的挑战
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.PerformanceChallenges"></a>

PostgreSQL 的 OID 管理依赖一个全局 32 位计数器，因此在生成 40 亿个唯一值后会发生循环回绕。尽管整个数据库集群共享这一计数器，但在 TOAST 操作中，OID 分配过程包括以下两步：
+ **全局计数器分配** - 全局计数器在集群范围内分配一个新的 OID。
+ **本地冲突检查** – TOAST 表负责确保新分配的 OID 不与该特定表中已有的 OID 冲突。

在以下情况下，可能会出现性能下降问题：
+ TOAST 表存在高度碎片或 OID 使用密集，导致 OID 分配过程延迟。
+ 在高数据变更率或广表结构中频繁使用 TOAST 时，系统将不断分配和重用 OID，从而加剧 OID 管理的负担。

有关更多信息，请参阅 [PostgreSQL TOAST table size limits and OID allocation documentation](https://wiki.postgresql.org/wiki/TOAST#Total_table_size_limit)：

全局计数器负责生成 OID，并且每生成 40 亿个值后就会循环回绕，因此系统偶尔会生成一个已经使用过的值。PostgreSQL 会检测到这种情况，并自动尝试使用下一个 OID。如果 TOAST 表中存在一大段连续使用的 OID 而没有空隙，就可能导致 INSERT 操作变慢。随着 OID 空间逐渐填满，这些问题会变得更加明显，导致插入和更新操作的性能下降。

### 识别问题
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.IdentifyingProblem"></a>
+ 简单的 `INSERT` 语句会随机出现明显变慢的情况，时快时慢，缺乏一致性。
+ 延迟仅发生在涉及 TOAST 操作的 `INSERT` 和 `UPDATE` 语句上。
+ 当 PostgreSQL 在 TOAST 表中难以找到可用 OID 时，日志中会出现如下条目：

  ```
  LOG: still searching for an unused OID in relation "pg_toast_20815"
  DETAIL: OID candidates have been checked 1000000 times, but no unused OID has been found yet.
  ```
+ 性能详情显示与 `LWLock:buffer_io` 和 `LWLock:OidGenLock` 等待事件相关的平均活跃会话（AAS）数量较多。

  您可以运行以下 SQL 查询来识别具有等待事件的长时间运行的 INSERT 事务：

  ```
  SELECT
      datname AS database_name,
      usename AS database_user,
      pid,
      now() - pg_stat_activity.xact_start AS transaction_duration,
      concat(wait_event_type, ':', wait_event) AS wait_event,
      substr(query, 1, 30) AS TRANSACTION,
      state
  FROM
      pg_stat_activity
  WHERE (now() - pg_stat_activity.xact_start) > INTERVAL '60 seconds'
      AND state IN ('active', 'idle in transaction', 'idle in transaction (aborted)', 'fastpath function call', 'disabled')
      AND pid <> pg_backend_pid()
  AND lower(query) LIKE '%insert%'
  ORDER BY
      transaction_duration DESC;
  ```

  显示等待时间较长的 INSERT 操作的查询结果示例：

  ```
   database_name |  database_user  |  pid  | transaction_duration |     wait_event      |          transaction           | state
  ---------------+-----------------+-------+----------------------+---------------------+--------------------------------+--------
   postgres       | db_admin_user| 70965 | 00:10:19.484061      | LWLock:buffer_io    | INSERT INTO "products" (......... | active
   postgres       | db_admin_user| 69878 | 00:06:14.976037      | LWLock:buffer_io    | INSERT INTO "products" (......... | active
   postgres       | db_admin_user| 68937 | 00:05:13.942847      | :                   | INSERT INTO "products" (......... | active
  ```

### 查明问题
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.IsolatingProblem"></a>
+ **测试小型插入** - 插入一条小于 `toast_tuple_target` 阈值的记录。请注意，压缩会在 TOAST 存储之前应用。如果此操作没有性能问题，则说明问题与 TOAST 操作有关。
+ **测试新表** – 创建一个结构相同的新表，并插入一条大于 `toast_tuple_target` 的记录。如果此操作正常，则说明问题局限于原表的 OID 分配。

## 建议
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.Recommendations"></a>

以下方法可帮助解决 TOAST OID 争用问题。
+ **数据清理与归档** – 审查并删除任何过期或不必要的数据，以释放 OID 供将来使用，或者将数据归档。请考虑以下限制：
  + 可扩展性有限，因为将来并非总是能够执行清理操作。
  + 可能需要执行耗时的 VACUUM 操作，以清理由此产生的死元组。
+ **写入新表** - 为将来的插入操作创建新表，并使用 `UNION ALL` 视图将旧表和新表的数据合并用于查询。该视图呈现来自旧表和新表的组合数据，使查询能够像访问单张表一样访问数据。请考虑以下限制：
  + 对旧表的更新仍可能导致 OID 耗尽问题。
+ **分区或分片** - 对表进行分区或对数据进行分片，以提升可扩展性和性能。请考虑以下限制：
  + 查询逻辑和维护复杂度增加，可能需要对应用程序进行修改，以正确处理分区或分片数据。

## 监控
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.Monitoring"></a>

### 使用系统表
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.SystemTables"></a>

您可以使用 PostgreSQL 的系统表来监控 OID 使用量的增长情况。

**警告**  
根据 TOAST 表中 OID 的数量，此操作可能需要一定时间才能完成。建议在非工作时间安排监控，以将对业务的影响降到最低。

以下匿名块统计每个 TOAST 表中使用的不同 OID 数量，并显示其父表的信息：

```
DO $$
DECLARE
    r record;
    o bigint;
    parent_table text;
    parent_schema text;
BEGIN
    SET LOCAL client_min_messages TO notice;
    FOR r IN
    SELECT
        c.oid,
        c.oid::regclass AS toast_table
    FROM
        pg_class c
    WHERE
        c.relkind = 't'
        AND c.relowner != 10 LOOP
            -- Fetch the number of distinct used OIDs (chunk IDs) from the TOAST table
            EXECUTE 'SELECT COUNT(DISTINCT chunk_id) FROM ' || r.toast_table INTO o;
            -- If there are used OIDs, find the associated parent table and its schema
            IF o <> 0 THEN
                SELECT
                    n.nspname,
                    c.relname INTO parent_schema,
                    parent_table
                FROM
                    pg_class c
                    JOIN pg_namespace n ON c.relnamespace = n.oid
                WHERE
                    c.reltoastrelid = r.oid;
                -- Raise a concise NOTICE message
                RAISE NOTICE 'Parent schema: % | Parent table: % | Toast table: % | Number of used OIDs: %', parent_schema, parent_table, r.toast_table, TO_CHAR(o, 'FM9,999,999,999,999');
            END IF;
        END LOOP;
END
$$;
```

按照 TOAST 表显示 OID 使用情况统计信息的输出示例：

```
NOTICE:  Parent schema: public | Parent table: my_table | Toast table: pg_toast.pg_toast_16559 | Number of used OIDs: 45,623,317
NOTICE:  Parent schema: public | Parent table: my_table1 | Toast table: pg_toast.pg_toast_45639925 | Number of used OIDs: 10,000
NOTICE:  Parent schema: public | Parent table: my_table2 | Toast table: pg_toast.pg_toast_45649931 | Number of used OIDs: 1,000,000
DO
```

以下匿名块检索为每个非空 TOAST 表分配的最大 OID：

```
DO $$
DECLARE
    r record;
    o bigint;
    parent_table text;
    parent_schema text;
BEGIN
    SET LOCAL client_min_messages TO notice;
    FOR r IN
    SELECT
        c.oid,
        c.oid::regclass AS toast_table
    FROM
        pg_class c
    WHERE
        c.relkind = 't'
        AND c.relowner != 10 LOOP
            -- Fetch the max(chunk_id) from the TOAST table
            EXECUTE 'SELECT max(chunk_id) FROM ' || r.toast_table INTO o;
            -- If there's at least one TOASTed chunk, find the associated parent table and its schema
            IF o IS NOT NULL THEN
                SELECT
                    n.nspname,
                    c.relname INTO parent_schema,
                    parent_table
                FROM
                    pg_class c
                    JOIN pg_namespace n ON c.relnamespace = n.oid
                WHERE
                    c.reltoastrelid = r.oid;
                -- Raise a concise NOTICE message
                RAISE NOTICE 'Parent schema: % | Parent table: % | Toast table: % | Max chunk_id: %', parent_schema, parent_table, r.toast_table, TO_CHAR(o, 'FM9,999,999,999,999');
            END IF;
        END LOOP;
END
$$;
```

显示 TOAST 表的最大块 ID 的输出示例：

```
NOTICE:  Parent schema: public | Parent table: my_table | Toast table: pg_toast.pg_toast_16559 | Max chunk_id: 45,639,907
NOTICE:  Parent schema: public | Parent table: my_table1 | Toast table: pg_toast.pg_toast_45639925 | Max chunk_id: 45,649,929
NOTICE:  Parent schema: public | Parent table: my_table2 | Toast table: pg_toast.pg_toast_45649931 | Max chunk_id: 46,649,935
DO
```

### 使用性能详情
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.PerformanceInsights"></a>

在需要分配新的对象标识符（OID）的操作过程中，性能详情中会显示 `LWLock:buffer_io` 和 `LWLock:OidGenLock` 等待事件。这些等待事件的平均活跃会话（AAS）较高通常表明在 OID 分配和资源管理过程中存在争用。这种情况在数据变更频繁、大型数据使用广泛或对象创建频繁的环境中尤为常见。

#### LWLock:buffer\$1io
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.LWLockBufferIO"></a>

`LWLock:buffer_io` 是一种等待事件，当 PostgreSQL 会话在等待共享缓冲区的 I/O 操作完成时会发生。通常在以下情况下出现：数据库从磁盘读取数据到内存中将修改后的页面从内存写回磁盘。`BufferIO` 等待事件通过在 I/O 操作进行时阻止多个进程访问或修改同一缓冲区，从而确保数据一致性。该等待事件频繁出现可能表明数据库工作负载中存在磁盘瓶颈或过高的 I/O 活动。

在 TOAST 操作期间：
+ PostgreSQL 会为大型对象分配 OID，并通过扫描 TOAST 表的索引来确保其唯一性。
+ 大型 TOAST 索引可能需要访问多个页面以验证 OID 的唯一性。当缓冲池无法缓存所有所需页面时，会导致磁盘 I/O 增加。

索引的大小直接影响在这些操作中需要访问的缓冲区页面数量。即使索引本身未膨胀，其体积也可能增加缓冲 I/O，尤其在高并发或数据变更频繁的环境中。有关更多信息，请参阅 [LWLock:BufferIO wait event troubleshooting guide](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/apg-waits.lwlockbufferio.html)。

#### LWLock:OidGenLock
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.LWLockOidGenLock"></a>

`OidGenLock` 是一种等待事件，当 PostgreSQL 会话在等待分配新的对象标识符（OID）时发生。该锁确保 OID 按顺序且安全地生成，每次仅允许一个进程生成 OID。

在 TOAST 操作期间：
+ **TOAST 表中数据块的 OID 分配** – PostgreSQL 在管理大数据记录时，为 TOAST 表中的数据块分配 OID。每个 OID 必须唯一，以避免系统目录中发生冲突。
+ **高并发** – 由于访问 OID 生成器是顺序进行的，当多个会话同时创建需要 OID 的对象时，可能会发生 `OidGenLock` 争用，增加会话等待 OID 分配完成的概率。
+ **依赖系统目录访问** – 分配 OID 需要更新共享系统目录表，如 `pg_class` 和 `pg_type`。如果这些表活动频繁（例如频繁执行 DDL 操作），会加剧 `OidGenLock` 的锁争用。
+ **高 OID 分配需求** – 在 TOAST 工作负载中，处理大型数据记录需要持续分配 OID，从而增加争用。

额外导致 OID 争用的因素：
+ **频繁创建对象** – 经常创建和删除对象（例如临时表）的工作负载，会放大全局 OID 计数器的争用。
+ **全局计数器锁定** – 为确保唯一性，全局 OID 计数器采用串行访问机制，这在高并发环境中会形成单一争用点。

## 使用 RDS for PostgreSQL 支持的日志记录机制
<a name="Appendix.PostgreSQL.CommonDBATasks.Auditing"></a>

您可以设置多个参数、扩展和其他可配置项来记录 PostgreSQL 数据库实例中发生的活动。这些功能包括：
+ `log_statement` 参数可用于记录 PostgreSQL 数据库中的用户活动。要了解有关 RDS for PostgreSQL 日志记录以及如何监控日志的更多信息，请参阅 [RDS for PostgreSQL 数据库日志文件](USER_LogAccess.Concepts.PostgreSQL.md)。
+ `rds.force_admin_logging_level` 参数记录数据库实例上的数据库中由 Amazon RDS 内部用户 (rdsadmin) 执行的操作。它将输出写入 PostgreSQL 错误日志。允许的值包括 `disabled`、`debug5`、`debug4`、`debug3`、`debug2`、`debug1`、`info`、`notice`、`warning`、`error`、日志、`fatal` 和 `panic`。默认值为 `disabled`。
+ 可以设置 `rds.force_autovacuum_logging_level` 参数以捕获 PostgreSQL 错误日志中的各种 autovacuum 操作。有关更多信息，请参阅 [记录 autovacuum 和 vacuum 活动](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging.md)。
+ 可以安装和配置 PostgreSQL Audit（pgAudit）扩展，以在会话级别或在对象级别捕获活动。有关更多信息，请参阅 [使用 pgAudit 记录数据库活动](Appendix.PostgreSQL.CommonDBATasks.pgaudit.md)。
+ `log_fdw` 扩展使您可以使用 SQL 访问数据库引擎日志。有关更多信息，请参阅 [使用 log\$1fdw 扩展通过 SQL 访问数据库日志](CHAP_PostgreSQL.Extensions.log_fdw.md)。
+ `pg_stat_statements` 库被指定为 RDS for PostgreSQL 版本 10 及更高版本中 `shared_preload_libraries` 参数的默认值。您可以使用该库分析正在运行的查询。确保在数据库参数组中设置 `pg_stat_statements`。有关使用此库提供的信息监控 RDS for PostgreSQL 数据库实例的更多信息，请参阅 [RDS PostgreSQL 的 SQL 统计数据](USER_PerfInsights.UsingDashboard.AnalyzeDBLoad.AdditionalMetrics.PostgreSQL.md)。
+ `log_hostname` 参数将每个客户端连接的主机名捕获到日志中。对于 RDS for PostgreSQL 版本 12 及更高版本，原定设置情况下，此参数设置为 `off`。如果您将其开启，请务必监视会话连接时间。开启后，该服务使用域名系统（DNS）反向查找请求来获取进行连接的客户端的主机名并将其添加到 PostgreSQL 日志中。这在会话连接期间会产生明显的影响。我们建议您仅出于故障排除目的开启此参数。

一般来说，日志记录的目的是使数据库管理员能够监控、优化性能和进行故障排除。许多日志都会自动上载到 Amazon CloudWatch 或 Performance Insights。在这里，对这些日志进行排序和分组，从而为您的数据库实例提供完整指标。要了解有关 Amazon RDS 监控和指标的更多信息，请参阅 [监控 Amazon RDS 实例中的指标](CHAP_Monitoring.md)。

# 使用 PostgreSQL 管理临时文件
<a name="PostgreSQL.ManagingTempFiles"></a>

在 PostgreSQL 中，一个复杂的查询可能会同时执行几个排序或哈希操作，每个操作都使用实例内存来存储结果，直至达到在 [https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM) 参数中指定的值。当实例内存不足时，会创建临时文件来存储结果。这些文件写入磁盘以完成查询执行。稍后，将在查询完成后自动删除这些文件。在 RDS for PostgreSQL 中，这些文件存储在数据卷上的 Amazon EBS 中。有关更多信息，请参阅 [Amazon RDS 数据库实例存储](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)。您可以监控 CloudWatch 内发布的 `FreeStorageSpace` 指标，以确保数据库实例具有足够的可用存储空间。有关更多信息，请参阅 [https://repost.aws/knowledge-center/storage-full-rds-cloudwatch-alarm](https://repost.aws/knowledge-center/storage-full-rds-cloudwatch-alarm)。

对于涉及多个并发查询的工作负载（这会增加临时文件的使用量），我们建议使用 Amazon RDS 优化型读取实例。这些实例使用基于本地非易失性存储规范（NVMe）的固态硬盘（SSD）块级存储来存放临时文件。有关更多信息，请参阅 [使用 Amazon RDS 优化型读取功能提高 RDS for PostgreSQL 的查询性能](USER_PostgreSQL.optimizedreads.md)。

您可以使用下面的参数和函数来管理实例中的临时文件。
+ **[https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-DISK](https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-DISK)** – 此参数取消任何超过 temp\$1files 大小（以 KB 为单位）的查询。此限制可防止任何查询无休止地运行并使用临时文件消耗磁盘空间。您可以使用来自 `log_temp_files` 参数的结果来估计该值。作为最佳实践，请检查工作负载行为并根据估计值设置限制。以下示例显示了当查询超过限制时如何取消查询。

  ```
  postgres=>select * from pgbench_accounts, pg_class, big_table;
  ```

  ```
  ERROR: temporary file size exceeds temp_file_limit (64kB)
  ```
+ **[https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-TEMP-FILES](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-TEMP-FILES)** – 当删除会话的临时文件时，此参数会向 postgresql.log 发送消息。此参数在查询成功完成后生成日志。因此，它可能无助于对长时间运行的活跃查询进行故障排除。

  以下示例显示，当查询成功完成后，条目将记录在 postgresql.log 文件中，同时清理临时文件。

  ```
                      
  2023-02-06 23:48:35 UTC:205.251.233.182(12456):adminuser@postgres:[31236]:LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp31236.5", size 140353536
  2023-02-06 23:48:35 UTC:205.251.233.182(12456):adminuser@postgres:[31236]:STATEMENT:  select a.aid from pgbench_accounts a, pgbench_accounts b where a.bid=b.bid order by a.bid limit 10;
  2023-02-06 23:48:35 UTC:205.251.233.182(12456):adminuser@postgres:[31236]:LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp31236.4", size 180428800
  2023-02-06 23:48:35 UTC:205.251.233.182(12456):adminuser@postgres:[31236]:STATEMENT:  select a.aid from pgbench_accounts a, pgbench_accounts b where a.bid=b.bid order by a.bid limit 10;
  ```
+ **[https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-GENFILE](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-GENFILE)** – 此函数在 RDS for PostgreSQL 13 及更高版本中提供，可让用户了解当前临时文件使用情况。完成的查询不会出现在该函数的结果中。在以下示例中，您可以查看此函数的结果。

  ```
  postgres=>select * from pg_ls_tmpdir();
  ```

  ```
        name       |    size    |      modification
  -----------------+------------+------------------------
   pgsql_tmp8355.1 | 1072250880 | 2023-02-06 22:54:56+00
   pgsql_tmp8351.0 | 1072250880 | 2023-02-06 22:54:43+00
   pgsql_tmp8327.0 | 1072250880 | 2023-02-06 22:54:56+00
   pgsql_tmp8351.1 |  703168512 | 2023-02-06 22:54:56+00
   pgsql_tmp8355.0 | 1072250880 | 2023-02-06 22:54:00+00
   pgsql_tmp8328.1 |  835031040 | 2023-02-06 22:54:56+00
   pgsql_tmp8328.0 | 1072250880 | 2023-02-06 22:54:40+00
  (7 rows)
  ```

  ```
  postgres=>select query from pg_stat_activity where pid = 8355;
                  
  query
  ----------------------------------------------------------------------------------------
  select a.aid from pgbench_accounts a, pgbench_accounts b where a.bid=b.bid order by a.bid
  (1 row)
  ```

  文件名包括生成了临时文件的会话的处理 ID（PID）。更高级的查询（如以下示例所示）对每个 PID 的临时文件执行总和。

  ```
  postgres=>select replace(left(name, strpos(name, '.')-1),'pgsql_tmp','') as pid, count(*), sum(size) from pg_ls_tmpdir() group by pid;
  ```

  ```
   pid  | count |   sum
  ------+-------------------
   8355 |     2 | 2144501760
   8351 |     2 | 2090770432
   8327 |     1 | 1072250880
   8328 |     2 | 2144501760
  (4 rows)
  ```
+ **`[ pg\$1stat\$1statements](https://www.postgresql.org/docs/current/pgstatstatements.html)`** – 如果您激活 pg\$1stat\$1sat\$1statements 参数，则可以查看每个调用的平均临时文件使用量。您可以识别查询的 query\$1id 并使用它来检查临时文件使用情况，如以下示例所示。

  ```
  postgres=>select queryid from pg_stat_statements where query like 'select a.aid from pgbench%';
  ```

  ```
         queryid
  ----------------------
   -7170349228837045701
  (1 row)
  ```

  ```
  postgres=>select queryid, substr(query,1,25), calls, temp_blks_read/calls temp_blks_read_per_call, temp_blks_written/calls temp_blks_written_per_call from pg_stat_statements where queryid = -7170349228837045701;
  ```

  ```
         queryid        |          substr           | calls | temp_blks_read_per_call | temp_blks_written_per_call
  ----------------------+---------------------------+-------+-------------------------+----------------------------
   -7170349228837045701 | select a.aid from pgbench |    50 |                  239226 |                     388678
  (1 row)
  ```
+ **`[Performance Insights](https://aws.amazon.com/rds/performance-insights/)`** – 在性能详情控制面板中，可以通过开启指标 **temp\$1bytes** 和 **temp\$1files** 来查看临时文件使用情况。然后，您可以看到这两个指标的平均值，并查看它们与查询工作负载的对应关系。性能详情中的视图并未专门显示正在生成临时文件的查询。但是，当您将性能详情与针对 `pg_ls_tmpdir` 显示的查询相结合时，您可以排查、分析并确定查询工作负载的变化。

  有关如何使用性能详情分析指标和查询的更多信息，请参阅[使用 Performance Insights 控制面板分析指标](USER_PerfInsights.UsingDashboard.md)。

  有关使用性能详情查看临时文件使用情况的示例，请参阅[使用性能详情查看临时文件使用情况](PostgreSQL.ManagingTempFiles.Example.md)

# 使用性能详情查看临时文件使用情况
<a name="PostgreSQL.ManagingTempFiles.Example"></a>

可以使用性能详情，通过开启指标 **temp\$1bytes** 和 **temp\$1files** 来查看临时文件使用情况。性能详情中的视图不显示生成临时文件的特定查询，但是，当您将性能详情与针对 `pg_ls_tmpdir` 显示的查询相结合时，可以排查、分析并确定查询工作负载的变化。

1. 在性能详情控制面板中，选择**管理指标**。

1. 选择**数据库指标**，然后选择 **temp\$1bytes** 和 **temp\$1files** 指标，如下图所示。  
![\[图表中显示的指标。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/rpg_mantempfiles_metrics.png)

1. 在 **Top SQL** 选项卡中，选择**首选项**图标。

1. 在**首选项**窗口中，打开 **Top SQL** 选项卡中显示的以下统计数据，然后选择**继续**。
   + 临时写入次数/秒
   + 临时读取次数/秒
   + 临时批量写入/调用
   + 临时批量读取/调用

1. 当临时文件与针对 `pg_ls_tmpdir` 显示的查询相组合时，临时文件将被分解，如以下示例所示。  
![\[显示临时文件使用情况的查询。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/rpg_mantempfiles_query.png)

当您的工作负载中排名靠前的查询经常创建临时文件时，就会发生 `IO:BufFileRead` 和 `IO:BufFileWrite` 事件。通过查看“数据库负载”和“热门 SQL”部分中的平均活动会话（AAS），您可以使用性能详情来确定在 `IO:BufFileRead` 和 `IO:BufFileWrite` 上等待的热门 SQL。

![\[图中的 IO:BufFileRead 和 IO:BufFileWrite。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/perfinsights_IOBufFile.png)


有关如何使用性能详情按等待事件分析热门查询和负载的更多信息，请参阅[“Top SQL”（主要 SQL）选项卡概览](USER_PerfInsights.UsingDashboard.AnalyzeDBLoad.AdditionalMetrics.md#USER_PerfInsights.UsingDashboard.Components.AvgActiveSessions.TopLoadItemsTable.TopSQL)。您应该识别和调整导致临时文件使用量和相关等待事件增加的查询。有关这些等待事件和补救措施的更多信息，请参阅 [IO:BufFileRead 和 IO:BufFileWrite](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/wait-event.iobuffile.html)。

**注意**  
[https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM) 参数控制排序操作何时耗尽内存以及结果何时写入临时文件中。我们建议您不要将此参数的设置更改为高于默认值，因为这将允许每个数据库会话消耗更多内存。此外，执行复杂联接和排序的单个会话可以执行并行操作，其中每个操作都会消耗内存。  
作为最佳实践，当您有一个包含多个联接和排序的大型报告时，请使用 `SET work_mem` 命令在会话级别设置此参数。然后，更改仅应用于当前会话，而不会全局更改该值。

## 将用于日志分析的 pgBadger 与 PostgreSQL 结合使用
<a name="Appendix.PostgreSQL.CommonDBATasks.Badger"></a>

您可以使用日志分析器（如 [pgBadger](http://dalibo.github.io/pgbadger/)）分析 PostgreSQL 日志。pgBadger 文档声明 %l 模式（会话或进程的日志行）应为前缀的一部分。但如果将当前 RDS `log_line_prefix` 作为参数提供给 pgBadger，它应该仍生成报告。

例如，以下命令使用 pgBadger 正确设置日期为 2014-02-04 的 Amazon RDS for PostgreSQL 日志文件的格式。

```
./pgbadger -f stderr -p '%t:%r:%u@%d:[%p]:' postgresql.log.2014-02-04-00 
```

## 使用 PGSnapper 监控 PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Snapper"></a>

可以使用 PGSnapper 协助定期收集 Amazon RDS for PostgreSQL 性能相关的统计数据和指标。有关更多信息，请参阅[使用 PGSnapper 监控 Amazon RDS for PostgreSQL 性能](https://aws.amazon.com/blogs/database/monitor-amazon-rds-for-postgresql-and-amazon-aurora-postgresql-performance-using-pgsnapper/)。

# 在 RDS for PostgreSQL 中管理自定义强制转换
<a name="PostgreSQL.CustomCasts"></a>

PostgreSQL 中的**类型强制转换**是将值从一种数据类型转换为另一种数据类型的过程。PostgreSQL 为许多常见的转换提供了内置的强制转换，但您也可以创建自定义类型强制转换来定义特定类型转换的行为方式。

强制转换指定如何执行从一种数据类型到另一种数据类型的转换。例如，将文本 `'123'` 转换为整数 `123`，或将数值 `45.67` 转换为文本 `'45.67'`。

有关 PostgreSQL 强制转换概念和语法的全面信息，请参阅 [PostgreSQL CREATE CAST 文档](https://www.postgresql.org/docs/current/sql-createcast.html)。

从 RDS for PostgreSQL 版本 13.23、14.20、15.15、16.11、17.7 和 18.1 开始，您可以使用 rds\$1casts 扩展为内置类型安装其它强制转换，同时仍然可以为自定义类型创建自己的强制转换。

**Topics**
+ [安装和使用 rds\$1casts 扩展](#PostgreSQL.CustomCasts.Installing)
+ [支持的强制转换](#PostgreSQL.CustomCasts.Supported)
+ [创建和删除强制转换](#PostgreSQL.CustomCasts.Creating)
+ [使用适当的上下文策略创建自定义强制转换](#PostgreSQL.CustomCasts.BestPractices)

## 安装和使用 rds\$1casts 扩展
<a name="PostgreSQL.CustomCasts.Installing"></a>

要创建 `rds_casts` 扩展，请以 `rds_superuser` 身份连接到 RDS for PostgreSQL 数据库实例，然后运行以下命令。

```
CREATE EXTENSION IF NOT EXISTS rds_casts;
```

## 支持的强制转换
<a name="PostgreSQL.CustomCasts.Supported"></a>

在要使用自定义强制转换的每个数据库中创建此扩展。在创建扩展后，请使用下面的命令来查看所有可用的强制转换：

```
SELECT * FROM rds_casts.list_supported_casts();
```

此函数列出了可用的强制转换组合（源类型、目标类型、强制上下文和强制转换函数）。例如，如果您想要创建从 `text` 到 `numeric` 作为一个 `implicit` 强制转换。您可以使用以下查询来查找强制转换是否可供创建：

```
SELECT * FROM rds_casts.list_supported_casts()
WHERE source_type = 'text' AND target_type = 'numeric';
 id | source_type | target_type |          qualified_function          | coercion_context
----+-------------+-------------+--------------------------------------+------------------
 10 | text        | numeric     | rds_casts.rds_text_to_numeric_custom | implicit
 11 | text        | numeric     | rds_casts.rds_text_to_numeric_custom | assignment
 13 | text        | numeric     | rds_casts.rds_text_to_numeric_custom | explicit
 20 | text        | numeric     | rds_casts.rds_text_to_numeric_inout  | implicit
 21 | text        | numeric     | rds_casts.rds_text_to_numeric_inout  | assignment
 23 | text        | numeric     | rds_casts.rds_text_to_numeric_inout  | explicit
```

rds\$1casts 扩展为每个强制转换提供两种类型的强制转换函数：
+ *\$1inout 函数*：使用 PostgreSQL 的标准 I/O 转换机制，其行为与使用 INOUT 方法创建的强制转换完全相同
+ *\$1custom functions*：提供增强的转换逻辑来处理边缘情况，例如将空字符串转换为 NULL 值以避免转换错误

`inout` 函数复制了 PostgreSQL 的原生强制转换行为，而 `custom` 函数则通过处理标准 INOUT 强制转换无法应对的场景（例如将空字符串转换为整数）来扩展此功能。

## 创建和删除强制转换
<a name="PostgreSQL.CustomCasts.Creating"></a>

您可以使用两种方法创建和删除支持的强制转换：

### 强制转换创建
<a name="PostgreSQL.CustomCasts.Creating.Methods"></a>

**方法 1：使用原生 CREATE CAST 命令**

```
CREATE CAST (text AS numeric)
WITH FUNCTION rds_casts.rds_text_to_numeric_custom
AS IMPLICIT;
```

**方法 2：使用 rds\$1casts.create\$1cast 函数**

```
SELECT rds_casts.create_cast(10);
```

`create_cast` 函数从 `list_supported_casts()` 输出中获取 ID。此方法更简单，可确保您使用正确的函数和上下文组合。此 id 保证在不同的 postgres 版本中保持不变。

要验证是否成功创建了强制转换，请查询 pg\$1cast 系统目录：

```
SELECT oid, castsource::regtype, casttarget::regtype, castfunc::regproc, castcontext, castmethod
FROM pg_cast
WHERE castsource = 'text'::regtype AND casttarget = 'numeric'::regtype;
  oid   | castsource | casttarget |               castfunc               | castcontext | castmethod
--------+------------+------------+--------------------------------------+-------------+------------
 356372 | text       | numeric    | rds_casts.rds_text_to_numeric_custom | i           | f
```

`castcontext` 列显示：`e` 表示 EXPLICIT、`a` 表示 ASSIGNMENT，或 `i` 表示 IMPLICIT。

### 删除强制转换
<a name="PostgreSQL.CustomCasts.Dropping"></a>

**方法 1：使用 DROP CAST 命令**

```
DROP CAST IF EXISTS (text AS numeric);
```

**方法 2：使用 rds\$1casts.drop\$1cast 函数**

```
SELECT rds_casts.drop_cast(10);
```

`drop_cast` 函数采用在创建强制转换时使用的相同 ID。此方法可确保您删除使用相应 ID 创建的确切强制转换。

## 使用适当的上下文策略创建自定义强制转换
<a name="PostgreSQL.CustomCasts.BestPractices"></a>

为整数类型创建多个强制转换时，如果所有强制转换都以 IMPLICIT 形式创建，则可能会出现运算符歧义错误。以下示例通过创建两个从文本到不同整数宽度的隐式强制转换来演示这个问题：

```
-- Creating multiple IMPLICIT casts causes ambiguity
postgres=> CREATE CAST (text AS int4) WITH FUNCTION rds_casts.rds_text_to_int4_custom(text) AS IMPLICIT;
CREATE CAST
postgres=> CREATE CAST (text AS int8) WITH FUNCTION rds_casts.rds_text_to_int8_custom(text) AS IMPLICIT;
CREATE CAST

postgres=> CREATE TABLE test_cast(col int);
CREATE TABLE
postgres=> INSERT INTO test_cast VALUES ('123'::text);
INSERT 0 1
postgres=> SELECT * FROM test_cast WHERE col='123'::text;
ERROR:  operator is not unique: integer = text
LINE 1: SELECT * FROM test_cast WHERE col='123'::text;
                                         ^
HINT:  Could not choose a best candidate operator. You might need to add explicit type casts.
```

之所以出现此错误，是因为在将整数列与文本值进行比较时，PostgreSQL 无法确定要使用哪种隐式强制转换。int4 和 int8 隐式强制转换都是有效的候选强制转换，这会造成歧义。

为避免这种运算符歧义，请使用 ASSIGNMENT 上下文表示较小的整数宽度，并使用 IMPLICIT 上下文表示较大的整数宽度：

```
-- Use ASSIGNMENT for smaller integer widths
CREATE CAST (text AS int2)
WITH FUNCTION rds_casts.rds_text_to_int2_custom(text)
AS ASSIGNMENT;

CREATE CAST (text AS int4)
WITH FUNCTION rds_casts.rds_text_to_int4_custom(text)
AS ASSIGNMENT;

-- Use IMPLICIT for larger integer widths
CREATE CAST (text AS int8)
WITH FUNCTION rds_casts.rds_text_to_int8_custom(text)
AS IMPLICIT;

postgres=> INSERT INTO test_cast VALUES ('123'::text);
INSERT 0 1
postgres=> SELECT * FROM test_cast WHERE col='123'::text;
 col
-----
 123
(1 row)
```

使用这种策略，只有 int8 强制转换是隐式的，因此 PostgreSQL 可以毫不歧义地确定要使用哪种强制转换。

# RDS for PostgreSQL 中并行查询的最佳实践
<a name="PostgreSQL.ParallelQueries"></a>

并行查询执行是 PostgreSQL 中的一项功能，支持将单个 SQL 查询分解为由多个后台工作进程同时处理的较小任务。PostgreSQL 可以将查询的某些部分（例如扫描、联接、聚合或排序）分配到多个 CPU 内核，而不是完全在单个后端进程中执行查询。*领导进程*协调此执行过程并从*并行工作线程*收集结果。

但是，对于大多数生产工作负载，尤其是高并发 OLTP 系统，我们建议禁用自动并行查询执行。虽然并行性可以加快对分析或报告工作负载中大型数据集的查询，但它会带来重大风险，在繁忙的生产环境中，这些风险往往大于收益。

并行执行还会带来大量开销。每个并行工作线程都是一个完整的 PostgreSQL 后端进程，它需要进程分叉（复制内存结构和初始化进程状态）和身份验证（占用 `max_connections` 限制中的连接槽）。每个工作线程还会消耗其自己的内存，包括用于排序和哈希操作的 `work_mem`，每个查询有多个工作线程，内存使用量会迅速成倍增加（例如，4 个工作线程 × 64 MB `work_mem` = 每个查询 256 MB）。因此，与单进程查询相比，并行查询消耗的系统资源可能要大得多。如果调整不当，它们可能会导致 CPU 饱和（多个工作线程使可用的处理能力不堪重负）、上下文切换增加（操作系统频繁在多个工作进程之间切换，增加开销并降低吞吐量）或连接耗尽（由于每个并行工作进程占用一个连接槽，因此包含 4 个工作线程的单个查询总共使用 5 个连接，1 个领导进程 \$1 4 个工作进程，这可能会在高并发下迅速耗尽连接池，从而防止新的客户端连接并导致应用程序故障）。在高并发工作负载下，多个查询可能会同时尝试并行执行，此时这些问题尤其严重。

PostgreSQL 根据成本估算来决定是否使用并行性。在某些情况下，如果并行计划看起来代价较低，即使在实践中并不理想，计划程序也可能会自动切换到并行计划。如果索引统计数据已过时，或者膨胀使顺序扫描看起来比索引查找更具吸引力，则可能会发生这种情况。由于这种行为，自动并行计划有时可能会导致查询性能或系统稳定性出现倒退。

要从 RDS for PostgreSQL 中的并行查询中获得最大优势，务必根据您的工作负载对这些并行查询进行测试和调优，监控系统影响，并禁用自动并行计划选择以支持查询级控制。

## 配置参数
<a name="PostgreSQL.ParallelQueries.ConfigurationParameters"></a>

PostgreSQL 使用多个参数来控制并行查询的行为和可用性。了解和调优这些参数对于实现可预测的性能至关重要：


| 参数 | 说明 | 默认值 | 
| --- | --- | --- | 
| max\$1parallel\$1workers | 总共可以运行的后台工作进程的最大数量 | GREATEST(\$1DBInstanceVCPU/2,8) | 
| max\$1parallel\$1workers\$1per\$1gather | 每个查询计划节点的最大工作线程数（例如，每个 Gather） | 2 | 
| parallel\$1setup\$1cost | 为启动并行查询基础设施而增加的计划程序成本 | 1000 | 
| parallel\$1tuple\$1cost | 在并行模式下处理的每个元组的成本（影响计划程序决策） | 0.1 | 
| force\$1parallel\$1mode | 强制计划程序测试并行计划（off、on、regress） | off | 

### 重要注意事项
<a name="PostgreSQL.ParallelQueries.ConfigurationParameters.KeyConsiderations"></a>
+ `max_parallel_workers` 控制并行工作线程的总池。如果设置得过低，则某些查询可能会回退到串行执行。
+ `max_parallel_workers_per_gather` 影响单个查询可以使用多少个工作线程。值较高会提高并发性，但也会增加资源使用量。
+ `parallel_setup_cost` 和 `parallel_tuple_cost` 影响计划程序的成本模型。降低这些值可以使并行计划更有可能被选中。
+ `force_parallel_mode` 对测试很有用，但除非必要，否则不应在生产环境中使用。

**注意**  
`max_parallel_workers` 参数的默认值是使用公式 `GREATEST($DBInstanceVCPU/2, 8)` 根据实例大小动态计算得出的。这意味着，当您将数据库实例扩展到更大的计算大小和更多 vCPU 时，可用并行工作线程的最大数量将自动增加。因此，以前以串行方式或有限并行性执行的查询可能会在纵向扩展操作后突然利用更多的并行工作线程，从而可能导致连接使用率、CPU 利用率和内存消耗量意外增加。重要的是要在发生任何计算扩展事件后监控并行查询行为，并在必要时调整 `max_parallel_workers_per_gather` 以保持可预测的资源使用量。

## 确定并行查询使用情况
<a name="PostgreSQL.ParallelQueries.IdentifyUsage"></a>

查询可能会根据数据分布或统计数据转变为并行计划。例如：

```
SELECT count(*) FROM customers WHERE last_login < now() - interval '6 months';
```

此查询可能使用最近数据的索引，但切换为对历史数据进行并行顺序扫描。

您可以通过加载 `auto_explain` 模块来记录查询执行计划。要了解更多信息，请参阅 AWS 知识中心中的[记录查询执行计划](https://aws.amazon.com/premiumsupport/knowledge-center/rds-postgresql-tune-query-performance/#)。



您可以监控 [CloudWatch 数据库洞察](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Database-Insights-Database-Instance-Dashboard.html)，以了解与并行查询相关的等待事件。要详细了解与并行查询相关的等待事件，请浏览 [IPC:并行等待事件](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/apg-ipc-parallel.html)

从 PostgreSQL 版本 18 开始，您可以使用 [https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW) 和 [https://www.postgresql.org/docs/current/pgstatstatements.html](https://www.postgresql.org/docs/current/pgstatstatements.html) 中的新列来监控并行工作线程活动：
+ `parallel_workers_to_launch`：计划启动的并行工作线程数量
+ `parallel_workers_launched`：实际启动的并行工作线程数量

这些指标有助于识别计划的并行性与实际并行性之间的差异，这可能指示资源约束或配置问题。使用以下查询来监控并行执行：

对于数据库级别的并行工作线程指标：

```
SELECT datname, parallel_workers_to_launch, parallel_workers_launched
FROM pg_stat_database
WHERE datname = current_database();
```

对于查询级别的并行工作线程指标

```
SELECT query, parallel_workers_to_launch, parallel_workers_launched
FROM pg_stat_statements
ORDER BY parallel_workers_launched;
```

## 如何控制并行性
<a name="PostgreSQL.ParallelQueries.ControlParallelism"></a>

有多种方法可以控制查询并行性，每种方法均针对不同的场景和需求而设计。

要全局禁用自动并行性，请[修改参数组](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.Modifying.html)来设置：

```
max_parallel_workers_per_gather = 0;
```

对于用户特定的永久设置，ALTER ROLE 命令提供了一种设置参数的方法，这些参数将应用于特定用户的所有将来会话。

例如：

`ALTER ROLE username SET max_parallel_workers_per_gather = 4;` 可确保每次该用户连接到数据库时，其会话都将在需要时使用此并行工作线程设置。

可以使用 SET 命令来实现会话级控制，该命令可在当前数据库会话的持续时间内修改参数。当您需要在不影响其他用户或将来会话的情况下临时调整设置时，这特别有用。设置后，这些参数将保持有效，直到显式重置或会话结束。这些命令很简单：

```
SET max_parallel_workers_per_gather = 4;
-- Run your queries
RESET max_parallel_workers_per_gather;
```

为了实现更精细的控制，SET LOCAL 支持您修改单个事务的参数。当您需要调整事务中一组特定查询的设置时，这是理想之选，之后设置会自动恢复到以前的值。这种方法有助于防止对同一会话中的其它操作产生意外影响。

## 诊断并行查询行为
<a name="PostgreSQL.ParallelQueries.Diagnosing"></a>

使用 `EXPLAIN (ANALYZE, VERBOSE)` 来确认查询是否使用了并行执行：
+ 查找诸如 `Gather`、`Gather Merge` 或 `Parallel Seq Scan` 之类的节点。
+ 比较有并行性和无并行性的计划。

要暂时禁用并行性以进行比较：

```
SET max_parallel_workers_per_gather = 0;
EXPLAIN ANALYZE <your_query>;
RESET max_parallel_workers_per_gather;
```

# 在 RDS for PostgreSQL 数据库实例上使用参数
<a name="Appendix.PostgreSQL.CommonDBATasks.Parameters"></a>

在某些情况下，您可以在不指定自定义参数组的情况下创建 RDS for PostgreSQL 数据库实例。如果是这样，您的数据库实例将使用您选择的 PostgreSQL 版本的默认参数组创建。例如，假设您使用 PostgreSQL 13.3 创建 RDS for PostgreSQL 数据库实例。在这种情况下，数据库实例使用 PostgreSQL 13 版本 `default.postgres13` 的参数组中的值创建。

您还可以创建自己的自定义数据库参数组。如果要从其默认值修改 RDS for PostgreSQL 数据库实例的任何设置，则需要执行此操作。要了解如何操作，请参阅[Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

您可以通过几种不同的方法跟踪 RDS for PostgreSQL 数据库实例的设置。您可以使用 AWS 管理控制台、AWS CLI 或 Amazon RDS API。也可以从实例的 PostgreSQL `pg_settings` 表中查询值，如下所示。

```
SELECT name, setting, boot_val, reset_val, unit
 FROM pg_settings
 ORDER BY name;
```

要了解此查询所返回值的更多相关信息，请参阅 PostgreSQL 文档中的 [https://www.postgresql.org/docs/current/view-pg-settings.html](https://www.postgresql.org/docs/current/view-pg-settings.html)。

更改 RDS for PostgreSQL 数据库实例上的 `max_connections` 和 `shared_buffers` 的设置时要特别小心。例如，假设您修改 `max_connections` 或 `shared_buffers` 的设置，并且您使用的值对于实际工作负载来说太高。在这种情况下，RDS for PostgreSQL 数据库实例将无法启动。如果发生这种情况，您会在 `postgres.log` 中看到如下错误。

```
2018-09-18 21:13:15 UTC::@:[8097]:FATAL:  could not map anonymous shared memory: Cannot allocate memory
2018-09-18 21:13:15 UTC::@:[8097]:HINT:  This error usually means that PostgreSQL's request for a shared memory segment
exceeded available memory or swap space. To reduce the request size (currently 3514134274048 bytes), reduce 
PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.
```

但是，您无法更改默认 RDS for PostgreSQL 数据库参数组中包含的任何设置值。要更改任何参数的设置，请首先创建自定义数据库参数组。然后，更改该自定义组中的设置，并将自定义参数组应用到 RDS for PostgreSQL 数据库实例。要了解更多信息，请参阅[Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

RDS for PostgreSQL 中有两种类型的参数。
+ **静态参数**：静态参数需要在更改后重启 RDS for PostgreSQL 数据库实例，以便新值生效。
+ **动态参数**：动态参数在更改设置后不需要重启。

**注意**  
如果 RDS for PostgreSQL 数据库实例使用您自己的自定义数据库参数组，则可以更改正在运行的数据库实例上动态参数的值。您可以通过使用 AWS 管理控制台、AWS CLI 或 Amazon RDS API 实现此目的。

如果您有这样做的权限，则还可使用 `ALTER DATABASE`、`ALTER ROLE` 和 `SET` 命令更改参数值。

## RDS for PostgreSQL 数据库实例参数列表
<a name="Appendix.PostgreSQL.CommonDBATasks.Parameters.parameters-list"></a>

下表列出了 RDS for PostgreSQL 数据库实例中的一些（但并非全部）可用参数。要查看所有可用参数，请使用 AWS CLI 命令 [describe-db-parameters](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-parameters.html)。例如，要获取 RDS for PostgreSQL 版本 13 的原定设置参数组中所有可用参数的列表，请运行以下命令。

```
aws rds describe-db-parameters --db-parameter-group-name default.postgres13
```

您还可以使用控制台。从 Amazon RDS 菜单中选择 **Parameter groups**（参数组），然后从您的 AWS 区域中的可用参数组中选择参数组。


|  参数名称  |  应用类型  |  描述  | 
| --- | --- | --- | 
|  `application_name`  | 动态 | 设置要在统计数据和日志中报告的应用程序名称。 | 
|  `archive_command`  | 动态 | 设置将被调用以存档 WAL 文件的 Shell 命令。 | 
|  `array_nulls`  | 动态 | 允许在阵列中输入 NULL 元素。 | 
|  `authentication_timeout`  | 动态 | 设置允许完成客户端身份验证的最长时间。 | 
|  `autovacuum`  | 动态 | 启动 Autovacuum 子进程。 | 
|  `autovacuum_analyze_scale_factor`  | 动态 | analyze 之前插入、更新或删除元组的次数，以对于 reltuple 的占比计。 | 
|  `autovacuum_analyze_threshold`  | 动态 | analyze 之前插入、更新或删除元组的最小次数。 | 
|  `autovacuum_freeze_max_age`  | 静态 | 对表进行 Autovacuum 以防事务 ID 重叠的期限。 | 
|  `autovacuum_naptime`  | 动态 | 两次 Autovacuum 运行之间的睡眠时间。 | 
|  `autovacuum_max_workers`  | 静态 | 设置同时运行的 Autovacuum 工作者的最大数量。 | 
|  `autovacuum_vacuum_cost_delay`  | 动态 | Autovacuum 的真空开销延迟，以毫秒计。 | 
|  `autovacuum_vacuum_cost_limit`  | 动态 | Autovacuum 在小睡之前可用的真空开销量。 | 
|  `autovacuum_vacuum_scale_factor`  | 动态 | vacuum 之前更新或删除元组的次数，以对于 reltuple 的占比计。 | 
|  `autovacuum_vacuum_threshold`  | 动态 | vacuum 之前更新或删除元组的最小次数。 | 
|  `backslash_quote`  | 动态 | 设置字符串字面值中是否允许有反斜杠 (\$1)。 | 
|  `bgwriter_delay`  | 动态 | 后台写入实例在两轮之间的睡眠时间。 | 
|  `bgwriter_lru_maxpages`  | 动态 | 后台写入实例每轮要刷新的最大 LRU 页数。 | 
|  `bgwriter_lru_multiplier`  | 动态 | 每轮要释放的平均缓冲区用量的倍数。 | 
|  `bytea_output`  | 动态 | 设置字节的输出格式。 | 
|  `check_function_bodies`  | 动态 | 在 CREATE FUNCTION 期间检查函数体。 | 
|  `checkpoint_completion_target`  | 动态 | 在检查点期间刷新脏缓冲区所用的时间，以对于检查点间隔的占比计。 | 
|  `checkpoint_segments`  | 动态 | 设置日志段中自动预写日志 (WAL) 检查点之间的最大距离。 | 
|  `checkpoint_timeout`  | 动态 | 设置自动 WAL 检查点之间的最长时间。 | 
|  `checkpoint_warning`  | 动态 | 如果填充检查点段的频率高于此，则启用警告。 | 
|  `client_connection_check_interval`  | 动态 |  设置在运行查询时检查断开连接的时间间隔。 | 
|  `client_encoding`  | 动态 | 设置客户端的字符集编码。 | 
|  `client_min_messages`  | 动态 | 设置发送到客户端的消息级别。 | 
|  `commit_delay`  | 动态 | 设置事务提交与将 WAL 刷新到磁盘之间的延迟，以微秒计。 | 
|  `commit_siblings`  | 动态 | 设置执行 commit\$1delay 之前同时打开的最少事务数。 | 
|  `constraint_exclusion`  | 动态 | 使计划程序可使用约束优化查询。 | 
|  `cpu_index_tuple_cost`  | 动态 | 设置计划程序对索引扫描期间处理每个索引条目的开销的估算。 | 
|  `cpu_operator_cost`  | 动态 | 设置计划程序对处理每个运算符或函数调用的开销的估算。 | 
|  `cpu_tuple_cost`  | 动态 | 设置计划程序对处理每个元组 (行) 的开销的估算。 | 
|  `cursor_tuple_fraction`  | 动态 | 设置计划程序对光标将检索的行占比的估算。 | 
|  `datestyle`  | 动态 | 设置日期和时间值的显示格式。 | 
|  `deadlock_timeout`  | 动态 | 设置在检查死锁之前等待锁定的时间。 | 
|  `debug_pretty_print`  | 动态 | 缩进分析树和计划树的显示内容。 | 
|  `debug_print_parse`  | 动态 | 记录每个查询的分析树。 | 
|  `debug_print_plan`  | 动态 | 记录每个查询的执行计划。 | 
|  `debug_print_rewritten`  | 动态 | 记录每个查询重写的分析树。 | 
|  `default_statistics_target`  | 动态 | 设置默认统计数据目标。 | 
|  `default_tablespace`  | 动态 | 设置要从中创建表和索引的默认表空间。 | 
|  `default_transaction_deferrable`  | 动态 | 设置新事务的默认可延迟状态。 | 
|  `default_transaction_isolation`  | 动态 | 设置每个新事务的事务隔离级别。 | 
|  `default_transaction_read_only`  | 动态 | 设置新事务的默认只读状态。 | 
|  `default_with_oids`  | 动态 | 默认情况下，使用对象 ID (OID) 创建新表。 | 
|  `effective_cache_size`  | 动态 | 设置计划程序对于磁盘缓存大小的假设。 | 
|  `effective_io_concurrency`  | 动态 | 磁盘子系统可有效处理的并行请求数。 | 
|  `enable_bitmapscan`  | 动态 | 使计划程序可使用位图扫描计划。 | 
|  `enable_hashagg`  | 动态 | 使计划程序可使用哈希聚合计划。 | 
|  `enable_hashjoin`  | 动态 | 使计划程序可使用哈希联接计划。 | 
|  `enable_indexscan`  | 动态 | 使计划程序可使用索引扫描计划。 | 
|  `enable_material`  | 动态 | 使计划程序可使用具体化。 | 
|  `enable_mergejoin`  | 动态 | 使计划程序可使用合并联接计划。 | 
|  `enable_nestloop`  | 动态 | 使计划程序可使用嵌套循环的联接计划。 | 
|  `enable_seqscan`  | 动态 | 使计划程序可使用顺序扫描计划。 | 
|  `enable_sort`  | 动态 | 使计划程序可使用显式排序步骤。 | 
|  `enable_tidscan`  | 动态 | 使计划程序可使用 TID 扫描计划。 | 
|  `escape_string_warning`  | 动态 | 警告在普通字符串字面值中有反斜杠 (\$1) 转义符。 | 
|  `extra_float_digits`  | 动态 | 设置所显示的浮点值位数。 | 
|  `from_collapse_limit`  | 动态 | 设置超出其即不折叠子查询的 FROM 列表大小。 | 
|  `fsync`  | 动态 | 强制将更新同步到磁盘。 | 
|  `full_page_writes`  | 动态 | 在检查点后首次修改时向 WAL 写入整页。 | 
|  `geqo`  | 动态 | 启用基因查询优化。 | 
|  `geqo_effort`  | 动态 | GEQO：用于设置其他 GEQO 参数默认值的工作负载。 | 
|  `geqo_generations`  | 动态 | GEQO：算法的迭代次数。 | 
|  `geqo_pool_size`  | 动态 | GEQO：群体中的个体数。 | 
|  `geqo_seed`  | 动态 | GEQO：随机路径选择的种子。 | 
|  `geqo_selection_bias`  | 动态 | GEQO：群体中的选择性压力。 | 
|  `geqo_threshold`  | 动态 | 设置超出其即使用 GEQO 的 FROM 项阈值。 | 
|  `gin_fuzzy_search_limit`  | 动态 | 通过允许由 GIN 进行的精确搜索得出的最大结果数。 | 
|  `hot_standby_feedback`  | 动态 | 确定热备用将反馈消息发送到主备用还是上游备用。 | 
|  `intervalstyle`  | 动态 | 设置间隔值的显示格式。 | 
|  `join_collapse_limit`  | 动态 | 设置超出其即不平展 JOIN 结构的 FROM 列表大小。 | 
|  `lc_messages`  | 动态 | 设置显示消息的语言。 | 
|  `lc_monetary`  | 动态 | 设置用于使货币金额格式化的区域设置。 | 
|  `lc_numeric`  | 动态 | 设置用于使数字格式化的区域设置。 | 
|  `lc_time`  | 动态 | 设置用于使日期和时间值格式化的区域设置。 | 
|  `log_autovacuum_min_duration`  | 动态 | 设置如超出即记录 Autovacuum 操作的最短运行时间。 | 
|  `log_checkpoints`  | 动态 | 记录每个检查点。 | 
|  `log_connections`  | 动态 | 记录每个成功的连接。 | 
|  `log_disconnections`  | 动态 | 记录会话结束，包括持续时间。 | 
|  `log_duration`  | 动态 | 记录每个完成的 SQL 语句的持续时间。 | 
|  `log_error_verbosity`  | 动态 | 设置记录消息的详细程度。 | 
|  `log_executor_stats`  | 动态 | 向服务器日志写入执行者性能统计数据。 | 
|  `log_filename`  | 动态 | 设置日志文件的文件名模式。 | 
|  `log_file_mode`  | 动态 | 设置日志文件的文件权限。默认值为 0644。 | 
|  `log_hostname`  | 动态 | 在连接日志中记录主机名。从 PostgreSQL 12 及更高版本开始，原定设置情况下，此参数为“off”。开启后，连接使用 DNS 反向查找来获取捕获到连接日志的主机名。如果您启用此参数，则应监控它对建立连接所花费时间的影响。 | 
|  `log_line_prefix `  | 动态 | 控制每个日志行前缀的信息。 | 
|  `log_lock_waits`  | 动态 | 记录长锁定等待次数。 | 
|  `log_min_duration_statement`  | 动态 | 设置如超出即记录语句的最短运行时间。 | 
|  `log_min_error_statement`  | 动态 | 导致记录所有产生此水平或此水平之上错误的语句。 | 
|  `log_min_messages`  | 动态 | 设置记录的消息级别。 | 
|  `log_parser_stats`  | 动态 | 向服务器日志写入分析器性能统计数据。 | 
|  `log_planner_stats`  | 动态 | 向服务器日志写入计划程序性能统计数据。 | 
|  `log_rotation_age`  | 动态 | 将在 N 分钟后进行日志文件自动轮换。 | 
|  `log_rotation_size`  | 动态 | 将在 N KB 后进行日志文件自动轮换。 | 
|  `log_statement`  | 动态 | 设置所记录的语句类型。 | 
|  `log_statement_stats`  | 动态 | 向服务器日志写入累计性能统计数据。 | 
|  `log_temp_files`  | 动态 | 记录对大于此 KB 数的临时文件的使用情况。 | 
|  `log_timezone`  | 动态 | 设置要在日志消息中使用的时区。 | 
|  `log_truncate_on_rotation`  | 动态 | 在日志轮换期间截断同名的现有日志文件。 | 
|  `logging_collector`  | 静态 | 启动子进程将 stderr 输出和/或 csvlog 捕获到日志文件中。 | 
|  `maintenance_work_mem`  | 动态 | 设置要用于维护操作的最大内存。 | 
|  `max_connections`  | 静态 | 设置最大并行连接数。 | 
|  `max_files_per_process`  | 静态 | 设置同时为每个服务器进程打开的最大文件数。 | 
|  `max_locks_per_transaction`  | 静态 | 设置每个事务的最大锁定数。 | 
|  `max_pred_locks_per_transaction`  | 静态 | 设置每个事务的最大谓词锁定数。 | 
|  `max_prepared_transactions`  | 静态 | 设置同时准备的最大事务数。 | 
|  `max_stack_depth`  | 动态 | 设置最大堆栈长度，以 KB 计。 | 
|  `max_standby_archive_delay`  | 动态 | 设置在有热备用服务器处理已存档的 WAL 数据时取消查询之前的最大延迟。 | 
|  `max_standby_streaming_delay`  | 动态 | 设置在有热备用服务器处理流式 WAL 数据时取消查询之前的最大延迟。 | 
| max\$1wal\$1size | 动态 | 设置触发检查点的 WAL 大小（MB）。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Parameters.html) 对 Amazon RDS for PostgreSQL 数据库实例使用以下命令可查看其当前值： <pre>SHOW max_wal_size;</pre>  | 
| min\$1wal\$1size | 动态 | 设置将 WAL 缩小到的最小大小。对于 PostgreSQL 9.6 版及更早版本，min\$1wal\$1size 以 16 MB 为单位。对于 PostgreSQL 10 版及更高版本，min\$1wal\$1size 以 1 MB 为单位。 | 
|  `quote_all_identifiers`  | 动态 | 在生成 SQL 片段时向所有标识符添加引号 (")。 | 
|  `random_page_cost`  | 动态 | 设置计划程序对非连续提取磁盘页面的开销的估算。除非开启查询计划管理（QPM），否则此参数没有值。开启 QPM 时，此参数的默认值为 4。 | 
| rds.adaptive\$1autovacuum | 动态 | 在超过事务 ID 阈值时自动优化 Autovacuum 参数。 | 
| rds.force\$1ssl | 动态 | 要求使用 SSL 连接。对于 RDS for PostgreSQL 版本 15，默认值设为 1（开启）。所有其他 RDS for PostgreSQL 主要版本 14 及更早版本的默认值都设为 0（关闭）。 | 
|  `rds.local_volume_spill_enabled`  | 静态 | 允许将逻辑溢出文件写入本地卷。 | 
|  `rds.log_retention_period`  | 动态 | 设置日志保留，以便 Amazon RDS 删除超过 n 分钟的 PostgreSQL 日志。 | 
| rds.rds\$1superuser\$1reserved\$1connections | 静态 | 设置为 rds\$1superuser 保留的连接插槽数。此参数仅在版本 15 及更高版本中提供。有关更多信息，请参阅 PostgreSQL 文档 [reserved\$1connections](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-RESERVED-CONNECTIONS)。 | 
| `rds.replica_identity_full` | 动态 | 当您将此参数设置为 `on` 时，它会将所有数据库表的副本标识设置覆盖为 `FULL`。这意味着，无论您的 `REPLICA IDENTITY FULL` 设置如何，所有列值都将写入预写日志（WAL）。  由于额外的 WAL 日志记录，开启此参数可能会增加数据库实例 IOPS。   | 
| rds.restrict\$1password\$1commands | 静态 | 将可以管理密码的用户限制为具有 rds\$1password 角色的用户。将此参数设置为 1 可启用密码限制。默认值为 0。 | 
|  `search_path`  | 动态 | 设置针对非架构限定名称的架构搜索顺序。 | 
|  `seq_page_cost`  | 动态 | 设置计划程序对连续提取磁盘页面的开销的估算。 | 
|  `session_replication_role`  | 动态 | 设置触发器和重写规则的会话行为。 | 
|  `shared_buffers`  | 静态 | 设置服务器使用的共享内存缓冲区数。 | 
|  `shared_preload_libraries `  | 静态 | 列出要预加载到 RDS for PostgreSQL 数据库实例中的共享库。支持的值包括 auto\$1explain、orafce、pgaudit、pglogical、pg\$1bigm、pg\$1cron、pg\$1hint\$1plan、pg\$1prewarm、pg\$1similarity、pg\$1stat\$1statements、pg\$1tle、pg\$1transport、plprofiler 和 plrust。 | 
|  `ssl`  | 动态 | 启用 SSL 连接。 | 
|  `sql_inheritance`  | 动态 | 导致在各种命令中默认加入子表。 | 
|  `ssl_renegotiation_limit`  | 动态 | 设置在重新协商加密密钥之前发送和接收的流量。 | 
|  `standard_conforming_strings`  | 动态 | 导致 ... 字符串按字面处理反斜杠。 | 
|  `statement_timeout`  | 动态 | 设置允许任何语句的最长持续时间。 | 
|  `synchronize_seqscans`  | 动态 | 启用同步顺序扫描。 | 
|  `synchronous_commit`  | 动态 | 设置当前事务同步级别。 | 
|  `tcp_keepalives_count`  | 动态 | 重新传输 TCP 保持连接信号的最大次数。 | 
|  `tcp_keepalives_idle`  | 动态 | 发出两次 TCP 保持连接信号之间的时间。 | 
|  `tcp_keepalives_interval`  | 动态 | 两次 TCP 保持连接信号重新传输之间的时间。 | 
|  `temp_buffers`  | 动态 | 设置每个会话使用的临时缓冲区的最大数量。 | 
| temp\$1file\$1limit | 动态 | 设置临时文件可以达到的最大大小，以 KB 为单位。 | 
|  `temp_tablespaces`  | 动态 | 选择用于临时表和排序文件的表空间。 | 
|  `timezone`  | 动态 | 设置用于显示和解译时间戳的时区。 互联网编号分配机构（IANA）每年多次在 [https://www.iana.org/time-zones](https://www.iana.org/time-zones) 上发布新的时区。每当 RDS 发布 PostgreSQL 的新次要维护版本时，RDS 都会附带发布时的最新时区数据。当您使用最新的 RDS for PostgreSQL 版本时，您会获得来自 RDS 的最新时区数据。为确保您的数据库实例具有最新的时区数据，我们建议升级到更高的数据库引擎版本。您无法手动修改 PostgreSQL 数据库实例中的时区表。RDS 不会修改或重置正在运行的数据库实例的时区数据。只有在执行数据库引擎版本升级时，才会安装新的时区数据。 | 
|  `track_activities`  | 动态 | 收集有关运行命令的信息。 | 
|  `track_activity_query_size`  | 静态 | 设置为 pg\$1stat\$1activity.current\$1query 保留的大小，以字节计。 | 
|  `track_counts`  | 动态 | 收集有关数据库活动的统计数据。 | 
|  `track_functions`  | 动态 | 收集有关数据库活动的函数级别统计数据。 | 
|  `track_io_timing`  | 动态 | 收集有关数据库活动的时序统计数据。 | 
|  `transaction_deferrable`  | 动态 | 指示是否将某个只读可序列化事务推迟到启动它不会发生序列化失败时。 | 
|  `transaction_isolation`  | 动态 | 设置当前事务隔离级别。 | 
|  `transaction_read_only`  | 动态 | 设置当前事务只读状态。 | 
|  `transform_null_equals`  | 动态 | 将 expr=NULL 视为 expr IS NULL。 | 
|  `update_process_title`  | 动态 | 更新进程标题以显示活动的 SQL 命令。 | 
|  `vacuum_cost_delay`  | 动态 | 真空开销延迟，以毫秒计。 | 
|  `vacuum_cost_limit`  | 动态 | 小睡之前可用的真空开销量。 | 
|  `vacuum_cost_page_dirty`  | 动态 | 由真空弄脏的页面的真空开销。 | 
|  `vacuum_cost_page_hit`  | 动态 | 在缓冲区缓存中找到的页面的真空开销。 | 
|  `vacuum_cost_page_miss`  | 动态 | 在缓冲区缓存中未找到的页面的真空开销。 | 
|  `vacuum_defer_cleanup_age`  | 动态 | 真空和热清理应推迟的事务数 (如果有)。 | 
|  `vacuum_freeze_min_age`  | 动态 | 真空应冻结表格行的最短期限。 | 
|  `vacuum_freeze_table_age`  | 动态 | 真空应扫描整个表以冻结元组的期限。 | 
|  `wal_buffers`  | 静态 | 设置 WAL 的共享内存中的磁盘页面缓冲区数。 | 
|  `wal_writer_delay`  | 动态 | 两次 WAL 刷新之间的 WAL 写入实例睡眠时间。 | 
|  `work_mem`  | 动态 | 设置要用于查询工作区的最大内存。 | 
|  `xmlbinary`  | 动态 | 设置如何将二进制值编码到 XML 中。 | 
|  `xmloption`  | 动态 | 设置要将隐式分析和序列化操作中的 XML 数据视为文档还是内容片段。 | 

Amazon RDS 对所有参数均使用默认的 PostgreSQL 单位。下表显示每个参数的 PostgreSQL 原定设置单位。


|  参数名称  |  单位  | 
| --- | --- | 
| `archive_timeout` | s | 
| `authentication_timeout` | s | 
| `autovacuum_naptime` | s | 
| `autovacuum_vacuum_cost_delay` | ms | 
| `bgwriter_delay` | ms | 
| `checkpoint_timeout` | s | 
| `checkpoint_warning` | s | 
| `deadlock_timeout` | ms | 
| `effective_cache_size` | 8 KB | 
| `lock_timeout` | ms | 
| `log_autovacuum_min_duration` | ms | 
| `log_min_duration_statement` | ms | 
| `log_rotation_age` | 分钟 | 
| `log_rotation_size` | KB | 
| `log_temp_files` | KB | 
| `maintenance_work_mem` | KB | 
| `max_stack_depth` | KB | 
| `max_standby_archive_delay` | ms | 
| `max_standby_streaming_delay` | ms | 
| `post_auth_delay` | s | 
| `pre_auth_delay` | s | 
| `segment_size` | 8 KB | 
| `shared_buffers` | 8 KB | 
| `statement_timeout` | ms | 
| `ssl_renegotiation_limit` | KB | 
| `tcp_keepalives_idle` | s | 
| `tcp_keepalives_interval` | s | 
| `temp_file_limit` | KB | 
| `work_mem` | KB | 
| `temp_buffers` | 8 KB | 
| `vacuum_cost_delay` | ms | 
| `wal_buffers` | 8 KB | 
| `wal_receiver_timeout` | ms | 
| `wal_segment_size` | B | 
| `wal_sender_timeout` | ms | 
| `wal_writer_delay` | ms | 
| `wal_receiver_status_interval` | s | 

# 使用 RDS for PostgreSQL 的等待事件进行优化
<a name="PostgreSQL.Tuning"></a>

等待事件是 RDS for PostgreSQL 的重要优化工具。当您能查明会话为什么在等待资源以及会话在做什么时，您就能更好地减少瓶颈。您可以使用本节中的信息来查找可能的原因和纠正措施。本节还讨论基本的 PostgreSQL 优化概念。

本节中的等待事件特定于 RDS for PostgreSQL。

**Topics**
+ [RDS for PostgreSQL 优化的基本概念](PostgreSQL.Tuning.concepts.md)
+ [RDS for PostgreSQL 等待事件](PostgreSQL.Tuning.concepts.summary.md)
+ [Client:ClientRead](wait-event.clientread.md)
+ [Client:ClientWrite](wait-event.clientwrite.md)
+ [CPU](wait-event.cpu.md)
+ [IO:BufFileRead 和 IO:BufFileWrite](wait-event.iobuffile.md)
+ [IO:DataFileRead](wait-event.iodatafileread.md)
+ [IO:WALWrite](wait-event.iowalwrite.md)
+ [IPC:并行等待事件](rpg-ipc-parallel.md)
+ [IPC:ProcArrayGroupUpdate](apg-rpg-ipcprocarraygroup.md)
+ [Lock:advisory](wait-event.lockadvisory.md)
+ [Lock:extend](wait-event.lockextend.md)
+ [Lock:Relation](wait-event.lockrelation.md)
+ [Lock:transactionid](wait-event.locktransactionid.md)
+ [Lock:tuple](wait-event.locktuple.md)
+ [LWLock:BufferMapping (LWLock:buffer\$1mapping)](wait-event.lwl-buffer-mapping.md)
+ [LWLock:BufferIO (IPC:BufferIO)](wait-event.lwlockbufferio.md)
+ [LWLock:buffer\$1content (BufferContent)](wait-event.lwlockbuffercontent.md)
+ [LWLock:lock\$1manager (LWLock:lockmanager)](wait-event.lw-lock-manager.md)
+ [LWLock:pg\$1stat\$1statements](apg-rpg-lwlockpgstat.md)
+ [LWLock:SubtransSLRU (LWLock:SubtransControlLock)](wait-event.lwlocksubtransslru.md)
+ [Timeout:PgSleep](wait-event.timeoutpgsleep.md)
+ [Timeout:VacuumDelay](wait-event.timeoutvacuumdelay.md)

# RDS for PostgreSQL 优化的基本概念
<a name="PostgreSQL.Tuning.concepts"></a>

在优化 RDS for PostgreSQL 数据库之前，请务必了解什么是等待事件以及它们发生的原因。还可以查看 RDS for PostgreSQL 的基本内存和磁盘架构。有关有用的架构图，请参阅 [PostgreSQL](https://en.wikibooks.org/wiki/PostgreSQL/Architecture) wikibook。

**Topics**
+ [RDS for PostgreSQL 等待事件](PostgreSQL.Tuning.concepts.waits.md)
+ [RDS for PostgreSQL 内存](PostgreSQL.Tuning.concepts.memory.md)
+ [RDS for PostgreSQL 进程](PostgreSQL.Tuning.concepts.processes.md)

# RDS for PostgreSQL 等待事件
<a name="PostgreSQL.Tuning.concepts.waits"></a>

*等待事件*表示会话正在等待资源。例如，当 RDS for PostgreSQL 等待从客户端接收数据时，会发生等待事件 `Client:ClientRead`。会话通常会等待如下资源。
+ 例如，当会话试图修改缓冲区时，对缓冲区的单线程访问
+ 当前被另一个会话锁定的行
+ 已读取一个数据文件
+ 已写入一个日志文件

例如，为了满足查询，会话可能会执行完整的表扫描。如果数据尚未在内存中，会话将等待磁盘输入/输出完成。当缓冲区读取到内存时，会话可能需要等待，因为其他会话正在访问相同的缓冲区。数据库使用预定义的等待事件记录等待。这些事件按类别进行分组。

等待事件本身并不表示存在性能问题。例如，如果请求的数据不在内存中，则必须从磁盘读取数据。如果一个会话锁定行以进行更新，则另一个会话将等待解锁该行，以便它可以更新该行。提交需要等待对日志文件的写入完成。等待是数据库正常运行不可或缺的组成部分。

另一方面，大量的等待事件通常表示存在性能问题。在这种情况下，您可以使用等待事件数据来确定会话将时间花费在哪里。例如，如果通常在几分钟内运行的报告现在运行需要几个小时，则可以确定对总等待时间贡献最大的等待事件。如果您能确定顶级等待事件的原因，您有时就可以进行更改来提高性能。例如，如果您的会话正在等待已被另一个会话锁定的行，则可以结束锁定会话。

# RDS for PostgreSQL 内存
<a name="PostgreSQL.Tuning.concepts.memory"></a>

RDS for PostgreSQL 内存分为共享内存和本地内存。

**Topics**
+ [RDS for PostgreSQL 中的共享内存](#PostgreSQL.Tuning.concepts.shared)
+ [RDS for PostgreSQL 中的本地内存](#PostgreSQL.Tuning.concepts.local)

## RDS for PostgreSQL 中的共享内存
<a name="PostgreSQL.Tuning.concepts.shared"></a>

RDS for PostgreSQL 会在实例启动时分配共享内存。共享内存分为多个子区域。以下各节提供了最重要子区域的说明。

**Topics**
+ [共享缓冲区](#PostgreSQL.Tuning.concepts.buffer-pool)
+ [预写日志 (WAL) 缓冲区](#PostgreSQL.Tuning.concepts.WAL)

### 共享缓冲区
<a name="PostgreSQL.Tuning.concepts.buffer-pool"></a>

*共享缓冲池*是一个 RDS for PostgreSQL 内存区域，它包含应用程序连接现在正在使用或过去使用的所有页面。*分页*是磁盘数据块的内存版本。共享缓冲池缓存从磁盘读取的数据块。该缓冲池减少了从磁盘重新读取数据的需求，从而提高了数据库的运行效率。

每个表和索引都存储为固定大小的页面数组。每个数据块包含多个元组，它们与行相对应。元组可以存储在任何页面中。

共享缓冲池的内存有限。如果新请求需要一个不在内存中的页面，并且没有更多的内存，RDS for PostgreSQL 会移除一个较少使用的页面来容纳请求。移出策略通过时钟扫描算法来实现。

`shared_buffers` 参数确定服务器用于缓存数据的内存量。根据数据库实例的可用内存，默认值设置为 `{DBInstanceClassMemory/32768}` 字节。

### 预写日志 (WAL) 缓冲区
<a name="PostgreSQL.Tuning.concepts.WAL"></a>

*预写日志（WAL）缓冲区*保存 RDS for PostgreSQL 稍后写入持久存储的事务数据。使用 WAL 机制，RDS for PostgreSQL 可以执行以下操作：
+ 发生故障后恢复数据
+ 通过避免频繁写入磁盘来减少磁盘输入/输出

当客户端更改数据时，RDS for PostgreSQL 会将更改写入 WAL 缓冲区。当客户发出 `COMMIT`，WAL 写入器进程将事务数据写入 WAL 文件。

`wal_level` 参数决定向 WAL 写入的信息量，可能的值包括 `minimal`、`replica` 和 `logical` 等。

## RDS for PostgreSQL 中的本地内存
<a name="PostgreSQL.Tuning.concepts.local"></a>

每个后端进程都会为查询处理分配本地内存。

**Topics**
+ [工作内存区域](#PostgreSQL.Tuning.concepts.local.work_mem)
+ [维护工作内存区域](#PostgreSQL.Tuning.concepts.local.maintenance_work_mem)
+ [临时缓冲区](#PostgreSQL.Tuning.concepts.temp)

### 工作内存区域
<a name="PostgreSQL.Tuning.concepts.local.work_mem"></a>

*工作内存区域*保存执行排序和哈希的查询的临时数据。例如，包含 `ORDER BY` 子句的查询执行排序。查询在哈希联接和聚合中使用哈希表。

`work_mem` 参数表示在写入临时磁盘文件之前，内部排序操作和哈希表要使用的内存量，以 MB 为单位。原定设置值为 4MB。可以同时运行多个会话，且每个会话可以并行运行维护操作。出于这个原因，使用的总工作内存可以是 `work_mem` 设置的倍数。

### 维护工作内存区域
<a name="PostgreSQL.Tuning.concepts.local.maintenance_work_mem"></a>

*维护工作内存区域*缓存数据以进行维护操作。这些操作包括 vacuum 操作、创建索引和添加外键。

`maintenance_work_mem` 参数指定维护操作要使用的最大内存量，以 MB 为单位。原定设置值为 64MB。一个数据库会话一次只能运行一个维护操作。

### 临时缓冲区
<a name="PostgreSQL.Tuning.concepts.temp"></a>

*临时缓冲区*缓存每个数据库会话的临时表。

每个会话都根据需要分配临时缓冲区，但不超过您指定的限制。当会话结束时，服务器将清除缓冲区。

`temp_buffers` 参数设置每个会话使用的临时缓冲区的最大数量，以 MB 为单位。默认值为 8 MB。在会话中首次使用临时表之前，您可以更改 `temp_buffers` 值。

# RDS for PostgreSQL 进程
<a name="PostgreSQL.Tuning.concepts.processes"></a>

RDS for PostgreSQL 使用多个进程。

**Topics**
+ [邮件管理员过程](#PostgreSQL.Tuning.concepts.postmaster)
+ [后端进程](#PostgreSQL.Tuning.concepts.backend)
+ [后台进程](#PostgreSQL.Tuning.concepts.vacuum)

## 邮件管理员过程
<a name="PostgreSQL.Tuning.concepts.postmaster"></a>

*邮件管理员进程*是启动 RDS for PostgreSQL 时开始的第一个进程。邮件管理员过程负有以下主要责任：
+ 分流并监控后台进程
+ 接收来自客户端进程的身份验证请求，并在允许数据库为请求提供服务之前对这些请求进行身份验证

## 后端进程
<a name="PostgreSQL.Tuning.concepts.backend"></a>

如果邮件管理员对客户请求进行身份验证，邮件管理员会分流一个新的后端进程，也称为 postgres 进程。一个客户端进程只连接到一个后端进程。客户端进程和后端进程直接通信，而无需邮件管理员过程的干预。

## 后台进程
<a name="PostgreSQL.Tuning.concepts.vacuum"></a>

邮件管理员过程会分流执行不同后端任务的几个进程。其中一些更重要的事项包括：
+ WAL 写入器

  RDS for PostgreSQL 会将 WAL（预写日志记录）缓冲区中的数据写入日志文件。预写日志记录的原则是，在数据库将描述这些更改的日志记录写入磁盘之后，数据库才能将更改写入数据文件。WAL 机制减少了磁盘 I/O，并允许 RDS for PostgreSQL 在出现故障后使用日志恢复数据库。
+ 后台写入器

  此进程会定期将内存缓冲区中的脏（已修改）分页写入数据文件。当后端进程在内存中修改分页时，分页会变脏。
+ Autovacuum 守护进程

  守护进程由以下各项组成：
  + Autovacuum 启动程序
  + Autovacuum 工件进程

  当 Autovacuum 开启时，它会检查包含大量插入的、更新的或删除的元组的表。守护进程要承担以下责任：
  + 恢复或重复使用更新或删除的行占用的磁盘空间
  + 更新计划人员使用的统计数据
  + 防止因事务 ID 重叠而导致旧数据丢失

  Autovacuum 功能自动执行 `VACUUM` 和 `ANALYZE` 命令。`VACUUM` 具有以下变体：标准和完整版。标准 vacuum 与其他数据库操作并行运行。`VACUUM FULL` 需要对您工作所在的表具有专有锁定。因此，它不能与访问同一表的操作并行运行。`VACUUM` 创建了大量的输入/输出流量，这可能会导致其他活动会话的性能不佳。

# RDS for PostgreSQL 等待事件
<a name="PostgreSQL.Tuning.concepts.summary"></a>

下表列出了 RDS for PostgreSQL 最常指示性能问题的等待事件，并总结了最常见的原因和纠正措施。


| 等待事件 | 定义 | 
| --- | --- | 
|  [Client:ClientRead](wait-event.clientread.md)  |  当 RDS for PostgreSQL 等待从客户端接收数据时，会发生此事件。  | 
|  [Client:ClientWrite](wait-event.clientwrite.md)  |  当 RDS for PostgreSQL 等待将数据写入客户端时，会发生此事件。  | 
|  [CPU](wait-event.cpu.md)  | 当线程在 CPU 中处于活动状态或正在等待 CPU 时，会发生此事件。 | 
|  [IO:BufFileRead 和 IO:BufFileWrite](wait-event.iobuffile.md)  |  这些事件发生在 RDS for PostgreSQL 创建临时文件时。  | 
|  [IO:DataFileRead](wait-event.iodatafileread.md)  |  当由于分页在共享内存中不可用，连接等待后端进程从存储中读取所需分页时，会发生此事件。  | 
| [IO:WALWrite](wait-event.iowalwrite.md)  | 当 RDS for PostgreSQL 正在等待将预写日志（WAL）缓冲区写入 WAL 文件时，会发生此事件。  | 
|  [Lock:advisory](wait-event.lockadvisory.md)  |  当 PostgreSQL 应用程序使用锁定来协调多个会话之间的活动时，会发生此事件。  | 
|  [Lock:extend](wait-event.lockextend.md) |  当后端进程正在等待锁定关系以对其进行扩展，而另一个进程出于同样目的锁定该关系时，会发生此事件。  | 
|  [Lock:Relation](wait-event.lockrelation.md)  |  当查询等待获取当前被另一个事务锁定的表或视图上的锁定时，会发生此事件。  | 
|  [Lock:transactionid](wait-event.locktransactionid.md)  | 当事务正在等待行级锁定时，会发生此事件。 | 
|  [Lock:tuple](wait-event.locktuple.md)  |  在后端进程等待获取元组锁定时，会发生此事件。  | 
|  [LWLock:BufferMapping (LWLock:buffer\$1mapping)](wait-event.lwl-buffer-mapping.md)  |  当会话正在等待将数据块与共享缓冲池中的缓冲区关联起来时，会发生此事件。  | 
|  [LWLock:BufferIO (IPC:BufferIO)](wait-event.lwlockbufferio.md)  |  当 RDS for PostgreSQL 正在等待其他进程在同时尝试访问页面时完成输入/输出（I/O）操作时，会发生此事件。  | 
|  [LWLock:buffer\$1content (BufferContent)](wait-event.lwlockbuffercontent.md)  |  当某个会话等待读取或写入内存中的某个数据页面，而另一个会话正锁定该页面以进行写入时，会发生此事件。  | 
|  [LWLock:lock\$1manager (LWLock:lockmanager)](wait-event.lw-lock-manager.md)  | 当 RDS for PostgreSQL 引擎维护共享锁的内存区域以便在无法使用快速路径锁时分配、检查和取消分配锁时，会发生此事件。 | 
|  [LWLock:SubtransSLRU (LWLock:SubtransControlLock)](wait-event.lwlocksubtransslru.md)  |  当进程正在等待访问子事务的最近使用最少（SLRU）的简单缓存时，发生此事件。  | 
|  [Timeout:PgSleep](wait-event.timeoutpgsleep.md)  |  当服务器进程调用 `pg_sleep` 函数并且正在等待睡眠超时过期时，会发生此事件。  | 
|  [Timeout:VacuumDelay](wait-event.timeoutvacuumdelay.md)  | 此事件表明 vacuum 进程正处于休眠状态，因为已达到估计的成本上限。 | 

# Client:ClientRead
<a name="wait-event.clientread"></a>

当 RDS for PostgreSQL 等待从客户端接收数据时，会发生 `Client:ClientRead` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.clientread.context.supported)
+ [上下文](#wait-event.clientread.context)
+ [等待次数增加的可能原因](#wait-event.clientread.causes)
+ [操作](#wait-event.clientread.actions)

## 支持的引擎版本
<a name="wait-event.clientread.context.supported"></a>

RDS for PostgreSQL 版本 10 及更高版本支持此等待事件信息。

## 上下文
<a name="wait-event.clientread.context"></a>

RDS for PostgreSQL 数据库实例正在等待从客户端接收数据。RDS for PostgreSQL 数据库实例必须先从客户端接收数据，然后才能向客户端发送更多数据。实例在从客户端接收数据之前等待的时间为 `Client:ClientRead` 事件。

## 等待次数增加的可能原因
<a name="wait-event.clientread.causes"></a>

`Client:ClientRead` 显示在主要等待中的常见原因包括以下各项：

**网络延迟增加**  
RDS for PostgreSQL 数据库实例和客户端之间的网络延迟可能会增加。较高的网络延迟会增加数据库实例从客户端接收数据所需的时间。

**客户端负载增加**  
客户端上可能存在 CPU 压力或网络饱和。客户端负载的增加可能会延迟从客户端向 RDS for PostgreSQL 数据库实例传输数据的时间。

**过多的网络往返次数**  
RDS for PostgreSQL 数据库实例和客户端之间的大量网络往返可能会延迟将数据从客户端传输到 RDS for PostgreSQL 数据库实例的过程。

**大型复制操作**  
在复制操作期间，数据将从客户端的文件系统传输到 RDS for PostgreSQL 数据库实例。向数据库实例发送大量数据可能会延迟从客户端向数据库实例传输数据的时间。

**空闲客户端连接**  
当客户端以 `idle in transaction` 状态连接到 RDS for PostgreSQL 数据库实例时，数据库实例可能会等待客户端发送更多数据或发出命令。在这种状态下的连接可能会导致 `Client:ClientRead` 事件增加。

**用于连接池的 PgBouncer**  
PgBouncer 有一个名为 `pkt_buf` 的低级网络配置设置，预设情况下设置为 4096。如果工作负载通过 PgBouncer 发送大于 4096 字节的查询数据包，我们建议增加 `pkt_buf` 设置为 8192。如果新设置没有减少 `Client:ClientRead` 事件的数量，我们建议增加 `pkt_buf` 设置为较大的值，例如 16384 或 32768。如果查询文本很大，则较大的设置可能会特别有用。

## 操作
<a name="wait-event.clientread.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [将客户端放置在与实例相同的可用区和 VPC 子网中](#wait-event.clientread.actions.az-vpc-subnet)
+ [扩展客户端](#wait-event.clientread.actions.scale-client)
+ [使用当前一代实例](#wait-event.clientread.actions.db-instance-class)
+ [提高网络带宽](#wait-event.clientread.actions.increase-network-bandwidth)
+ [监控网络性能的最大值](#wait-event.clientread.actions.monitor-network-performance)
+ [监控处于“空闲事务”状态的事务](#wait-event.clientread.actions.check-idle-in-transaction)

### 将客户端放置在与实例相同的可用区和 VPC 子网中
<a name="wait-event.clientread.actions.az-vpc-subnet"></a>

为了减少网络延迟并提高网络吞吐量，请将客户端放在与 RDS for PostgreSQL 数据库实例相同的可用区和虚拟私有云（VPC）子网中。确保客户端在地理位置上尽可能靠近数据库实例。

### 扩展客户端
<a name="wait-event.clientread.actions.scale-client"></a>

使用 Amazon CloudWatch 或其他主机指标，确定您的客户端当前是受 CPU 或网络带宽的限制，还是受此两者的限制。如果客户端受到限制，请相应地扩展您的客户端。

### 使用当前一代实例
<a name="wait-event.clientread.actions.db-instance-class"></a>

在某些情况下，您可能没有使用支持巨型帧的数据库实例类。如果您在 Amazon EC2 上运行应用程序，请考虑为客户端使用当前一代实例。另外，在客户端操作系统上配置最大传输单位 (MTU)。这种技术可能会减少网络往返次数并提高网络吞吐量。有关更多信息，请参阅《Amazon EC2 用户指南》**中的[巨型帧（9001 MTU）](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances)。

有关数据库实例类的信息，请参阅 [数据库实例类](Concepts.DBInstanceClass.md)。要确定等同于 Amazon EC2 实例类型的数据库实例类，请将 `db.` 放置在 Amazon EC2 实例类型名称之前。例如，`r5.8xlarge` Amazon EC2 实例等同于 `db.r5.8xlarge` 数据库实例类。

### 提高网络带宽
<a name="wait-event.clientread.actions.increase-network-bandwidth"></a>

使用 `NetworkReceiveThroughput` 和 `NetworkTransmitThroughput` Amazon CloudWatch 指标监控数据库实例上的传入和传出网络流量。这些指标可以帮助您确定网络带宽是否足以满足您的工作负载。

如果您的网络带宽不够，请增加它。如果 AWS 客户端或您的数据库实例已达到网络带宽限制，增加带宽的唯一方法是增加数据库实例大小。有关更多信息，请参阅 [数据库实例类类型](Concepts.DBInstanceClass.Types.md)。

有关 CloudWatch 指标的更多信息，请参阅[Amazon RDS 的 Amazon CloudWatch 指标](rds-metrics.md)。

### 监控网络性能的最大值
<a name="wait-event.clientread.actions.monitor-network-performance"></a>

如果您使用的是 Amazon EC2 客户端，Amazon EC2 会提供网络性能指标的最大值，包括聚合入站和出站网络带宽。它还提供连接跟踪功能，以确保按预期返回数据包以及域名系统 (DNS) 等服务的链接本地服务访问。要监控这些最大值，请使用当前的增强型联网驱动程序并监控客户端的网络性能。

有关更多信息，请参阅《Amazon EC2 用户指南》**中的[监控您的 Amazon EC2 实例的网络性能](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html)，以及《Amazon EC2 用户指南》**中的[监控您的 Amazon EC2 实例的网络性能](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/monitoring-network-performance-ena.html)。

### 监控处于“空闲事务”状态的事务
<a name="wait-event.clientread.actions.check-idle-in-transaction"></a>

检查您是否有越来越多的 `idle in transaction` 连接。要做到这一点，请监控 `pg_stat_activity` 表中的 `state` 列。您可能能够通过运行类似于以下内容的查询来识别连接源。

```
select client_addr, state, count(1) from pg_stat_activity 
where state like 'idle in transaction%' 
group by 1,2 
order by 3 desc
```

# Client:ClientWrite
<a name="wait-event.clientwrite"></a>

当 RDS for PostgreSQL 等待将数据写入客户端时，会发生 `Client:ClientWrite` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.clientwrite.context.supported)
+ [上下文](#wait-event.clientwrite.context)
+ [等待次数增加的可能原因](#wait-event.clientwrite.causes)
+ [操作](#wait-event.clientwrite.actions)

## 支持的引擎版本
<a name="wait-event.clientwrite.context.supported"></a>

RDS for PostgreSQL 版本 10 及更高版本支持此等待事件信息。

## 上下文
<a name="wait-event.clientwrite.context"></a>

客户端进程必须先读取从 RDS for PostgreSQL 数据库集群接收的所有数据，然后集群才能发送更多数据。集群在将更多数据发送给客户端之前等待的时间为 `Client:ClientWrite` 事件。

RDS for PostgreSQL 数据库实例与客户端之间的网络吞吐量降低可能会导致此事件。客户端的 CPU 压力和网络饱和也可能导致此事件。*CPU 压力*是 CPU 被充分利用并且有任务等待 CPU 时间的时间。*网络饱和*是当数据库和客户端之间的网络传输的数据超出其处理能力之时。

## 等待次数增加的可能原因
<a name="wait-event.clientwrite.causes"></a>

`Client:ClientWrite` 显示在主要等待中的常见原因包括以下各项：

**网络延迟增加**  
RDS for PostgreSQL 数据库实例和客户端之间的网络延迟可能会增加。较高的网络延迟会增加客户端接收数据所需的时间。

**客户端负载增加**  
客户端上可能存在 CPU 压力或网络饱和。客户端负载的增加会延迟从 RDS for PostgreSQL 数据库实例接收数据的过程。

**发送到客户端的大量数据**  
RDS for PostgreSQL 数据库实例可能会向客户端发送大量数据。客户端可能无法像集群发送数据那样地快速接收数据。诸如大型表的副本之类的活动可能会导致 `Client:ClientWrite` 事件增加。

## 操作
<a name="wait-event.clientwrite.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [将客户端放置在与集群相同的可用区和 VPC 子网中。](#wait-event.clientwrite.actions.az-vpc-subnet)
+ [使用当前一代实例](#wait-event.clientwrite.actions.db-instance-class)
+ [减少发送到客户端的数据量](#wait-event.clientwrite.actions.reduce-data)
+ [扩展客户端](#wait-event.clientwrite.actions.scale-client)

### 将客户端放置在与集群相同的可用区和 VPC 子网中。
<a name="wait-event.clientwrite.actions.az-vpc-subnet"></a>

为了减少网络延迟并提高网络吞吐量，请将客户端放在与 RDS for PostgreSQL 数据库实例相同的可用区和虚拟私有云（VPC）子网中。

### 使用当前一代实例
<a name="wait-event.clientwrite.actions.db-instance-class"></a>

在某些情况下，您可能没有使用支持巨型帧的数据库实例类。如果您在 Amazon EC2 上运行应用程序，请考虑为客户端使用当前一代实例。另外，在客户端操作系统上配置最大传输单位 (MTU)。这种技术可能会减少网络往返次数并提高网络吞吐量。有关更多信息，请参阅《Amazon EC2 用户指南》**中的[巨型帧（9001 MTU）](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances)。

有关数据库实例类的信息，请参阅 [数据库实例类](Concepts.DBInstanceClass.md)。要确定等同于 Amazon EC2 实例类型的数据库实例类，请将 `db.` 放置在 Amazon EC2 实例类型名称之前。例如，`r5.8xlarge` Amazon EC2 实例等同于 `db.r5.8xlarge` 数据库实例类。

### 减少发送到客户端的数据量
<a name="wait-event.clientwrite.actions.reduce-data"></a>

如果可能，请调整应用程序以减少 RDS for PostgreSQL 数据库实例发送给客户端的数据量。进行这样的调整可以减轻客户端上的 CPU 和网络争用。

### 扩展客户端
<a name="wait-event.clientwrite.actions.scale-client"></a>

使用 Amazon CloudWatch 或其他主机指标，确定您的客户端当前是受 CPU 或网络带宽的限制，还是受此两者的限制。如果客户端受到限制，请相应地扩展您的客户端。

# CPU
<a name="wait-event.cpu"></a>

当线程在 CPU 中处于活动状态或正在等待 CPU 时，会发生此事件。

**Topics**
+ [支持的引擎版本](#wait-event.cpu.context.supported)
+ [上下文](#wait-event.cpu.context)
+ [等待次数增加的可能原因](#wait-event.cpu.causes)
+ [操作](#wait-event.cpu.actions)

## 支持的引擎版本
<a name="wait-event.cpu.context.supported"></a>

此等待事件信息与所有的 RDS for PostgreSQL 版本相关。

## 上下文
<a name="wait-event.cpu.context"></a>

*中央处理单元 (CPU)* 是运行指令的计算机的组件。例如，CPU 指令执行算术运算并在内存中交换数据。如果查询增加了通过数据库引擎执行的指令的数量，则运行查询所花费的时间将增加。*CPU 调度*正在为进程提供 CPU 时间。调度由操作系统的内核编排。

**Topics**
+ [如何判断此等待何时发生](#wait-event.cpu.when-it-occurs)
+ [DBLoadCPU 指标](#wait-event.cpu.context.dbloadcpu)
+ [os.cpuUtilization 指标](#wait-event.cpu.context.osmetrics)
+ [CPU 调度的可能原因](#wait-event.cpu.context.scheduling)

### 如何判断此等待何时发生
<a name="wait-event.cpu.when-it-occurs"></a>

该 `CPU` 等待事件表示后端进程在 CPU 中处于活动状态或正在等待 CPU。您知道，当查询显示以下信息时会发生这种情况：
+ The `pg_stat_activity.state` column has the value `active`。
+ `pg_stat_activity` 中的 `wait_event_type` 和 `wait_event` 列都是 `null`。

要查看正在使用或等待 CPU 的后端进程，请运行以下查询。

```
SELECT * 
FROM   pg_stat_activity
WHERE  state = 'active'
AND    wait_event_type IS NULL
AND    wait_event IS NULL;
```

### DBLoadCPU 指标
<a name="wait-event.cpu.context.dbloadcpu"></a>

CPU 的性能详情指标为 `DBLoadCPU`。`DBLoadCPU` 的值可能与 Amazon CloudWatch 指标 `CPUUtilization` 的值不同。后一个指标是从 Hypervisor 中收集的，用于数据库实例。

### os.cpuUtilization 指标
<a name="wait-event.cpu.context.osmetrics"></a>

性能详情操作系统指标提供有关 CPU 利用率的详细信息。例如，您可以显示以下指标：
+ `os.cpuUtilization.nice.avg`
+ `os.cpuUtilization.total.avg`
+ `os.cpuUtilization.wait.avg`
+ `os.cpuUtilization.idle.avg`

性能详情将数据库引擎的 CPU 使用情况报告为 `os.cpuUtilization.nice.avg`。

### CPU 调度的可能原因
<a name="wait-event.cpu.context.scheduling"></a>

 操作系统（OS）内核处理 CPU 的调度。当 CPU 处于*活动状态*时，进程可能需要等待才能获得调度。CPU 在执行计算时处于活动状态。当它有一个未运行的空闲线程（也即，一个等待内存输入/输出的空闲线程）时也处于活动状态。这种类型的 I/O 主导着典型的数据库工作负载。

满足以下条件时，进程可能会等待获得 CPU 调度：
+ CloudWatch `CPUUtilization` 指标接近 100%。
+ 平均负载大于 vCPU 的数量，表示负载过重。您可以在性能详情中的操作系统指标部分找到 `loadAverageMinute` 指标。

## 等待次数增加的可能原因
<a name="wait-event.cpu.causes"></a>

当此事件的发生率超过正常（可能表示性能问题）时，典型的原因包括以下几点。

**Topics**
+ [突然猛增的可能原因](#wait-event.cpu.causes.spikes)
+ [长期高频的可能原因](#wait-event.cpu.causes.long-term)
+ [极端状况](#wait-event.cpu.causes.corner-cases)

### 突然猛增的可能原因
<a name="wait-event.cpu.causes.spikes"></a>

突然猛增的最可能原因如下：
+ 您的应用程序打开了太多与数据库同时连接。这种情况被称为“连接风暴”。
+ 您的应用程序工作负载在以下任一方面发生变化：
  + 新查询
  + 数据集的大小增加
  + 索引维护或创建
  + 新函数
  + 新的运营商
  + 并行查询执行增加
+ 您的查询执行计划已更改。在某些情况下，更改可能会导致缓冲区增加。例如，查询之前使用索引，而现在正在使用顺序扫描。在这种情况下，查询需要更多的 CPU 才能实现同样的目标。

### 长期高频的可能原因
<a name="wait-event.cpu.causes.long-term"></a>

长期反复出现的事件的最可能原因：
+ CPU 上同时运行的后端进程太多。这些进程可以是并行工件。
+ 查询执行不佳，因为它们需要大量缓冲区。

### 极端状况
<a name="wait-event.cpu.causes.corner-cases"></a>

如果所有可能的原因都不是实际原因，则可能会发生以下情况：
+ CPU 正在换入和换出进程。
+ 如果关闭了*大页*功能，CPU 可能正在管理页表条目。原定设置情况下，微型、小型和中型数据库实例类以外的所有数据库实例类都会开启内存管理功能。有关更多信息，请参阅 [适用于 RDS for PostgreSQL 的大页](PostgreSQL.Concepts.General.FeatureSupport.HugePages.md)。

## 操作
<a name="wait-event.cpu.actions"></a>

如果 `CPU` 等待事件主导着数据库活动，它不一定表示性能问题。只在性能下降时应对此事件。

**Topics**
+ [调查数据库是否导致 CPU 增加](#wait-event.cpu.actions.db-CPU)
+ [确定连接数量是否增加](#wait-event.cpu.actions.connections)
+ [响应工作负载变化](#wait-event.cpu.actions.workload)

### 调查数据库是否导致 CPU 增加
<a name="wait-event.cpu.actions.db-CPU"></a>

检查性能详情中的 `os.cpuUtilization.nice.avg` 指标。如果此值远低于 CPU 使用率，则非数据库进程是 CPU 的主要贡献者。

### 确定连接数量是否增加
<a name="wait-event.cpu.actions.connections"></a>

检查 Amazon CloudWatch 中的 `DatabaseConnections` 指标。您的操作取决于 CPU 等待事件增加期间该数量是增加还是减少。

#### 连接增加
<a name="wait-event.cpu.actions.connections.increased"></a>

如果连接数量增加，请将消耗 CPU 的后端进程数与 vCPU 的数量进行比较。以下是可能的情况：
+ 消耗 CPU 的后端进程数量少于 vCPU 的数量。

  在这种情况下，连接数量不是问题。但是，您仍然可以尝试降低 CPU 利用率。
+ 消耗 CPU 的后端进程数量大于 vCPU 的数量。

  在这种情况下，需考虑以下选项：
  + 减少连接到数据库的后端进程的数量。例如，实施连接池解决方案，例如 RDS 代理。要了解更多信息，请参阅[Amazon RDS 代理](rds-proxy.md)。
  + 升级实例大小以获得更多 vCPU 数量。
  + 如果适用，将一些只读工作负载重新导向到读取器节点。

#### 连接未增加
<a name="wait-event.cpu.actions.connections.decreased"></a>

检查性能详情中的 `blks_hit` 指标。寻找 `blks_hit` 增加与 CPU 使用率之间的相关性。以下是可能的情况：
+ CPU 使用率和 `blks_hit` 具有相关性。

  在这种情况下，找到与 CPU 使用率相关联的主要 SQL 语句，然后查找计划更改。您可以使用下面的方法之一：
  + 手动解释计划并将其与预期的执行计划进行比较。
  + 寻找每秒数据块命中量和每秒局部数据块命中量的增加。在性能详情控制面板的**主要 SQL** 部分中，选择 **Preferences**（首选项）。
+ CPU 使用率和 `blks_hit` 无关。

  在这种情况下，请确定是否出现以下任一情况：
  + 应用程序正在快速连接到数据库并断开与数据库的连接。

    通过打开 `log_connections` 和 `log_disconnections`，然后分析 PostgreSQL 日志来诊断此行为。考虑使用 `pgbadger` 日志分析器。有关更多信息，请参阅 [https://github.com/darold/pgbadger](https://github.com/darold/pgbadger)。
  + 操作系统已超载。

    在这种情况下，性能详情显示，后端进程使用 CPU 的时间比平时更长。在性能详情 `os.cpuUtilization` 指标或 CloudWatch `CPUUtilization` 指标中寻找证据。如果操作系统过载，请查看增强监控指标以进一步诊断。具体来说，请查看进程列表以及每个进程占用的 CPU 百分比。
  + 主要 SQL 语句消耗的 CPU 太多。

    检查与 CPU 使用率相关联的语句，看看它们是否可以使用更少的 CPU。运行 `EXPLAIN` 命令，并将重点放在影响最大的计划节点上。考虑使用 PostgreSQL 执行计划可视化工具。要试用此工具，请参阅 [http://explain.dalibo.com/](http://explain.dalibo.com/)。

### 响应工作负载变化
<a name="wait-event.cpu.actions.workload"></a>

如果您的工作负载发生了变化，请查找以下类型的更改：

新查询  
检查是否预计会出现新的查询。如果是，请确保他们的执行计划和每秒执行次数符合预期。

数据集的大小增加  
确定分区（如果尚未实施）是否有帮助。此策略可能会减少查询需要检索的页数。

索引维护或创建  
检查维护时间表是否符合预期。最佳实践是在高峰活动之外安排维护活动。

新函数  
检查这些功能在测试期间是否按预期运行。具体来说，检查每秒执行次数是否符合预期。

新的运营商  
检查它们在测试期间是否按预期运行。

运行并行查询的增加  
确定是否出现以下任一情况：  
+ 所涉及的关系或索引的规模突然增长，因此它们与 `min_parallel_table_scan_size` 或 `min_parallel_index_scan_size` 显著不同。
+ 最近对 `parallel_setup_cost` 或 `parallel_tuple_cost` 进行了更改。
+ 最近对 `max_parallel_workers` 或 `max_parallel_workers_per_gather` 进行了更改。

# IO:BufFileRead 和 IO:BufFileWrite
<a name="wait-event.iobuffile"></a>

`IO:BufFileRead` 和 `IO:BufFileWrite` 事件发生在 RDS for PostgreSQL 创建临时文件时。当操作需要的内存超过当前定义的工作内存参数时，它们会将临时数据写入持久性存储。此操作有时被称为*溢出到磁盘*。有关临时文件及其用法的更多信息，请参阅[使用 PostgreSQL 管理临时文件](PostgreSQL.ManagingTempFiles.md)。

**Topics**
+ [支持的引擎版本](#wait-event.iobuffile.context.supported)
+ [上下文](#wait-event.iobuffile.context)
+ [等待次数增加的可能原因](#wait-event.iobuffile.causes)
+ [操作](#wait-event.iobuffile.actions)

## 支持的引擎版本
<a name="wait-event.iobuffile.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.iobuffile.context"></a>

`IO:BufFileRead` 和 `IO:BufFileWrite` 与工作内存区域和维护工作内存区域有关。有关这些本地内存区域的更多信息，请参阅 PostgreSQL 文档中的[资源消耗量](https://www.postgresql.org/docs/current/runtime-config-resource.html)。

`work_mem` 的原定设置值为 4MB。如果一个会话并行执行操作，则处理并行性的每个工件将使用 4MB 的内存。出于此原因，请仔细设置 `work_mem`。如果您将值增加的太大，则运行很多会话的数据库可能会占用太多内存。如果您将值设置得太低，RDS for PostgreSQL 会在本地存储中创建临时文件。这些临时文件的磁盘输入/输出可能会降低性能。

如果观察到以下事件顺序，则数据库可能正在生成临时文件：

1. 可用性突然急剧下降

1. 可用空间的快速恢复

您可能还会看到“chainsaw”模式。此模式可能表明您的数据库在不断创建小文件。

## 等待次数增加的可能原因
<a name="wait-event.iobuffile.causes"></a>

一般来说，这些等待事件是占用内存比 `work_mem` 或 `maintenance_work_mem` 参数分配的内存更多的操作造成。为了进行补偿，操作会写入临时文件。`IO:BufFileRead` 和 `IO:BufFileWrite` 事件的常见原因包括以下内容：

**需要比工作内存区域中存在的内存更多的查询**  
具有以下特征的查询使用工作内存区域：  
+ 哈希联接
+ `ORDER BY` 子句
+ `GROUP BY` 子句
+ `DISTINCT`
+ 窗口函数
+ `CREATE TABLE AS SELECT`
+ 具体化视图刷新

**需要比维护工作内存区域中存在的内存更多的语句**  
以下语句使用维护工作内存区域：  
+ `CREATE INDEX`
+ `CLUSTER`

## 操作
<a name="wait-event.iobuffile.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [识别问题](#wait-event.iobuffile.actions.problem)
+ [请检查您的联接查询](#wait-event.iobuffile.actions.joins)
+ [检查您的 ORDER BY 和 GROUP BY 查询](#wait-event.iobuffile.actions.order-by)
+ [避免使用 DISTINCT 操作](#wait-event.iobuffile.actions.distinct)
+ [考虑使用窗口函数而不是 GROUP BY 函数](#wait-event.iobuffile.actions.window)
+ [调查具体化视图和 CTAS 语句](#wait-event.iobuffile.actions.mv-refresh)
+ [在重新构建索引时使用 pg\$1repack](#wait-event.iobuffile.actions.pg_repack)
+ [聚集表时，增加 maintenance\$1work\$1mem](#wait-event.iobuffile.actions.cluster)
+ [优化内存以防止 IO:BufFileRead 和 IO:BufFileWrite](#wait-event.iobuffile.actions.tuning-memory)

### 识别问题
<a name="wait-event.iobuffile.actions.problem"></a>

您可以直接在性能详情中查看临时文件的使用情况。有关更多信息，请参阅 [使用性能详情查看临时文件使用情况](PostgreSQL.ManagingTempFiles.Example.md)。禁用性能详情后，您可能会注意到 `IO:BufFileRead` 和 `IO:BufFileWrite` 操作量有所增加。

要确定问题的根源，可以将 `log_temp_files` 参数设置为记录所生成的临时文件超过指定阈值 KB 的所有查询。原定设置情况下，`log_temp_files` 设置为 `-1`，这将关闭此日志记录功能。如果您将此参数设置为 `0`，RDS for PostgreSQL 会记录所有临时文件。如果值为 `1024`，RDS for PostgreSQL 会记录所生成的临时文件大于 1MB 的所有查询。有关 `log_temp_files` 更多信息，请参阅 PostgreSQL 文档中的[错误报告和日志记录](https://www.postgresql.org/docs/current/runtime-config-logging.html)。

### 请检查您的联接查询
<a name="wait-event.iobuffile.actions.joins"></a>

您的查询很可能使用联接。例如，以下查询将四个表联接到一起。

```
SELECT * 
       FROM "order" 
 INNER JOIN order_item 
       ON (order.id = order_item.order_id)
 INNER JOIN customer 
       ON (customer.id = order.customer_id)
 INNER JOIN customer_address 
       ON (customer_address.customer_id = customer.id AND 
           order.customer_address_id = customer_address.id)
 WHERE customer.id = 1234567890;
```

临时文件使用率激增的可能原因是查询本身存在问题。例如，中断的子句可能无法正确筛选联接。考虑以下示例中的第二个内联接。

```
SELECT * 
       FROM "order"
 INNER JOIN order_item 
       ON (order.id = order_item.order_id)
 INNER JOIN customer 
       ON (customer.id = customer.id)
 INNER JOIN customer_address 
       ON (customer_address.customer_id = customer.id AND 
           order.customer_address_id = customer_address.id)
 WHERE customer.id = 1234567890;
```

前面的查询错误地将 `customer.id` 与 `customer.id` 进行了联接，在每个客户和每个订单之间生成了笛卡尔积。这种类型的意外联接会生成大型临时文件。根据表的大小，笛卡尔查询甚至可以填满存储空间。满足以下条件时，您的应用程序可能会有笛卡尔联接：
+ 您可以看到存储可用性大幅下降，然后是快速恢复。
+ 现在没有创建任何索引。
+ 现在没有发布任何 `CREATE TABLE FROM SELECT` 语句。
+ 没有进行任何具体化视图的刷新。

要查看是否使用正确的键联接表，请检查查询和对象关系映射指令。请记住，应用程序的某些查询不会总是被调用，而且有些查询是动态生成的。

### 检查您的 ORDER BY 和 GROUP BY 查询
<a name="wait-event.iobuffile.actions.order-by"></a>

在某些情况下，`ORDER BY` 子句可能会导致过多的临时文件。请考虑以下准则：
+ 当需要对它们进行排序时，只包括 `ORDER BY` 子句中的列。本指南对于返回数千行并在 `ORDER BY` 子句中指定很多列的查询尤其重要。
+ 考虑创建索引以在 `ORDER BY` 子句与具有相同升序或降序的列匹配时对它们进行加速。部分索引更可取，因为它们较小。较小的索引可以更快地读取和遍历。
+ 如果为可以接受 null 值的列创建索引，请考虑是希望将 null 值存储在索引的末尾还是在索引的开头存储。

  如果可能，通过筛选结果集来减少需要排序的行数。如果您使用 `WITH` 子句语句或子查询，请记住，内部查询会生成一个结果集并会将其传递给外部查询。查询可以筛选出的行越多，查询需要进行的排序就越少。
+ 如果您不需要获取完整的结果集，请使用 `LIMIT` 子句。例如，如果您只想要前五行，则使用 `LIMIT` 子句的查询不会继续生成结果。这样，查询需要更少的内存和临时文件。

使用 `GROUP BY` 子句的查询也可能需要临时文件。`GROUP BY` 查询通过使用以下函数汇总值：
+ `COUNT`
+ `AVG`
+ `MIN`
+ `MAX`
+ `SUM`
+ `STDDEV`

要优化 `GROUP BY` 查询，请按照 `ORDER BY` 查询的建议。

### 避免使用 DISTINCT 操作
<a name="wait-event.iobuffile.actions.distinct"></a>

如果可能的话，避免使用 `DISTINCT` 操作来删除重复的行。查询返回的不必要和重复的行越多，`DISTINCT` 操作就会越昂贵。如果可能，请在 `WHERE` 子句中添加筛选条件，即使您对不同的表使用相同的筛选条件。筛选查询并正确联接可以提高性能并减少资源使用。它还可以防止错误的报告和结果。

如果您需要将 `DISTINCT` 用于同一个表的多行，请考虑创建复合索引。将索引中的多个列进行分组可以缩短评估不同行的时间。此外，如果您使用 RDS for PostgreSQL 版本 10 或更高版本，则可以使用 `CREATE STATISTICS` 命令在多个列之间关联统计数据。

### 考虑使用窗口函数而不是 GROUP BY 函数
<a name="wait-event.iobuffile.actions.window"></a>

使用 `GROUP BY`，您可以更改结果集，然后检索聚合的结果。使用窗口函数，可以在不更改结果集的情况下聚合数据。窗口函数使用 `OVER` 子句来跨查询定义的集执行计算，从而将一行与另一行关联。您可以使用窗口函数中的所有 `GROUP BY` 函数，但也可以使用以下函数：
+ `RANK`
+ `ARRAY_AGG`
+ `ROW_NUMBER`
+ `LAG`
+ `LEAD`

为了尽量减少窗口函数生成的临时文件的数量，请在需要两个不同的聚合时删除同一结果集的重复项。请考虑以下查询。

```
SELECT sum(salary) OVER (PARTITION BY dept ORDER BY salary DESC) as sum_salary
     , avg(salary) OVER (PARTITION BY dept ORDER BY salary ASC) as avg_salary
  FROM empsalary;
```

您可以使用如下 `WINDOW` 子句重新写入查询。

```
SELECT sum(salary) OVER w as sum_salary
         , avg(salary) OVER w as_avg_salary
    FROM empsalary
  WINDOW w AS (PARTITION BY dept ORDER BY salary DESC);
```

原定设置情况下，RDS for PostgreSQL 执行计划器会整合类似的节点，这样它就不会重复操作。但是，通过对窗口数据块使用显式声明，您可以更轻松地维护查询。您还可以通过防止重复来提高性能。

### 调查具体化视图和 CTAS 语句
<a name="wait-event.iobuffile.actions.mv-refresh"></a>

当具体化视图刷新时，它会运行查询。此查询可以包含 `GROUP BY`、`ORDER BY` 或 `DISTINCT` 之类的操作。刷新期间，您可能会观察到大量临时文件以及等待事件 `IO:BufFileWrite` 和 `IO:BufFileRead`。同样地，当您根据 `SELECT` 语句创建表时，`CREATE TABLE` 语句会运行查询。要减少所需的临时文件，请优化查询。

### 在重新构建索引时使用 pg\$1repack
<a name="wait-event.iobuffile.actions.pg_repack"></a>

创建索引时，引擎会对结果集进行排序。随着表的大小增加以及索引列中的值变得更加多样化，临时文件需要更多的空间。在大多数情况下，如果不修改维护工作内存区域，就无法阻止为大型表创建临时文件。有关 `maintenance_work_mem` 的更多信息，请参阅 PostgreSQL 文档中的[https://www.postgresql.org/docs/current/runtime-config-resource.html](https://www.postgresql.org/docs/current/runtime-config-resource.html)。

重新创建大型索引时可能的解决方法是使用 pg\$1repack 扩展。有关更多信息，请参阅 pg\$1repack 文档中的[用最少的锁定重新组织 PostgreSQL 数据库中的表](https://reorg.github.io/pg_repack/)。有关在 RDS for PostgreSQL 数据库实例中设置此扩展的信息，请参阅[使用 pg\$1repack 扩展减少表和索引的膨胀](Appendix.PostgreSQL.CommonDBATasks.pg_repack.md)。

### 聚集表时，增加 maintenance\$1work\$1mem
<a name="wait-event.iobuffile.actions.cluster"></a>

`CLUSTER` 命令基于 *index\$1name* 指定的现有索引聚集 *table\$1name* 指定的表。RDS for PostgreSQL 以物理方式重新创建表以匹配给定索引的顺序。

当磁性存储普遍存在时，集群很常见，因为存储吞吐量有限。由于基于 SSD 的存储已经很常见，因此集群不太受欢迎。但是，如果对表进行聚集，您仍然可以根据表大小、索引、查询等稍微提高性能。

如果您运行 `CLUSTER` 命令并观察到等待事件 `IO:BufFileWrite` 和 `IO:BufFileRead`，请优化 `maintenance_work_mem`。将内存大小增加到相当大的量。较高的值意味着引擎可以使用更多内存进行集群操作。

### 优化内存以防止 IO:BufFileRead 和 IO:BufFileWrite
<a name="wait-event.iobuffile.actions.tuning-memory"></a>

在某些情况下，您需要优化内存。您的目标是使用相应的参数平衡以下消耗区域间的内存，如下所示。
+ `work_mem` 值 
+ 折扣 `shared_buffers` 值后剩余的内存
+ 已打开和使用中的最大连接数，受限于 `max_connections`

有关优化内存的更多信息，请参阅 PostgreSQL 文档中的[资源消耗量](https://www.postgresql.org/docs/current/runtime-config-resource.html)。

#### 增加工作内存区域的大小
<a name="wait-event.iobuffile.actions.tuning-memory.work-mem"></a>

在某些情况下，唯一的选项是增加会话使用的内存。如果您的查询编写正确并且正在使用正确的键进行连接，请考虑增加 `work_mem` 值。

要了解查询生成了多少个临时文件，请将 `log_temp_files` 设置为 `0`。如果您将 `work_mem` 值增加为日志中标识的最大值，则可以防止查询生成临时文件。但是，`work_mem` 为每个连接或并行工件设置每个计划节点的最大值。如果数据库有 5000 个连接，并且每个连接使用 256MiB 内存，则引擎需要 1.2TiB 的 RAM。因此，您的实例可能会耗尽内存。

#### 为共享缓冲池预留足够的内存
<a name="wait-event.iobuffile.actions.tuning-memory.shared-pool"></a>

您的数据库使用很多内存区域，例如共享缓冲池，而不仅仅是工作内存区域。在增加 `work_mem` 之前考虑这些额外的内存区域的要求。

例如，假设您的 RDS for PostgreSQL 实例类为 db.r5.2xlarge。此实例类拥有 64GiB 的内存。原定设置情况下，将 25% 的内存预留为共享缓冲池。减去分配给共享内存区域的量后，仍然有 16384 MB。不要将剩余内存专门分配给工作内存区域，因为操作系统和引擎还需要内存。

您可以分配给 `work_mem` 的内存取决于实例类。如果您使用较大的实例类，则可用的内存更多。但是，在前面的示例中，您不能使用超过 16GiB 的内存。否则，当内存耗尽时，您的实例将变得不可用。要从不可用状态恢复实例，RDS for PostgreSQL 自动化服务会自动重新启动。

#### 管理连接数
<a name="wait-event.iobuffile.actions.tuning-memory.connections"></a>

假设您的数据库实例具有 5000 个同时连接。每个连接至少使用 4MiB 的 `work_mem` 连接的内存消耗过高可能会降低性能。作为响应，您可进行以下选择：
+ 升级到更大的实例类。
+ 使用连接代理或池程序减少同时数据库连接的数量。

对于代理，请考虑 Amazon RDS 代理、pgBouncer 或基于您的应用程序的连接池程序。此解决方案减轻了 CPU 负载。它还可以降低所有连接都需要工作内存区域时的风险。当数据库连接较少时，您可以增加 `work_mem` 的值。通过这种方式，您可以减少 `IO:BufFileRead` 和 `IO:BufFileWrite` 等待事件的发生率。此外，等待工作内存区域的查询显著加速。

# IO:DataFileRead
<a name="wait-event.iodatafileread"></a>

当由于分页在共享内存中不可用，连接等待后端进程从存储中读取所需分页时，会发生 `IO:DataFileRead` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.iodatafileread.context.supported)
+ [上下文](#wait-event.iodatafileread.context)
+ [等待次数增加的可能原因](#wait-event.iodatafileread.causes)
+ [操作](#wait-event.iodatafileread.actions)

## 支持的引擎版本
<a name="wait-event.iodatafileread.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.iodatafileread.context"></a>

所有查询和数据处理 (DML) 操作都会访问缓冲池中的页面。可以诱导读取的语句包括 `SELECT`、`UPDATE` 和 `DELETE`。例如，`UPDATE` 可以从表或索引中读取页面。如果请求或更新的页面不在共享缓冲池中，则此读取可能会导致 `IO:DataFileRead` 事件。

由于共享缓冲池是有限的，所以它可以填满。在这种情况下，对不在内存中的页面的请求会强制数据库从磁盘中读取数据块。如果 `IO:DataFileRead` 事件频繁发生，您的共享缓冲池可能太小，从而无法容纳您的工作负载。对于读取大量不适合缓冲池的行的 `SELECT` 查询，此问题很严重。有关缓冲区池的更多信息，请参阅 PostgreSQL 文档中的[资源消耗量](https://www.postgresql.org/docs/current/runtime-config-resource.html)。

## 等待次数增加的可能原因
<a name="wait-event.iodatafileread.causes"></a>

`IO:DataFileRead` 事件的常见原因包括以下各项：

**连接激增**  
您可能会发现多个连接生成相同数量的 IO:DataFileRead 等待事件。在这种情况下，`IO:DataFileRead` 事件可能会发生激增（突然大幅度增加）。

**执行顺序扫描的 SELECT 和 DML 语句**  
您的应用程序可能正在执行新的操作。或者，现有的操作可能会因为新的执行计划而发生变化。在这种情况下，请查找具有更大的 `seq_scan` 值的表格（特别是大型表格）。通过查询 `pg_stat_user_tables` 查找它们。要跟踪生成更多读取操作的查询，请使用扩展 `pg_stat_statements`。

**适用于大型数据集的 CTAS 和 CREATE INDEX**  
*CTAS* 是一个 `CREATE TABLE AS SELECT` 语句。如果您使用大型数据集作为源来运行 CTAS，或者在大型表上创建索引，则可能会发生 `IO:DataFileRead` 事件。创建索引时，数据库可能需要使用顺序扫描读取整个对象。当页面不在内存中时，CTAS 会生成 `IO:DataFile` 读取。

**多个 vacuum 工件同时运行**  
vacuum 工件可以手动或自动触发。我们建议采取积极的 vacuum 策略。但是，当表中有许多更新或删除的行时，`IO:DataFileRead` 等待增加。回收空间后，花在 `IO:DataFileRead` 上的 vacuum 时间减少。

**摄取大量数据**  
当您的应用程序提取大量数据时，`ANALYZE` 操作可能会更频繁地发生。`ANALYZE` 进程可以由 Autovacuum 启动程序触发，也可以手动调用。  
`ANALYZE` 操作可以读取表的子集。必须扫描的页数通过将 30 乘以 `default_statistics_target` 值进行计算。有关更多信息，请参阅 [PostgreSQL 文档](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET)。`default_statistics_target` 参数接受 1 到 10000 之间的值，其中原定设置值为 100。

**资源匮乏**  
如果消耗了实例网络带宽或 CPU，`IO:DataFileRead` 事件可能会更频繁地发生。

## 操作
<a name="wait-event.iodatafileread.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [检查谓词筛选条件是否存在生成等待的查询](#wait-event.iodatafileread.actions.filters)
+ [尽量减少维护操作的影响](#wait-event.iodatafileread.actions.maintenance)
+ [响应大量连接](#wait-event.iodatafileread.actions.connections)

### 检查谓词筛选条件是否存在生成等待的查询
<a name="wait-event.iodatafileread.actions.filters"></a>

假设您确定了正在生成 `IO:DataFileRead` 等待事件的特定查询。您可以使用以下方法识别它们：
+ 性能详情
+ 目录视图，例如扩展程序 `pg_stat_statements` 提供的视图
+ 目录视图 `pg_stat_all_tables`，如果它定期显示物理读取数量增加
+ `pg_statio_all_tables` 视图，如果它显示 `_read` 计数器正在增加

我们建议您确定这些查询的谓词（`WHERE` 子句）中使用了哪些筛选条件。请遵循以下准则：
+ 运行 `EXPLAIN` 命令。在输出中，确定使用的扫描类型。顺序扫描不一定表示存在问题。与使用筛选条件的查询相比，使用顺序扫描的查询自然会产生更多的 `IO:DataFileRead` 事件。

  了解 `WHERE` 子句中列出的列是否已编入索引。如果没有，请考虑为此列创建索引。这种方法避免了顺序扫描并减少了 `IO:DataFileRead` 事件。如果某个查询具有限制性筛选条件并且仍然生成顺序扫描，请评估是否使用了正确的索引。
+ 了解查询是否正在访问非常大的表。在某些情况下，对表进行分区可以提高性能，从而允许查询只读取必要的分区。
+ 检查联接操作的基数（总行数）。请注意您在筛选条件中为您的 `WHERE` 子句传递的值的限制性。如果可能，请优化查询以减少在计划的每个步骤中传递的行数。

### 尽量减少维护操作的影响
<a name="wait-event.iodatafileread.actions.maintenance"></a>

维护操作（例如 `VACUUM` 和 `ANALYZE`）非常重要。我们建议您不要将其关闭，因为您会找到与这些维护操作相关的 `IO:DataFileRead` 等待事件。以下方法可以最大限度地减少这些操作的影响：
+ 在非高峰时段手动运行维护操作。此方法可防止数据库达到自动操作的阈值。
+ 对于非常大的表，请考虑对表进行分区。这种方法减少了维护操作的开销。数据库只访问需要维护的分区。
+ 当您摄取大量数据时，请考虑禁用自动分析功能。

当以下公式为真时，系统会自动为表触发 Autovacuum 功能。

```
pg_stat_user_tables.n_dead_tup > (pg_class.reltuples x autovacuum_vacuum_scale_factor) + autovacuum_vacuum_threshold
```

视图 `pg_stat_user_tables` 和目录 `pg_class` 有多个行。一行可以对应于表中的一行。这个公式假设 `reltuples` 适用于特定的表。参数 `autovacuum_vacuum_scale_factor`（原定设置为 0.20）和 `autovacuum_vacuum_threshold`（原定设置为 50 个元组）通常在全局范围内为整个实例设置。但是，您可以为特定表设置不同的值。

**Topics**
+ [查找不必要地占用空间的表](#wait-event.iodatafileread.actions.maintenance.tables)
+ [查找不必要地占用空间的索引](#wait-event.iodatafileread.actions.maintenance.indexes)
+ [查找符合 Autovacuum 操作条件的表](#wait-event.iodatafileread.actions.maintenance.autovacuumed)

#### 查找不必要地占用空间的表
<a name="wait-event.iodatafileread.actions.maintenance.tables"></a>

要查找不必要地占用空间的表，可以使用 PostgreSQL `pgstattuple` 扩展中的函数。原定设置情况下，此扩展（模块）在所有 RDS for PostgreSQL 数据库实例上均可用，并且可以使用以下命令在实例上进行实例化。

```
CREATE EXTENSION pgstattuple;
```

有关此扩展的更多信息，请参阅 PostgreSQL 文档中的 [pgstattuple](https://www.postgresql.org/docs/current/pgstattuple.html)。

您可以在应用程序中检查表和索引膨胀。有关更多信息，请参[诊断表和索引膨胀](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.diag-table-ind-bloat.html)。

#### 查找不必要地占用空间的索引
<a name="wait-event.iodatafileread.actions.maintenance.indexes"></a>

要查找臃肿的索引并估计在您具有读取权限的表上不必要地消耗的空间量，可以运行以下查询。

```
-- WARNING: rows with is_na = 't' are known to have bad statistics ("name" type is not supported).
-- This query is compatible with PostgreSQL 8.2 and later.

SELECT current_database(), nspname AS schemaname, tblname, idxname, bs*(relpages)::bigint AS real_size,
  bs*(relpages-est_pages)::bigint AS extra_size,
  100 * (relpages-est_pages)::float / relpages AS extra_ratio,
  fillfactor, bs*(relpages-est_pages_ff) AS bloat_size,
  100 * (relpages-est_pages_ff)::float / relpages AS bloat_ratio,
  is_na
  -- , 100-(sub.pst).avg_leaf_density, est_pages, index_tuple_hdr_bm, 
  -- maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, sub.reltuples, sub.relpages 
  -- (DEBUG INFO)
FROM (
  SELECT coalesce(1 +
       ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)), 0 
       -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth)
    ) AS est_pages,
    coalesce(1 +
       ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0
    ) AS est_pages_ff,
    bs, nspname, table_oid, tblname, idxname, relpages, fillfactor, is_na
    -- , stattuple.pgstatindex(quote_ident(nspname)||'.'||quote_ident(idxname)) AS pst, 
    -- index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples 
    -- (DEBUG INFO)
  FROM (
    SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, relam, table_oid, fillfactor,
      ( index_tuple_hdr_bm +
          maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN
            WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
            ELSE index_tuple_hdr_bm%maxalign
          END
        + nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN
            WHEN nulldatawidth = 0 THEN 0
            WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
            ELSE nulldatawidth::integer%maxalign
          END
      )::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
      -- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO)
    FROM (
      SELECT
        i.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.relam, a.attrelid AS table_oid,
        current_setting('block_size')::numeric AS bs, fillfactor,
        CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
          WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8
          ELSE 4
        END AS maxalign,
        /* per page header, fixed size: 20 for 7.X, 24 for others */
        24 AS pagehdr,
        /* per page btree opaque data */
        16 AS pageopqdata,
        /* per tuple header: add IndexAttributeBitMapData if some cols are null-able */
        CASE WHEN max(coalesce(s.null_frac,0)) = 0
          THEN 2 -- IndexTupleData size
          ELSE 2 + (( 32 + 8 - 1 ) / 8) 
          -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8)
        END AS index_tuple_hdr_bm,
        /* data len: we remove null values save space using it fractionnal part from stats */
        sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth,
        max( CASE WHEN a.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na
      FROM pg_attribute AS a
        JOIN (
          SELECT nspname, tbl.relname AS tblname, idx.relname AS idxname, 
            idx.reltuples, idx.relpages, idx.relam,
            indrelid, indexrelid, indkey::smallint[] AS attnum,
            coalesce(substring(
              array_to_string(idx.reloptions, ' ')
               from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor
          FROM pg_index
            JOIN pg_class idx ON idx.oid=pg_index.indexrelid
            JOIN pg_class tbl ON tbl.oid=pg_index.indrelid
            JOIN pg_namespace ON pg_namespace.oid = idx.relnamespace
          WHERE pg_index.indisvalid AND tbl.relkind = 'r' AND idx.relpages > 0
        ) AS i ON a.attrelid = i.indexrelid
        JOIN pg_stats AS s ON s.schemaname = i.nspname
          AND ((s.tablename = i.tblname AND s.attname = pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE)) 
          -- stats from tbl
          OR  (s.tablename = i.idxname AND s.attname = a.attname))
          -- stats from functional cols
        JOIN pg_type AS t ON a.atttypid = t.oid
      WHERE a.attnum > 0
      GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9
    ) AS s1
  ) AS s2
    JOIN pg_am am ON s2.relam = am.oid WHERE am.amname = 'btree'
) AS sub
-- WHERE NOT is_na
ORDER BY 2,3,4;
```

#### 查找符合 Autovacuum 操作条件的表
<a name="wait-event.iodatafileread.actions.maintenance.autovacuumed"></a>

要查找符合 Autovacuum 操作条件的表，请运行以下查询。

```
--This query shows tables that need vacuuming and are eligible candidates.
--The following query lists all tables that are due to be processed by autovacuum. 
-- During normal operation, this query should return very little.
WITH  vbt AS (SELECT setting AS autovacuum_vacuum_threshold 
              FROM pg_settings WHERE name = 'autovacuum_vacuum_threshold')
    , vsf AS (SELECT setting AS autovacuum_vacuum_scale_factor 
              FROM pg_settings WHERE name = 'autovacuum_vacuum_scale_factor')
    , fma AS (SELECT setting AS autovacuum_freeze_max_age 
              FROM pg_settings WHERE name = 'autovacuum_freeze_max_age')
    , sto AS (SELECT opt_oid, split_part(setting, '=', 1) as param, 
                split_part(setting, '=', 2) as value 
              FROM (SELECT oid opt_oid, unnest(reloptions) setting FROM pg_class) opt)
SELECT
    '"'||ns.nspname||'"."'||c.relname||'"' as relation
    , pg_size_pretty(pg_table_size(c.oid)) as table_size
    , age(relfrozenxid) as xid_age
    , coalesce(cfma.value::float, autovacuum_freeze_max_age::float) autovacuum_freeze_max_age
    , (coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
         coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples) 
         as autovacuum_vacuum_tuples
    , n_dead_tup as dead_tuples
FROM pg_class c 
JOIN pg_namespace ns ON ns.oid = c.relnamespace
JOIN pg_stat_all_tables stat ON stat.relid = c.oid
JOIN vbt on (1=1) 
JOIN vsf ON (1=1) 
JOIN fma on (1=1)
LEFT JOIN sto cvbt ON cvbt.param = 'autovacuum_vacuum_threshold' AND c.oid = cvbt.opt_oid
LEFT JOIN sto cvsf ON cvsf.param = 'autovacuum_vacuum_scale_factor' AND c.oid = cvsf.opt_oid
LEFT JOIN sto cfma ON cfma.param = 'autovacuum_freeze_max_age' AND c.oid = cfma.opt_oid
WHERE c.relkind = 'r' 
AND nspname <> 'pg_catalog'
AND (
    age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float)
    or
    coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
      coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples <= n_dead_tup
    -- or 1 = 1
)
ORDER BY age(relfrozenxid) DESC;
```

### 响应大量连接
<a name="wait-event.iodatafileread.actions.connections"></a>

当您监控 Amazon CloudWatch 时，您可能会发现 `DatabaseConnections` 指标激增。这种增加表示与数据库的连接数量有所增加。我们建议采取以下方法：
+ 限制应用程序可与每个实例一起打开的连接数。如果您的应用程序具有嵌入式连接池功能，请设置合理数量的连接。根据实例中的 vCPU 可以有效并行处理的数量来确定数量。

  如果您的应用程序没有使用连接池功能，请考虑使用 Amazon RDS 代理或替代方案。这种方法允许您的应用程序打开与负载均衡器的多个连接。然后，均衡器可以打开与数据库的数量有限的连接。由于并行运行的连接减少，您的数据库实例在内核中执行的上下文切换会减少。查询的进度应该更快，从而导致等待事件减少。有关更多信息，请参阅 [Amazon RDS 代理](rds-proxy.md)。
+ 尽可能利用 RDS for PostgreSQL 的只读副本。当您的应用程序运行只读操作时，将这些请求发送到只读副本。此方法可减少主（写入器）节点上的输入/输出压力。
+ 请考虑纵向扩展数据库实例。更高容量的实例类可提供更多内存，这为 RDS for PostgreSQL 提供了一个更大的共享缓冲池来容纳页面。较大的大小还为数据库实例提供了更多的 vCPU 来处理连接。当生成 `IO:DataFileRead` 等待事件的操作为写入时，更多的 vCPU 会特别有用。

# IO:WALWrite
<a name="wait-event.iowalwrite"></a>



**Topics**
+ [支持的引擎版本](#wait-event.iowalwrite.context.supported)
+ [上下文](#wait-event.iowalwrite.context)
+ [等待次数增加的可能原因](#wait-event.iowalwrite.causes)
+ [操作](#wait-event.iowalwrite.actions)

## 支持的引擎版本
<a name="wait-event.iowalwrite.context.supported"></a>

RDS for PostgreSQL 10 及更高版本的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.iowalwrite.context"></a>

数据库中生成预写日志数据的活动首先填满 WAL 缓冲区，然后异步写入磁盘。当 SQL 会话等待 WAL 数据完成向磁盘写入以便它可以释放事务的 COMMIT 调用时，会生成等待事件 `IO:WALWrite`。

## 等待次数增加的可能原因
<a name="wait-event.iowalwrite.causes"></a>

如果这种等待事件经常发生，则应查看您的工作负载以及工作负载执行的更新类型及其频率。特别要查找以下类型的活动。

**繁重的 DML 活动**  
更改数据库表中的数据不会立即发生。对一个表的插入可能需要等待从另一客户端对同一个表进行插入或更新。用于更改数据值的数据操作语言（DML）语句（INSERT、UPDATE、DELETE、COMMIT、ROLLBACK TRANSATION）可能会导致争用，从而导致预写日志文件等待刷新缓冲区。以下 Amazon RDS 性能详情指标反映了这种情况，这些指标表明 DML 活动非常多。  
+  `tup_inserted`
+ `tup_updated`
+ `tup_deleted`
+ `xact_rollback`
+ `xact_commit`
有关这些指标的更多信息，请参阅 [适用于 Amazon RDS for PostgreSQL 的性能详情计数器](USER_PerfInsights_Counters.md#USER_PerfInsights_Counters.PostgreSQL)。

**频繁的检查点活动**  
过多的检查点会导致更多数量的 WAL 文件。在 RDS for PostgreSQL 中，整页写入始终处于“开启”状态。整页写入有助于防止数据丢失。但是，当检查点活动过于频繁时，系统可能会遇到整体性能问题。在 DML 活动非常多的系统上尤其如此。在某些情况下，您可能会在 `postgresql.log` 中发现错误消息，指出“检查点出现频率过高”。  
我们建议您在优化检查点时，谨慎平衡性能与出现异常关闭时进行恢复所需的预期时间。

## 操作
<a name="wait-event.iowalwrite.actions"></a>

我们建议通过执行以下操作来减少此等待事件的数量。

**Topics**
+ [减少提交的数量](#wait-event.iowalwrite.actions.problem)
+ [监控您的检查点](#wait-event.iowalwrite.actions.monitor)
+ [纵向扩展 IO](#wait-event.iowalwrite.actions.scale-io)
+ [专用日志卷（DLV）](#wait-event.iowalwrite.actions.dlv)

### 减少提交的数量
<a name="wait-event.iowalwrite.actions.problem"></a>

为了减少提交的数量，您可以将语句合并到事务数据块中。使用 Amazon RDS 性能详情来检查正在运行的查询类型。您也可以将大型维护操作移至非高峰时段。例如，在非生产时间创建索引或使用 `pg_repack` 操作。

### 监控您的检查点
<a name="wait-event.iowalwrite.actions.monitor"></a>

您可以监控两个参数，以查看 RDS for PostgreSQL 数据库实例对于检查点写入 WAL 文件的频率。
+ `log_checkpoints` –原定设置情况下，该参数为“on”。它会导致对于每个检查点向 PostgreSQL 日志发送一条消息。这些日志消息包括写入的缓冲区数量、写入缓冲区所花的时间以及针对给定检查点添加、删除或回收的 WAL 文件数。

  有关此参数的更多信息，请参阅 PostgreSQL 文档中的[错误报告和日志记录](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-CHECKPOINTS)。
+ `checkpoint_warning` – 此参数为检查点频率设置阈值（以秒为单位），超过该阈值将生成警告。原定设置情况下，不在 RDS for PostgreSQL 中设置此参数。您可以设置此参数的值，以便在 RDS for PostgreSQL 数据库实例中的数据库更改以 WAL 文件大小无法处理的速率写入时收到警告。例如，假设您将参数设置为 30。如果您的 RDS for PostgreSQL 实例需要写入更改的频率超过每 30 秒，则会向 PostgreSQL 日志发送“检查点出现频率过高”的警告。这可能表明应增加您的 `max_wal_size` 值。

  有关更多信息，请参阅 PostgreSQL 文档中的[预写日志](https://www.postgresql.org/docs/current/runtime-config-wal.html#RUNTIME-CONFIG-WAL-CHECKPOINTS)。

### 纵向扩展 IO
<a name="wait-event.iowalwrite.actions.scale-io"></a>

这种类型的输入/输出（IO）等待事件可以通过扩展每秒进行读写操作的次数（IOPS）以提供更快的 IO 来进行修复。扩展 IO 比扩展 CPU 更可取，因为扩展 CPU 会导致更多的 IO 争用，原因在于增加的 CPU 可以处理更多的工作，从而使 IO 瓶颈进一步恶化。一般情况下，建议在执行扩展操作之前优化您的工作负载。

### 专用日志卷（DLV）
<a name="wait-event.iowalwrite.actions.dlv"></a>

您可以利用 Amazon RDS 控制台、AWS CLI 或 Amazon RDS API，将专用日志卷（DLV）用于使用预调配 IOPS（PIOPS）存储的数据库实例。DLV 将 PostgreSQL 数据库事务日志移动到与包含数据库表的卷不同的存储卷中。有关更多信息，请参阅 [专用日志卷（DLV）](CHAP_Storage.md#CHAP_Storage.dlv)。

# IPC:并行等待事件
<a name="rpg-ipc-parallel"></a>

以下 `IPC:parallel wait events` 表明会话正在等待与并行查询执行操作相关的进程间通信。
+ `IPC:BgWorkerStartup`：进程正在等待并行工作进程完成其启动序列。在初始化工作线程以执行并行查询时会发生这种情况。
+ `IPC:BgWorkerShutdown`：进程正在等待并行工作进程完成其关闭序列。这发生在并行查询执行的清理阶段。
+ `IPC:ExecuteGather`：在查询执行期间，进程正在等待从并行工作进程接收数据。当领导进程需要从其工作线程中收集结果时，会发生这种情况。
+ `IPC:ParallelFinish`：进程正在等待并行工作线程完成其执行并报告其最终结果。这种情况发生在并行查询执行的完成阶段。

**Topics**
+ [支持的引擎版本](#rpg-ipc-parallel-context-supported)
+ [上下文](#rpg-ipc-parallel-context)
+ [等待次数增加的可能原因](#rpg-ipc-parallel-causes)
+ [操作](#rpg-ipc-parallel-actions)

## 支持的引擎版本
<a name="rpg-ipc-parallel-context-supported"></a>

Aurora PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="rpg-ipc-parallel-context"></a>

PostgreSQL 中的并行查询执行涉及多个进程协同工作以处理单个查询。当确定查询适合并行化时，领导进程会根据 `max_parallel_workers_per_gather` 参数设置与一个或多个并行工作进程进行协调。领导进程在各工作线程之间划分工作，每个工作线程独立处理自己的那部分数据，然后将结果收集回领导进程。

**注意**  
每个并行工作线程均作为一个单独的进程运行，其资源需求类似于完整的用户会话。这意味着，与非并行查询相比，具有 4 个工作线程的并行查询消耗的资源（CPU、内存、I/O 带宽）最多可达 5 倍，因为领导进程和每个工作进程都保持自己的资源分配。例如，诸如 `work_mem` 的设置单独应用于每个工作线程，可能会使所有进程的总内存使用量成倍增加。

并行查询架构由三个主要部分组成：
+ 领导进程：启动并行操作、划分工作负载并与工作进程进行协调的主进程。
+ 工作进程：并行执行查询各部分的后台进程。
+ 收集/收集合并：将来自多个工作进程的结果合并回领导进程的操作

在并行执行期间，进程需要通过进程间通信（IPC）机制相互通信。这些 IPC 等待事件发生在不同的阶段：
+ 工作线程启动：初始化并行工作线程时
+ 数据交换：当工作线程处理数据并将结果发送给领导进程时
+ 工作线程关闭：当并行执行完成且终止工作线程时
+ 同步点：当进程需要协调或等待其它进程完成其任务时

了解这些等待事件对于诊断与并行查询执行相关的性能问题至关重要，尤其是在可能同时执行多个并行查询的高并发环境中。

## 等待次数增加的可能原因
<a name="rpg-ipc-parallel-causes"></a>

有几个因素可能导致与并行相关的 IPC 等待事件增加：

**并行查询的高并发性**  
当多个并行查询同时运行时，可能会导致资源争用和 IPC 操作的等待时间增加。这在事务量或分析工作负载较高的系统中尤其常见。

**并行查询计划不够理想**  
如果查询计划器选择效率低下的并行计划，则可能会导致不必要的并行化或工作线程间的工作分配不佳。这可能会导致 IPC 等待增加，尤其是对于 `IPC:ExecuteGather` 和 `IPC:ParallelFinish` 事件。这些规划问题通常源于过时的统计数据和表/索引膨胀。

**并行工作线程频繁启动和关闭**  
频繁启动和终止并行工作线程的短期查询可能会导致 `IPC:BgWorkerStartup` 和 `IPC:BgWorkerShutdown` 事件增加。这种情况经常出现在具有许多小型可并行查询的 OLTP 工作负载中。

**资源约束**  
有限的 CPU、内存或 I/O 容量可能会导致并行执行出现瓶颈，从而导致所有 IPC 事件的等待时间增加。例如，如果 CPU 饱和，则工作进程可能需要更长的时间才能启动或处理自己的那部分工作。

**复杂的查询结构**  
具有多个并行性级别的查询（例如，并行联接后跟并行聚合）可能会导致更复杂的 IPC 模式并可能增加等待时间，尤其是对于 `IPC:ExecuteGather` 事件。

**大型结果集**  
生成大型结果集的查询可能会导致 `IPC:ExecuteGather` 等待时间增加，因为领导进程将花费更多的时间来收集和处理来自工作进程的结果。

了解这些因素有助于诊断和解决与 Aurora PostgreSQL 中的并行查询执行相关的性能问题。

## 操作
<a name="rpg-ipc-parallel-actions"></a>

当您看到与并行查询相关的等待时，这通常表示后端进程正在协调或等待并行工作进程。在执行并行计划期间，这些等待很常见。您可以通过监控并行工作线程使用情况、查看参数设置以及调整查询执行和资源分配，来调查并缓解这些等待的影响。

**Topics**
+ [分析查询计划是否存在并行性效率低下问题](#rpg-ipc-parallel-analyze-plans)
+ [监控并行查询使用情况](#rpg-ipc-parallel-monitor)
+ [查看和调整并行查询设置](#rpg-ipc-parallel-adjust-settings)
+ [优化资源分配](#rpg-ipc-parallel-optimize-resources)
+ [调查连接管理](#rpg-ipc-parallel-connection-management)
+ [查看和优化维护操作](#rpg-ipc-parallel-maintenance)

### 分析查询计划是否存在并行性效率低下问题
<a name="rpg-ipc-parallel-analyze-plans"></a>

并行查询执行可能经常导致系统不稳定、CPU 峰值和不可预测的查询性能变化。彻底分析并行性是否确实可以改善特定工作负载至关重要。使用 EXPLAIN ANALYZE 查看并行查询执行计划。

在会话级别暂时禁用并行性以比较计划效率：

```
SET max_parallel_workers_per_gather = 0;
EXPLAIN ANALYZE <your_query>;
```

重新启用并行性并进行比较：

```
RESET max_parallel_workers_per_gather;
EXPLAIN ANALYZE <your_query>;
```

如果禁用并行性会产生更好或更一致的结果，则考虑使用 SET 命令在会话级别为特定查询禁用并行性。为了获得更广泛的影响，您可能需要通过调整数据库参数组中的相关参数，来在实例级别禁用并行性。有关更多信息，请参阅 [在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。

### 监控并行查询使用情况
<a name="rpg-ipc-parallel-monitor"></a>

使用以下查询来深入了解并行查询活动和容量：

检查活动的并行工作进程：

```
SELECT
    COUNT(*)
FROM
    pg_stat_activity
WHERE
    backend_type = 'parallel worker';
```

此查询显示活动的并行工作进程的数量。较高的值可能表示为“max\$1parallel\$1workers”配置了较高的值，您可能需要考虑将其降低。

检查并发并行查询：

```
SELECT
    COUNT(DISTINCT leader_pid)
FROM
    pg_stat_activity
WHERE
    leader_pid IS NOT NULL;
```

此查询返回已启动并行查询的不同领导进程的数量。此处的数字较高表示多个会话正在并发运行并行查询，这可能会增加对 CPU 和内存的需求。

### 查看和调整并行查询设置
<a name="rpg-ipc-parallel-adjust-settings"></a>

查看以下参数以确保它们与您的工作负载一致：
+ `max_parallel_workers`：所有会话中并行工作线程的总数。
+ `max_parallel_workers_per_gather`：每个查询的最大工作线程数。

对于 OLAP 工作负载，增加这些值可以提高性能。对于 OLTP 工作负载，通常首选较低的值。

```
SHOW max_parallel_workers;
SHOW max_parallel_workers_per_gather;
```

### 优化资源分配
<a name="rpg-ipc-parallel-optimize-resources"></a>

监控 CPU 利用率，如果 vCPU 的数量一直很高，并且应用程序从并行查询中受益，请考虑调整 vCPU 的数量。确保有足够的内存可用于并行操作。
+ 使用性能详情指标来确定系统是否受到 CPU 限制。
+ 每个并行工作线程都使用自己的 `work_mem`。确保总内存使用量在实例限制范围内。

并行查询可能比非并行查询消耗的资源要多得多，因为每个工作进程都是一个完全独立的进程，它对系统的影响与额外的用户会话大致相同。在为此设置选择值时，以及在配置其它用于控制资源利用率的设置（例如 `work_mem`）时，应考虑到这一点。有关更多信息，请参阅 [PostgreSQL 文档](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM)。资源限制（例如 `work_mem`）单独应用于每个工作线程，这意味着跨所有进程的总利用率可能比针对任何单个进程的正常利用率高得多。

如果工作负载高度并行化，可以考虑增加 vCPU 数量或调整内存参数。

### 调查连接管理
<a name="rpg-ipc-parallel-connection-management"></a>

如果遇到连接耗尽的情况，请查看应用程序连接池策略。考虑在应用程序级别实现连接池（如果尚未使用）。

### 查看和优化维护操作
<a name="rpg-ipc-parallel-maintenance"></a>

协调索引创建和其它维护任务，以防止资源争用。考虑将这些操作安排在非高峰时段。避免在用户查询负载较高的时期安排繁重的维护工作（例如并行索引构建）。这些操作可能会消耗并行工作线程并影响常规查询的性能。

# IPC:ProcArrayGroupUpdate
<a name="apg-rpg-ipcprocarraygroup"></a>

当会话正等待组领导在操作结束时更新事务状态时，会发生 `IPC:ProcArrayGroupUpdate` 事件。虽然 PostgreSQL 通常将 IPC 类型的等待事件与并行查询操作相关联，但这个特定等待事件并非并行查询所特有。

**Topics**
+ [支持的引擎版本](#apg-rpg-ipcprocarraygroup.supported)
+ [上下文](#apg-rpg-ipcprocarraygroup.context)
+ [等待次数增加的可能原因](#apg-rpg-ipcprocarraygroup.causes)
+ [操作](#apg-rpg-ipcprocarraygroup.actions)

## 支持的引擎版本
<a name="apg-rpg-ipcprocarraygroup.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="apg-rpg-ipcprocarraygroup.context"></a>

**了解进程数组** – 进程（proc）数组是 PostgreSQL 中的共享内存结构。它包含有关所有正在运行的进程的信息，包括事务详细信息。在事务完成（`COMMIT` 或 `ROLLBACK`）期间，需要更新 ProcArray 以反映更改并从数组中清除 transactionID。尝试完成事务的会话必须在 ProcArray 上获得独占锁。这可以防止其他进程获得其共享或独占锁。

**组更新机制** – 在执行 COMMIT 或 ROLLBACK 时，如果后端进程无法在独占模式下获取 ProcArrayLock，它会更新一个名为 ProcArrayGroupMember 的特殊字段。这会将事务添加到打算结束的会话列表中。然后，此后端进程进入休眠状态，其休眠时间被记录为 ProcArrayGroupUpdate 等待事件。ProcArray 中具有 procArrayGroupMember 的第一个进程，称为领导进程，以独占模式获取 ProcArrayLock。然后，它会清除等待群组 transactionID 清除的进程列表。完成后，领导进程会释放 ProcArrayLock，然后唤醒此列表中的所有进程，通知它们其事务已完成。

## 等待次数增加的可能原因
<a name="apg-rpg-ipcprocarraygroup.causes"></a>

正在运行的进程越多，领导进程在独占模式下保持 procArrayLock 的时间就越长。因此，更多的写入事务会进入组更新场景，导致可能出现大量进程在 `ProcArrayGroupUpdate` 等待事件上排队等待。在数据库洞察的 Top SQL 视图中，您会看到 COMMIT 是该等待事件占比最多的语句。这是预期行为，但需要对正在运行的特定写入 SQL 进行更深入的调查，以确定要采取的适当措施。

## 操作
<a name="apg-rpg-ipcprocarraygroup.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。可以通过使用 Amazon RDS 性能详情或查询 PostgreSQL 系统视图 `pg_stat_activity` 来识别 `IPC:ProcArrayGroupUpdate` 事件。

**Topics**
+ [监控事务提交和回滚操作](#apg-rpg-ipcprocarraygroup.actions.monitor)
+ [减少并发性](#apg-rpg-ipcprocarraygroup.actions.concurrency)
+ [实施连接池](#apg-rpg-ipcprocarraygroup.actions.pooling)
+ [使用速度更快的存储](#apg-rpg-ipcprocarraygroup.actions.storage)

### 监控事务提交和回滚操作
<a name="apg-rpg-ipcprocarraygroup.actions.monitor"></a>

**监控提交和回滚** – 提交和回滚数量的增加可能会导致 ProcArray 承受的压力增加。例如，如果 SQL 语句由于重复键冲突增多而开始失败，您可能会看到回滚次数增加，这可能会增加 ProcArray 争用和表膨胀。

Amazon RDS 数据库洞察提供 PostgreSQL 指标 `xact_commit` 和 `xact_rollback` 以报告每秒的提交和回滚次数。

### 减少并发性
<a name="apg-rpg-ipcprocarraygroup.actions.concurrency"></a>

**批处理事务** – 尽可能在单个事务中进行批量操作，以减少提交/回滚操作。

**限制并发性** - 减少并发活跃事务的数量，以缓解 ProcArray 上的锁争用。虽然需要进行一些测试，但减少并发连接总数可以减少争用并维持吞吐量。

### 实施连接池
<a name="apg-rpg-ipcprocarraygroup.actions.pooling"></a>

**连接池解决方案** - 使用连接池来有效地管理数据库连接，从而减少后端的总数，进而减少 ProcArray 上的工作负载。虽然需要进行一些测试，但减少并发连接总数可以减少争用并维持吞吐量。

**减少连接风暴** – 同样，频繁创建和终止连接的模式会给 ProcArray 带来额外的压力。通过减少这种模式，可以减少总体争用。

### 使用速度更快的存储
<a name="apg-rpg-ipcprocarraygroup.actions.storage"></a>

**专用日志卷** – 如果 `IPC:ProcArrayGroupUpdate` 等待事件伴随着很多 `IO:WALWrite` 等待事件，则设置专用日志卷可以减少写入 WAL 的瓶颈。反过来，这会提高提交的性能。

有关更多信息，请参阅[专用日志卷](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PIOPS.dlv.html)。

# Lock:advisory
<a name="wait-event.lockadvisory"></a>

当 PostgreSQL 应用程序使用锁定来协调多个会话之间的活动时，会发生 `Lock:advisory` 事件。

**Topics**
+ [相关引擎版本](#wait-event.lockadvisory.context.supported)
+ [上下文](#wait-event.lockadvisory.context)
+ [原因](#wait-event.lockadvisory.causes)
+ [操作](#wait-event.lockadvisory.actions)

## 相关引擎版本
<a name="wait-event.lockadvisory.context.supported"></a>

此等待事件信息与 RDS for PostgreSQL 版本 9.6 及更高版本相关。

## 上下文
<a name="wait-event.lockadvisory.context"></a>

PostgreSQL 咨询锁是由用户的应用程序代码显式锁定和解锁的应用程序级别的合作锁。应用程序可以使用 PostgreSQL 咨询锁来协调多个会话之间的活动时。与常规锁、对象级锁或行级锁不同的是，应用程序对锁的生命周期拥有完全控制权。有关更多信息，请参阅 PostgreSQL 文档中的[咨询锁](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS)。

咨询锁可以在事务结束之前释放，也可以在事务中由会话持有。对于隐式的、系统强制的锁，例如 `CREATE INDEX` 语句获取的对表的互斥访问锁，情况并非如此。

有关用于获取（锁定）和释放（解锁）咨询锁的函数的说明，请参阅 PostgreSQL 文档中的[咨询锁函数](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS)。

咨询锁是在常规的 PostgreSQL 锁定系统之上实施的，并且在 `pg_locks` 系统视图中可见。

## 原因
<a name="wait-event.lockadvisory.causes"></a>

这种锁类型由显式使用它的应用程序完全控制。作为查询的一部分为每个行获取的咨询锁可能会导致锁激增或长期积累。

当以获得比查询返回的行更多的锁的方式运行查询时，会发生这些影响。应用程序最终必须释放每个锁，但是如果在未返回的行上获取锁，则应用程序无法找到所有锁。

以下示例来自 PostgreSQL 文档中的[咨询锁](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS)。

```
SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100;
```

在此示例中，`LIMIT` 子句只能在内部选择行并锁定其 ID 值后停止查询的输出。当数据量不断增长导致计划人员选择在开发过程中未测试的其他执行计划时，可能会突然发生这种情况。在这种情况下，由于应用程序会为锁定的每个 ID 值调用 `pg_advisory_unlock`，会发生累积。但是，在这种情况下，它找不到在未返回的行上获取的锁集合。由于锁是在会话级别获取的，因此它们不会在事务结束时自动释放。

阻止锁定尝试激增的另一个可能原因是意外的冲突。在这些冲突中，应用程序的不相关部分错误地共享了相同的锁 ID 空间。

## 操作
<a name="wait-event.lockadvisory.actions"></a>

查看应用程序对咨询锁的使用情况，并详细说明在应用程序流中获取和释放每种类型的咨询锁的位置和时间。

确定会话是获取太多锁定还是长时间运行的会话没有尽早释放锁，从而导致锁缓慢累积。您可以通过使用 `pg_terminate_backend(pid)` 结束会话来纠正会话级别锁定的缓慢累积。

正在等待咨询锁的客户端显示在带有 `wait_event_type=Lock` 和 `wait_event=advisory` 的 `pg_stat_activity` 中。您可以通过查询相同 `pid` 的 `pg_locks` 系统视图来获取特定的锁定值，以寻找 `locktype=advisory` 和 `granted=f`。

然后您可以通过查询具有 `granted=t` 的相同咨询锁的 `pg_locks` 来识别阻止的会话，如以下示例所示。

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED;
```

所有的咨询锁 API 函数都有两组参数，一个 `bigint` 参数或两个 `integer` 参数：
+ 对于具有一个 `bigint` 参数的 API 函数，上面的 32 位在 `pg_locks.classid` 中，下面的 32 位在 `pg_locks.objid` 中。
+ 对于具有两个 `integer` 参数的 API 函数，第一个参数是 `pg_locks.classid`，第二个参数是 `pg_locks.objid`。

`pg_locks.objsubid` 值表示使用了哪个 API 表单：`1` 表示一个 `bigint` 参数；`2` 表示两个 `integer` 参数。

# Lock:extend
<a name="wait-event.lockextend"></a>

当后端进程正在等待锁定关系以对其进行扩展，而另一个进程出于同样目的锁定该关系时，会发生 `Lock:extend` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.lockextend.context.supported)
+ [上下文](#wait-event.lockextend.context)
+ [等待次数增加的可能原因](#wait-event.lockextend.causes)
+ [操作](#wait-event.lockextend.actions)

## 支持的引擎版本
<a name="wait-event.lockextend.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.lockextend.context"></a>

事件 `Lock:extend` 表示后端进程正在等待扩展另一个后端进程在扩展该关系时保持锁定的关系。由于每次只有一个进程可以扩展关系，因此系统会生成 `Lock:extend` 等待事件。`INSERT`、`COPY` 和 `UPDATE` 操作可以生成此事件。

## 等待次数增加的可能原因
<a name="wait-event.lockextend.causes"></a>

当 `Lock:extend` 事件的发生率超过正常（可能表示性能问题）时，典型原因包括以下几点：

**对同一表的并发插入或更新激增 **  
插入或更新同一表的查询的并发会话数可能会增加。

**网络带宽不足**  
数据库实例上的网络带宽可能不足以满足当前工作负载的存储通信需求。这可能会导致存储延迟，从而导致 `Lock:extend` 事件增加。

## 操作
<a name="wait-event.lockextend.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [减少同一关系的并发插入和更新](#wait-event.lockextend.actions.action1)
+ [提高网络带宽](#wait-event.lockextend.actions.increase-network-bandwidth)

### 减少同一关系的并发插入和更新
<a name="wait-event.lockextend.actions.action1"></a>

首先，确定 `tup_inserted` 和 `tup_updated` 指标是否有增加，以及此等待事件是否伴随增加。如果是这样，请检查哪些关系在插入和更新操作中处于高争用状态。要确定这一点，请查询 `pg_stat_all_tables` 视图，以了解 `n_tup_ins` 和 `n_tup_upd` 字段中的值。有关 `pg_stat_all_tables` 视图的信息，请参阅 PostgreSQL 文档中的 [pg\$1stat\$1all\$1tables](https://www.postgresql.org/docs/13/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW)。

要获取有关正在阻止和已阻止的查询的更多信息，请如以下示例所示查询 `pg_stat_activity`：

```
SELECT
    blocked.pid,
    blocked.usename,
    blocked.query,
    blocking.pid AS blocking_id,
    blocking.query AS blocking_query,
    blocking.wait_event AS blocking_wait_event,
    blocking.wait_event_type AS blocking_wait_event_type
FROM pg_stat_activity AS blocked
JOIN pg_stat_activity AS blocking ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
where
blocked.wait_event = 'extend'
and blocked.wait_event_type = 'Lock';
 
   pid  | usename  |            query             | blocking_id |                         blocking_query                           | blocking_wait_event | blocking_wait_event_type
  ------+----------+------------------------------+-------------+------------------------------------------------------------------+---------------------+--------------------------
   7143 |  myuser  | insert into tab1 values (1); |        4600 | INSERT INTO tab1 (a) SELECT s FROM generate_series(1,1000000) s; | DataFileExtend      | IO
```

在您确定有助于增加 `Lock:extend` 事件的关系后，请使用以下方法来减少争用：
+ 查明是否可以使用分区来减少同一个表的争用。将插入或更新的元组分成不同的分区可以减少争用。有关分区的信息，请参阅 [使用 pg\$1partman 扩展管理 PostgreSQL 分区](PostgreSQL_Partitions.md)。
+ 如果等待事件主要是由于更新活动造成的，请考虑减少关系的 fillfactor 值。这可以减少更新期间对新数据块的请求。fillfactor 是表的存储参数，用于确定打包表页面的最大空间量。它表示为页面总空间的百分比。有关 fillfactor 参数的更多信息，请参阅 PostgreSQL 文档中的 [CREATE TABLE](https://www.postgresql.org/docs/13/sql-createtable.html)。
**重要**  
我们强烈建议您在更改 fillfactor 时测试系统，因为更改此值可能会对性能产生负面影响，这具体取决于您的工作负载。

### 提高网络带宽
<a name="wait-event.lockextend.actions.increase-network-bandwidth"></a>

要查看写入延迟是否增加，请检查 CloudWatch 中的 `WriteLatency` 指标。如果有，请使用 `WriteThroughput` 和 `ReadThroughput` Amazon CloudWatch 指标监控数据库实例上与存储相关的流量。这些指标可以帮助您确定网络带宽是否足以满足您的工作负载的存储活动。

如果您的网络带宽不够，请增加它。如果您的数据库实例已达到网络带宽限制，增加带宽的唯一方法是增加数据库实例大小。

有关 CloudWatch 指标的更多信息，请参阅[Amazon RDS 的 Amazon CloudWatch 实例级指标](rds-metrics.md#rds-cw-metrics-instance)。有关每个数据库实例类的网络性能的信息，请参阅 [Amazon RDS 的 Amazon CloudWatch 实例级指标](rds-metrics.md#rds-cw-metrics-instance)。

# Lock:Relation
<a name="wait-event.lockrelation"></a>

当查询等待获取当前被另一个事务锁定的表或视图（关系）上的锁定时，会发生 `Lock:Relation` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.lockrelation.context.supported)
+ [上下文](#wait-event.lockrelation.context)
+ [等待次数增加的可能原因](#wait-event.lockrelation.causes)
+ [操作](#wait-event.lockrelation.actions)

## 支持的引擎版本
<a name="wait-event.lockrelation.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.lockrelation.context"></a>

大多数 PostgreSQL 命令隐式使用锁来控制对表中数据的并发访问。您还可以通过 `LOCK` 命令在应用程序代码中显式使用这些锁。许多锁定模式彼此不兼容，它们可以在尝试访问同一对象时阻止事务。发生这种情况时，RDS for PostgreSQL 会生成一个 `Lock:Relation` 事件。以下是一些常见的示例：
+ `ACCESS EXCLUSIVE` 之类的独占锁可以阻止所有并发访问。数据定义语言 (DDL) 操作（例如 `DROP TABLE`、`TRUNCATE`、`VACUUM FULL` 和 `CLUSTER`）隐式获取 `ACCESS EXCLUSIVE` 锁定。`ACCESS EXCLUSIVE` 也是用于未显式指定模式的 `LOCK TABLE` 语句的原定设置锁定模式。
+ 在表上使用 `CREATE INDEX (without CONCURRENT)` 与数据操作语言 (DML) 语句 `UPDATE`、`DELETE` 和 `INSERT` 有冲突，这些语句可获取 `ROW EXCLUSIVE` 锁定。

有关表级锁和冲突锁模式的更多信息，请参阅 PostgreSQL 文档中的[显式锁定](https://www.postgresql.org/docs/13/explicit-locking.html)。

阻止查询和事务通常通过以下方式之一解锁阻止：
+ 阻止查询 – 应用程序可以取消查询或者用户可以结束该过程。引擎还可以因会话的语句超时或死锁检测机制而强制结束查询。
+ 阻止事务 – 事务在运行 `ROLLBACK` 或 `COMMIT` 语句时停止阻止。当会话被客户端或网络问题断开连接或结束时，也会自动发生回滚。当数据库引擎关闭、系统内存不足等时，可以结束会话。

## 等待次数增加的可能原因
<a name="wait-event.lockrelation.causes"></a>

当 `Lock:Relation` 事件的发生频率高于正常值时，可能表明存在性能问题。典型的原因包括：

**增加与表锁冲突的并发会话**  
用冲突锁定模式锁定相同表格的查询的并发会话数可能会增加。

**维护操作**  
`VACUUM` 和 `ANALYZE` 之类的运行状况维护操作可以显著增加冲突锁的数量。`VACUUM FULL` 获取 `ACCESS EXCLUSIVE` 锁，`ANALYSE` 获取 `SHARE UPDATE EXCLUSIVE`锁。这两种类型的锁都可能导致 `Lock:Relation` 等待事件。应用程序数据维护操作（例如刷新具体化视图）也可以增加阻止的查询和事务。

**读取器实例的锁定**  
写入器和读取器持有的关系锁之间可能存在冲突。目前，仅 `ACCESS EXCLUSIVE` 关系锁复制到读取器实例。但是，`ACCESS EXCLUSIVE` 关系锁将与读取器持有的任何 `ACCESS SHARE` 关系锁冲突。这可能会导致读取器上的锁定关系等待事件增加。

## 操作
<a name="wait-event.lockrelation.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [减少阻止 SQL 语句的影响](#wait-event.lockrelation.actions.reduce-blocks)
+ [尽量减少维护操作的影响](#wait-event.lockrelation.actions.maintenance)

### 减少阻止 SQL 语句的影响
<a name="wait-event.lockrelation.actions.reduce-blocks"></a>

为了减少阻止 SQL 语句的影响，请尽可能修改应用程序代码。以下是减少数据块的两种常见方法：
+ 使用 `NOWAIT` 选项 – 一些 SQL 命令，例如 `SELECT` 和 `LOCK` 语句，支持此选项。如果无法立即获取锁定，则 `NOWAIT` 指令将取消请求锁定的查询。这种方法可以帮助防止阻止会话导致其后面堆积阻止的会话。

  例如：假设事务 A 正在等待事务 B 所持有的锁定。现在，如果 B 请求对被事务 C 锁定的表进行锁，那么事务 A 可能会被阻止，直到事务 C 完成。但是，如果事务 B 在请求对 C 进行锁定时使用 `NOWAIT`，它可能会很快失败，并确保事务 A 不必无限期等待。
+ 使用 `SET lock_timeout` – 设置 `lock_timeout` 值，以限制 SQL 语句等待获取关系锁的时间。如果锁未在指定的超时内获取，则请求锁定的事务将被取消。在会话级别设置此值。

### 尽量减少维护操作的影响
<a name="wait-event.lockrelation.actions.maintenance"></a>

维护操作（例如 `VACUUM` 和 `ANALYZE`）非常重要。我们建议您不要将其关闭，因为您会找到与这些维护操作相关的 `Lock:Relation` 等待事件。以下方法可以最大限度地减少这些操作的影响：
+ 在非高峰时段手动运行维护操作。
+ 要减少由 Autovacuum 任务导致的 `Lock:Relation` 等待，执行任何需要的 Autovacuum 优化。有关优化 Autovacuum 的信息，请参阅《*Amazon RDS 用户指南*》中的[在 Amazon RDS 上使用 PostgreSQL Autovacuum](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)。

# Lock:transactionid
<a name="wait-event.locktransactionid"></a>

当事务正在等待行级锁定时，会发生 `Lock:transactionid` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.locktransactionid.context.supported)
+ [上下文](#wait-event.locktransactionid.context)
+ [等待次数增加的可能原因](#wait-event.locktransactionid.causes)
+ [操作](#wait-event.locktransactionid.actions)

## 支持的引擎版本
<a name="wait-event.locktransactionid.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.locktransactionid.context"></a>

当事务试图获取已被授予同时运行的事务的行级锁时，会发生事件 `Lock:transactionid`。显示 `Lock:transactionid` 等待事件的会话因此锁定被阻止。当阻止事务在 `COMMIT` 或 `ROLLBACK` 语句中结束后，被阻止的事务可以继续进行。

RDS for PostgreSQL 的多版本并发控制语义保证读取器不会阻止写入器，写入器也不会阻止读取器。为了发生行级冲突，正在阻止和已阻止的事务必须发出以下类型的冲突语句：
+ `UPDATE`
+ `SELECT … FOR UPDATE`
+ `SELECT … FOR KEY SHARE`

语句 `SELECT … FOR KEY SHARE` 是一种特殊情况。数据库使用子句 `FOR KEY SHARE` 以优化参照完整性的性能。一行上的行级锁定可以组织引用该行的其他表上的 `INSERT`、`UPDATE` 和 `DELETE` 命令。

## 等待次数增加的可能原因
<a name="wait-event.locktransactionid.causes"></a>

当此事件出现频率超过正常时，原因通常是 `UPDATE`、`SELECT … FOR UPDATE` 或 `SELECT … FOR KEY SHARE` 语句结合以下条件。

**Topics**
+ [高并发性](#wait-event.locktransactionid.concurrency)
+ [空闲事务](#wait-event.locktransactionid.idle)
+ [长时间运行的事务](#wait-event.locktransactionid.long-running)

### 高并发性
<a name="wait-event.locktransactionid.concurrency"></a>

RDS for PostgreSQL 可以使用细粒度的行级锁定语义。满足以下条件时，行级冲突的可能性会增加：
+ 高度并发的工作负载争用相同的行。
+ 并发性增加。

### 空闲事务
<a name="wait-event.locktransactionid.idle"></a>

有时，`pg_stat_activity.state` 列会显示值 `idle in transaction`。对于已开始事务但尚未发布 `COMMIT` 或 `ROLLBACK` 的会话，会显示此值。如果 `pg_stat_activity.state` 值不为 `active`，`pg_stat_activity` 中显示的查询是完成运行的最新版本。阻止会话没有主动处理查询，因为未完成的事务持有锁定。

如果空闲事务获得了行级锁，则可能会阻止其他会话获取它。这种情况导致等待事件 `Lock:transactionid` 频繁发生。要诊断问题，请检查来自的 `pg_stat_activity` 和 `pg_locks` 的输出。

### 长时间运行的事务
<a name="wait-event.locktransactionid.long-running"></a>

长时间运行的事务会获得很长一段时间的锁定。这些长期保留的锁定可以阻止其他事务运行。

## 操作
<a name="wait-event.locktransactionid.actions"></a>

行锁定是 `UPDATE`、`SELECT … FOR UPDATE` 或 `SELECT … FOR KEY SHARE` 语句之间发生的冲突。在尝试解决方案之前，请先了解这些语句何时在同一行上运行。使用此信息选择以下各部分所述的策略。

**Topics**
+ [响应高并发](#wait-event.locktransactionid.actions.problem)
+ [回应空闲事务](#wait-event.locktransactionid.actions.find-blocker)
+ [响应长期运行的事务](#wait-event.locktransactionid.actions.concurrency)

### 响应高并发
<a name="wait-event.locktransactionid.actions.problem"></a>

如果并发性是问题，请尝试以下方法之一：
+ 降低应用程序中的并发率。例如，减少活动会话的数量。
+ 实施连接池。要了解如何使用 RDS 代理进行池连接，请参阅 [Amazon RDS 代理](rds-proxy.md)。
+ 设计应用程序或数据模型以避免争用 `UPDATE` 和 `SELECT … FOR UPDATE` 语句。您还可以减少 `SELECT … FOR KEY SHARE` 语句访问的外键的数量。

### 回应空闲事务
<a name="wait-event.locktransactionid.actions.find-blocker"></a>

如果 `pg_stat_activity.state` 显示 `idle in transaction`，请使用以下策略：
+ 尽可能开启自动提交。这种方法可防止事务在等待 `COMMIT` 或 `ROLLBACK` 时阻止其他事务。
+ 搜索缺失 `COMMIT`、`ROLLBACK` 或 `END` 的代码路径。
+ 确保应用程序中的异常处理逻辑始终具有通向有效 `end of transaction` 的路径。
+ 确保您的应用程序在结束与`COMMIT` 或 `ROLLBACK` 的事务后处理查询结果。

### 响应长期运行的事务
<a name="wait-event.locktransactionid.actions.concurrency"></a>

如果长时间运行的事务导致频繁发生 `Lock:transactionid`，请尝试以下策略：
+ 在长时间运行的事务中保持行锁定。
+ 尽可能通过实现自动提交来限制查询的长度。

# Lock:tuple
<a name="wait-event.locktuple"></a>

在后端进程等待获取元组锁定时，会发生 `Lock:tuple` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.locktuple.context.supported)
+ [上下文](#wait-event.locktuple.context)
+ [等待次数增加的可能原因](#wait-event.locktuple.causes)
+ [操作](#wait-event.locktuple.actions)

## 支持的引擎版本
<a name="wait-event.locktuple.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.locktuple.context"></a>

事件 `Lock:tuple` 表示一个后端正在等待获取元组上的锁定，而另一个后端在同一个元组上保持冲突锁定。下表说明了会话生成 `Lock:tuple` 事件的场景。


|  时间  |  会话 1  |  会话 2  |  会话 3  | 
| --- | --- | --- | --- | 
|  t1  |  开始事务。  |    |    | 
|  t2  |  更新第 1 行。  |    |    | 
|  t3  |    |  更新第 1 行。会话获取元组上的独占锁定，然后等待会话 1 通过提交或回滚来释放锁。  |    | 
|  t4  |    |    |  更新第 1 行。会话等待会话 2 才能释放元组上的独占锁定。  | 

或者您可以使用基准测试工具 `pgbench` 来模拟此等待事件。配置大量并发会话以使用自定义 SQL 文件更新表中的同一行。

要了解冲突锁模式的更多信息，请参阅 PostgreSQL 文档中的[显式锁定](https://www.postgresql.org/docs/current/explicit-locking.html)。要了解有关 `pgbench` 的更多信息，请参阅 PostgreSQL 文档中的 [pgbench](https://www.postgresql.org/docs/current/pgbench.html)。

## 等待次数增加的可能原因
<a name="wait-event.locktuple.causes"></a>

当此事件的发生率超过正常（可能表示性能问题）时，典型原因包括以下几点：
+ 大量并发会话试图通过运行 `UPDATE` 或 `DELETE` 语句获取相同元组的冲突锁定。
+ 高度并发的会话正在使用 `FOR UPDATE` 或 `FOR NO KEY UPDATE` 锁定模式运行 `SELECT` 语句。
+ 各种因素促使应用程序或连接池打开更多会话以执行相同的操作。由于新会话正在尝试修改相同的行，数据库负载可能会激增，`Lock:tuple` 可以出现。

有关更多信息，请参阅 PostgreSQL 文档中的[行级锁定](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS)。

## 操作
<a name="wait-event.locktuple.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [调查应用程序逻辑](#wait-event.locktuple.actions.problem)
+ [查找阻止器会话](#wait-event.locktuple.actions.find-blocker)
+ [在并发性高时降低并发性](#wait-event.locktuple.actions.concurrency)
+ [排查瓶颈](#wait-event.locktuple.actions.bottlenecks)

### 调查应用程序逻辑
<a name="wait-event.locktuple.actions.problem"></a>

了解阻止器会话是否已经处于 `idle in transaction` 状态很长一段时间。如果是这样，请考虑结束阻止器会话，作为短期解决方案。您可以使用 `pg_terminate_backend` 函数。有关此函数的更多信息，请参阅 PostgreSQL 文档中的[服务器信号函数](https://www.postgresql.org/docs/13/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL)。

要获得长期解决方案，请执行以下操作：
+ 调整应用程序逻辑。
+ 使用 `idle_in_transaction_session_timeout` 参数。此参数可结束空闲时间超过指定时间的已打开事务的任何会话。有关更多信息，请参阅 PostgreSQL 文档中的[客户端连接原定设置](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT)。
+ 尽可能多地使用自动提交。有关更多信息，请参阅 PostgreSQL 文档中的 [SET AUTOCOMMIT](https://www.postgresql.org/docs/current/ecpg-sql-set-autocommit.html)。

### 查找阻止器会话
<a name="wait-event.locktuple.actions.find-blocker"></a>

在 `Lock:tuple` 等待事件发生时，通过找出哪些锁相互依赖来识别阻止器和已阻止的会话。有关更多信息，请参阅 PostgreSQL wiki 中的[锁定依赖项信息](https://wiki.postgresql.org/wiki/Lock_dependency_information)。

以下示例查询所有会话，并对 `tuple` 进行筛选，通过 `wait_time` 进行排序。

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED;
```

### 在并发性高时降低并发性
<a name="wait-event.locktuple.actions.concurrency"></a>

`Lock:tuple` 事件可能会不断发生，特别是在繁忙的工作负载时间。在这种情况下，考虑降低非常繁忙的行的高并发率。通常，只有几个行控制队列或布尔逻辑，这使得这些行非常繁忙。

您可以根据业务需求、应用程序逻辑和工作负载类型使用不同的方法来降低并发性。例如，您可以执行以下操作：
+ 重新设计表和数据逻辑以降低高并发性。
+ 更改应用程序逻辑以降低行级别的高并发性。
+ 使用行级锁定利用和重新设计查询。
+ 使用具有重试操作的 `NOWAIT` 子句。
+ 考虑使用乐观和混合锁定逻辑并发控制。
+ 考虑更改数据库隔离级别。

### 排查瓶颈
<a name="wait-event.locktuple.actions.bottlenecks"></a>

当出现诸如 CPU 匮乏或 Amazon EBS 带宽的最大使用率的瓶颈时，可能会发生 `Lock:tuple`。要减少瓶颈，请考虑以下方法：
+ 纵向扩展您的实例类类型。
+ 优化资源密集型查询。
+ 更改应用程序逻辑。
+ 存档很少访问的数据。

# LWLock:BufferMapping (LWLock:buffer\$1mapping)
<a name="wait-event.lwl-buffer-mapping"></a>

当会话正在等待将数据块与共享缓冲池中的缓冲区关联起来时，会发生此事件。

**注意**  
对于 RDS for PostgreSQL 版本 13 及更高版本，此事件命名为 `LWLock:BufferMapping`。对于 RDS for PostgreSQL 版本 12 及更旧版本，此事件命名为 `LWLock:buffer_mapping`。

**Topics**
+ [支持的引擎版本](#wait-event.lwl-buffer-mapping.context.supported)
+ [上下文](#wait-event.lwl-buffer-mapping.context)
+ [原因](#wait-event.lwl-buffer-mapping.causes)
+ [操作](#wait-event.lwl-buffer-mapping.actions)

## 支持的引擎版本
<a name="wait-event.lwl-buffer-mapping.context.supported"></a>

此等待事件信息与 RDS for PostgreSQL 版本 9.6 及更高版本相关。

## 上下文
<a name="wait-event.lwl-buffer-mapping.context"></a>

*共享缓冲池*是一个 PostgreSQL 内存区域，它包含进程现在正在使用或过去使用的所有页面。当进程需要页面时，它会将页面读入共享缓冲池中。`shared_buffers` 参数会设置共享缓冲区大小并保留一个内存区域来存储表和索引页。如果更改此参数，请确保重新启动数据库。

以下情况下回发生 `LWLock:buffer_mapping` 等待事件：
+ 进程在缓冲区表中搜索页面并获取共享缓冲区映射锁。
+ 进程将页面加载到缓冲池中并获取独占缓冲区映射锁。
+ 进程从缓冲池中删除页面并获取独占缓冲区映射锁。

## 原因
<a name="wait-event.lwl-buffer-mapping.causes"></a>

当此事件发生超过正常时（可能表示性能问题），数据库正在共享缓冲池中移入和移出分页。典型的原因包括：
+ 大型查询
+ 臃肿的索引和表
+ 完整的表扫描
+ 小于工作集的共享池大小

## 操作
<a name="wait-event.lwl-buffer-mapping.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。

**Topics**
+ [监控缓冲区相关的指标](#wait-event.lwl-buffer-mapping.actions.monitor-metrics)
+ [评估您的索引策略](#wait-event.lwl-buffer-mapping.actions.indexes)
+ [减少必须快速分配的缓冲区数量](#wait-event.lwl-buffer-mapping.actions.buffers)

### 监控缓冲区相关的指标
<a name="wait-event.lwl-buffer-mapping.actions.monitor-metrics"></a>

当 `LWLock:buffer_mapping` 等待激增时，调查缓冲区命中率。您可以使用这些指标更好地了解缓冲区缓存中发生的情况。检查以下指标：

`blks_hit`  
此性能详情计数器指标表示从共享缓冲池中检索的数据块的数量。当 `LWLock:buffer_mapping` 等待事件出现后，您可能会观察到 `blks_hit` 激增。

`blks_read`  
此性能详情计数器指标表示需要将输入/输出读入共享缓冲池的数据块的数量。您可能会在 `LWLock:buffer_mapping` 等待事件的前面观察到 `blks_read` 激增。

### 评估您的索引策略
<a name="wait-event.lwl-buffer-mapping.actions.indexes"></a>

要确认您的索引策略不会降低性能，请检查以下各项：

索引膨胀  
确保索引和表膨胀不会导致不必要的分页被读入共享缓冲区。如果表中包含未使用的行，请考虑存档数据并从表中删除这些行。然后，您可以为调整大小的表重建索引。

常用查询的索引  
要确定您是否拥有最佳索引，请在性能详情中监控数据库引擎指标。`tup_returned` 指标显示读取的行数。`tup_fetched` 指标显示返回到客户端的行数量。如果 `tup_returned` 明显大于 `tup_fetched`，可能无法正确编制数据索引。此外，您的表统计数据可能不是最新的。

### 减少必须快速分配的缓冲区数量
<a name="wait-event.lwl-buffer-mapping.actions.buffers"></a>

要减少 `LWLock:buffer_mapping` 等待事件，请尝试减少必须快速分配的缓冲区数量。一种策略是执行较小的批处理操作。通过对表进行分区，也许能够实现较小的批处理。

# LWLock:BufferIO (IPC:BufferIO)
<a name="wait-event.lwlockbufferio"></a>

当 RDS for PostgreSQL 正在等待其他进程在同时尝试访问页面的情况下完成输入/输出（I/O）操作时，会发生 `LWLock:BufferIO` 事件。它的目的是将同一个分页读入共享缓冲区中。

**Topics**
+ [相关引擎版本](#wait-event.lwlockbufferio.context.supported)
+ [上下文](#wait-event.lwlockbufferio.context)
+ [原因](#wait-event.lwlockbufferio.causes)
+ [操作](#wait-event.lwlockbufferio.actions)

## 相关引擎版本
<a name="wait-event.lwlockbufferio.context.supported"></a>

此等待事件信息与所有 RDS for PostgreSQL 版本相关。对于 RDS for PostgreSQL 12 及更早版本，此等待事件命名为 lwlock:buffer\$1io，而在 RDS for PostgreSQL 13 版本中，它命名为 lwlock:bufferio。从 RDS for PostgreSQL 14 版本开始，BufferIO 等待事件从 `LWLock` 移到 `IPC` 等待事件类型（IPC:BufferIO）。

## 上下文
<a name="wait-event.lwlockbufferio.context"></a>

每个共享缓冲区都有一个与 `LWLock:BufferIO` 等待事件相关的输入/输出锁，每次必须在共享缓冲池外检索数据块（或分页）。

此锁定用于处理多个会话，而这些会话都需要访问同一个数据块。必须从共享缓冲池外部读取此数据库块，该缓冲池由 `shared_buffers` 参数定义。

一旦在共享缓冲池内读取分页，`LWLock:BufferIO` 锁即被释放。

**注意**  
`LWLock:BufferIO` 等待事件发生在 [IO:DataFileRead](wait-event.iodatafileread.md) 等待事件之前。`IO:DataFileRead` 事件在从存储中读取数据时发生。

有关轻量级锁定的更多信息，请参阅[锁定概览](https://github.com/postgres/postgres/blob/65dc30ced64cd17f3800ff1b73ab1d358e92efd8/src/backend/storage/lmgr/README#L20)。

## 原因
<a name="wait-event.lwlockbufferio.causes"></a>

`LWLock:BufferIO` 显示在主要等待中的常见原因包括以下各项：
+ 多个后端或连接试图访问同样在等待输入/输出操作的同一页面
+ 共享缓冲池大小之间的比率（由 `shared_buffers` 参数定义）以及当前工作负载所需的缓冲区数量
+ 共享缓冲池的大小与其他操作移出的分页数量没有很好地平衡
+ 需要引擎在共享缓冲池中读取更多页面的臃肿的大索引
+ 缺乏强制数据库引擎从表中读取更多页面的索引
+ 检查点发生太频繁或需要刷新太多修改过的页面
+ 试图在同一页面上执行操作的数据库连接突增

## 操作
<a name="wait-event.lwlockbufferio.actions"></a>

根据等待事件的原因，我们建议采取不同的操作：
+ 观察 Amazon CloudWatch 指标，了解 `BufferCacheHitRatio` 突然减少和 `LWLock:BufferIO` 等待事件之间的关系。此影响可能意味着您有一个较小的共享缓冲区设置。您可能需要增加数据库实例类或对其进行纵向扩展。您可以将工作负载拆分为更多的读取器节点。
+ 如果您发现 `LWLock:BufferIO` 与 `BufferCacheHitRatio` 指标降低相一致，请根据您的工作负载峰值时间优化 `max_wal_size` 和 `checkpoint_timeout`。然后确定哪个查询可能会导致发生此情况。
+ 验证是否有未使用的索引，然后将其删除。
+ 使用分区表（也具有分区索引）。这样做有助于保持较低的指数重新排序并降低其影响。
+ 避免对列进行不必要的索引编制。
+ 使用连接池防止数据库连接突增。
+ 作为最佳实践，限制与数据库的最大连接数。

# LWLock:buffer\$1content (BufferContent)
<a name="wait-event.lwlockbuffercontent"></a>

当某个会话等待读取或写入内存中的某个数据页面，而另一个会话正锁定该页面以进行写入时，会发生 `LWLock:buffer_content` 事件。在 RDS for PostgreSQL 13 及更高版本中，此等待事件称为 `BufferContent`。

**Topics**
+ [支持的引擎版本](#wait-event.lwlockbuffercontent.context.supported)
+ [上下文](#wait-event.lwlockbuffercontent.context)
+ [等待次数增加的可能原因](#wait-event.lwlockbuffercontent.causes)
+ [操作](#wait-event.lwlockbuffercontent.actions)

## 支持的引擎版本
<a name="wait-event.lwlockbuffercontent.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.lwlockbuffercontent.context"></a>

要读取或操作数据，PostgreSQL 会通过共享内存缓冲区访问数据。要从缓冲区读取，进程会在共享模式下获取缓冲区内容的轻量级锁 (LWLock)。要写入缓冲区，它会在独占模式下获得该锁。共享锁允许其他进程同时获取对该内容的共享锁。独占锁可防止其他进程获取对该内容的任何类型的锁定。

`LWLock:buffer_content` (`BufferContent`) 事件表示多个进程试图获取对特定缓冲区的内容的锁定。

## 等待次数增加的可能原因
<a name="wait-event.lwlockbuffercontent.causes"></a>

当 `LWLock:buffer_content` (`BufferContent`) 事件的发生率超过正常（可能表示性能问题）时，典型原因包括以下几点：

**增加了对同一数据的并发更新**  
更新相同缓冲区内容的查询的并发会话数可能会增加。在具有大量索引的表中，这种争用可能更加明显。

**工作负载数据不在内存中**  
当活动工作负载正在处理的数据不在内存中时，这些等待事件可能会增加。这种影响是因为持有锁的进程可以在执行磁盘输入/输出操作时保持更长时间。

**过度使用外键约束**  
外键约束可能会增加进程在缓冲区内容锁上保留的时间。这种影响是因为读取操作需要在更新引用的键时对该键进行共享缓冲区内容锁定。

## 操作
<a name="wait-event.lwlockbuffercontent.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。您可以通过使用 Amazon RDS 性能详情或查询视图 `pg_stat_activity` 来识别 `LWLock:buffer_content` (`BufferContent`) 事件。

**Topics**
+ [提高内存中的效率](#wait-event.lwlockbuffercontent.actions.in-memory)
+ [减少对外键约束的使用](#wait-event.lwlockbuffercontent.actions.foreignkey)
+ [删除未使用的索引](#wait-event.lwlockbuffercontent.actions.indexes)
+ [使用序列时增加缓存大小](#wait-event.lwlockbuffercontent.actions.sequences)

### 提高内存中的效率
<a name="wait-event.lwlockbuffercontent.actions.in-memory"></a>

为了增加活动工作负载数据在内存中的可能性，请对表进行分区或纵向扩展您的实例类。有关数据库实例类的信息，请参阅 [数据库实例类](Concepts.DBInstanceClass.md)。

### 减少对外键约束的使用
<a name="wait-event.lwlockbuffercontent.actions.foreignkey"></a>

调查在使用外键约束时遇到大量`LWLock:buffer_content` (`BufferContent`) 等待事件的工作负载。删除不必要的外键约束。

### 删除未使用的索引
<a name="wait-event.lwlockbuffercontent.actions.indexes"></a>

对于遇到大量 `LWLock:buffer_content`(`BufferContent`) 等待事件的工作负载，识别未使用的索引并删除它们。

### 使用序列时增加缓存大小
<a name="wait-event.lwlockbuffercontent.actions.sequences"></a>

如果您的表使用序列，请增加缓存大小以消除序列页和索引页上的争用。每个序列都是共享内存中的单个页面。预定义缓存是对应于每个连接的。当许多并发会话获取序列值时，这可能不足以处理工作负载。

# LWLock:lock\$1manager (LWLock:lockmanager)
<a name="wait-event.lw-lock-manager"></a>

当 RDS for PostgreSQL 引擎维护共享锁的内存区域以便在无法使用快速路径锁时分配、检查和取消分配锁时，会发生此事件。

**Topics**
+ [支持的引擎版本](#wait-event.lw-lock-manager.context.supported)
+ [上下文](#wait-event.lw-lock-manager.context)
+ [等待次数增加的可能原因](#wait-event.lw-lock-manager.causes)
+ [操作](#wait-event.lw-lock-manager.actions)

## 支持的引擎版本
<a name="wait-event.lw-lock-manager.context.supported"></a>

此等待事件信息与 RDS for PostgreSQL 版本 9.6 及更高版本相关。对于早于版本 13 的 RDS for PostgreSQL 发行版，此等待事件的名称为 `LWLock:lock_manager`。对于 RDS for PostgreSQL 版本 13 及更高版本，此等待事件的名称为 `LWLock:lockmanager`。

## 上下文
<a name="wait-event.lw-lock-manager.context"></a>

发布 SQL 语句时，RDS for PostgreSQL 会记录锁，以在并发操作期间保护数据库的结构、数据和完整性。引擎可以使用快速路径锁或不快的路径锁来实现这个目标。不快的路径锁定更昂贵，并且比快速路径锁定造成的开销更大。

### 快速路径锁定
<a name="wait-event.lw-lock-manager.context.fast-path"></a>

为了减少频繁获取和释放但很少发生冲突的锁的开销，后端进程可以使用快速路径锁定。数据库对满足以下条件的锁定使用此机制：
+ 他们使用 DEFAULT 锁定方法。
+ 它们代表数据库关系的锁，而不是共享关系。
+ 它们是不太可能发生冲突的弱锁。
+ 引擎可以快速确认不可能存在发生冲突的锁。

在以下任一条件为真时，引擎无法使用快速路径锁定：
+ 锁不满足上述标准。
+ 没有更多的插槽可用于后端进程。

要优化查询以实现快速路径锁，可以使用以下查询。

```
SELECT count(*), pid, mode, fastpath
  FROM pg_locks
 WHERE fastpath IS NOT NULL
 GROUP BY 4,3,2
 ORDER BY pid, mode;
 count | pid  |      mode       | fastpath
-------+------+-----------------+----------
16 | 9185 | AccessShareLock | t
336 | 9185 | AccessShareLock | f
1 | 9185 | ExclusiveLock   | t
```

以下查询仅显示数据库中的总数。

```
SELECT count(*), mode, fastpath
  FROM pg_locks
 WHERE fastpath IS NOT NULL
 GROUP BY 3,2
 ORDER BY mode,1;
count |      mode       | fastpath
-------+-----------------+----------
16 | AccessShareLock | t
337 | AccessShareLock | f
1 | ExclusiveLock   | t
(3 rows)
```

有关快速路径锁定的更多信息，请参阅 PostgreSQL 锁管理器 README 中的[快速路径](https://github.com/postgres/postgres/blob/master/src/backend/storage/lmgr/README#L70-L76)和 PostgreSQL 文档中的 [pg-locks](https://www.postgresql.org/docs/9.3/view-pg-locks.html#AEN98195)。

### 锁管理器的扩缩问题示例
<a name="wait-event.lw-lock-manager.context.lock-manager"></a>

在此示例中，名为 `purchases` 的表存储五年的数据，按天进行分区。每个分区有两个索引。将发生以下一系列事件：

1. 您查询了许多天的数据，这需要数据库读取许多分区。

1. 数据库为每个分区创建一个锁条目。如果分区索引是优化程序访问路径的一部分，则数据库也会为它们创建一个锁条目。

1. 当同一后端进程请求的锁条目数大于 16 时（这是 `FP_LOCK_SLOTS_PER_BACKEND` 的值），锁管理器会使用非快速路径锁定方法。

现代应用程序可能有数百个会话。如果并发会话在没有适当的分区修剪的情况下查询父级数据库，则数据库可能会创建数百甚至数千个非快速路径锁。通常，当此并发性高于 vCPU 的数量时，会出现 `LWLock:lock_manager` 等待事件。

**注意**  
`LWLock:lock_manager` 等待事件与数据库架构中的分区或索引数量无关。相反，它与数据库必须控制的非快速路径锁的数量有关。

## 等待次数增加的可能原因
<a name="wait-event.lw-lock-manager.causes"></a>

当 `LWLock:lock_manager` 等待事件发生率超出正常（可能表明性能问题）时，突增的最可能原因如下：
+ 并发活动会话正在运行不使用快速路径锁的查询。这些会话还超出了最大 vCPU。
+ 大量并发活动会话正在访问严重分区的表。每个分区都有多个索引。
+ 数据库正在经历连接风暴。预设情况下，当数据库缓慢时，某些应用程序和连接池软件会创建更多连接。这种做法使问题变得更糟。优化连接池软件，以免发生连接风暴。
+ 大量会话在不修剪分区的情况下查询父级表。
+ 数据定义语言 (DDL)、数据操作语言 (DML) 或维护命令专门锁定经常访问或修改的繁忙关系或元组。

## 操作
<a name="wait-event.lw-lock-manager.actions"></a>

如果 `CPU` 等待事件发生，它不一定表示性能问题。仅当性能下降并且此等待事件主导了数据库负载时才响应此事件。

**Topics**
+ [使用分区修剪](#wait-event.lw-lock-manager.actions.pruning)
+ [删除不必要的索引](#wait-event.lw-lock-manager.actions.indexes)
+ [优化查询以实现快速路径锁定](#wait-event.lw-lock-manager.actions.tuning)
+ [优化其他等待事件](#wait-event.lw-lock-manager.actions.other-waits)
+ [减少硬件瓶颈](#wait-event.lw-lock-manager.actions.hw-bottlenecks)
+ [使用连接池程序。](#wait-event.lw-lock-manager.actions.pooler)
+ [升级您的 RDS for PostgreSQL 版本](#wait-event.lw-lock-manager.actions.pg-version)

### 使用分区修剪
<a name="wait-event.lw-lock-manager.actions.pruning"></a>

*分区修剪*是一种适用于声明性分区表的查询优化策略，它从表扫描中排除不需要的分区，从而提高性能。预设情况下，分区修剪处于开启状态。如果它已关闭，请按如下方式将其打开。

```
SET enable_partition_pruning = on;
```

查询可以在其 `WHERE` 子句包含用于分区的列时利用分区修建。有关更多信息，请参阅 PostgreSQL 文档中的[分区修建](https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITION-PRUNING)。

### 删除不必要的索引
<a name="wait-event.lw-lock-manager.actions.indexes"></a>

数据库可能包含未使用或很少使用的索引。如果是，请考虑删除它们。请执行以下任一操作：
+ 通过阅读 PostgreSQL wiki 中的[未使用索引](https://wiki.postgresql.org/wiki/Index_Maintenance#Unused_Indexes)了解如何查找不必要的索引。
+ 运行 PG 收集器。此 SQL 脚本会收集数据库信息并将其显示在整合的 HTML 报告中。检查“未使用的索引”部分。有关更多信息，请参阅 AWS Labs GitHub 存储库中的 [pg-collector](https://github.com/awslabs/pg-collector)。

### 优化查询以实现快速路径锁定
<a name="wait-event.lw-lock-manager.actions.tuning"></a>

要了解您的查询是否使用快速路径锁定，请查询 `pg_locks` 表中的 `fastpath` 列。如果您的查询没有使用快速路径锁定，请尝试将每个查询的关系数减少到 16 个以下。

### 优化其他等待事件
<a name="wait-event.lw-lock-manager.actions.other-waits"></a>

如果 `LWLock:lock_manager` 排在主要等待列表中的第一个或第二个，请检查列表中是否也显示了以下等待事件：
+ `Lock:Relation`
+ `Lock:transactionid`
+ `Lock:tuple`

如果前面的事件显示在列表的前面，请考虑首先优化这些等待事件。这些事件可以是 `LWLock:lock_manager` 的驱动因素。

### 减少硬件瓶颈
<a name="wait-event.lw-lock-manager.actions.hw-bottlenecks"></a>

您可能存在硬件瓶颈，例如 CPU 匮乏或 Amazon EBS 带宽的最大使用率。在这样的情况下，需考虑减少硬件瓶颈。请考虑以下操作：
+ 纵向扩展您的实例类。
+ 优化占用大量 CPU 和内存的查询。
+ 更改应用程序逻辑。
+ 将您的数据存档。

有关 CPU、内存和 EBS 网络带宽的更多信息，请参阅 [Amazon RDS 实例类型](https://aws.amazon.com/rds/instance-types/)。

### 使用连接池程序。
<a name="wait-event.lw-lock-manager.actions.pooler"></a>

如果您的活动连接总数超过最大 vCPU，则需要 CPU 的操作系统进程超过实例类型所能支持的数量。在这种情况下，需考虑使用或优化连接池。有关您的实例类型 vCPU 数量的更多信息，请参阅 [Amazon RDS 实例类型](https://aws.amazon.com/rds/instance-types/)。

有关为连接池的更多信息，请参阅以下资源：
+ [Amazon RDS 代理](rds-proxy.md)
+ [pgbouncer](http://www.pgbouncer.org/usage.html)
+ *PostgreSQL 文档*中的[连接池和数据源](https://www.postgresql.org/docs/7.4/jdbc-datasource.html)

### 升级您的 RDS for PostgreSQL 版本
<a name="wait-event.lw-lock-manager.actions.pg-version"></a>

如果您当前的 RDS for PostgreSQL 版本低于 12，请升级到版本 12 或更高版本。PostgreSQL 版本 12 及更高版本具有改进的分区机制。有关版本 12 的更多信息，请参阅 [PostgreSQL 12.0 发布说明]( https://www.postgresql.org/docs/release/12.0/)。有关升级 RDS for PostgreSQL 的更多信息，请参阅 [升级 RDS for PostgreSQL 数据库引擎](USER_UpgradeDBInstance.PostgreSQL.md)。

# LWLock:pg\$1stat\$1statements
<a name="apg-rpg-lwlockpgstat"></a>

当 `pg_stat_statements` 扩展对跟踪 SQL 语句的哈希表进行独占锁定时，就会发生 LWLock:pg\$1stat\$1statements 等待事件。如果存在以下情形，可能会发生这种情况：
+ 当跟踪的语句数量达到配置的 `pg_stat_statements.max` 参数值，并且需要为更多条目腾出空间时，此扩展会对调用次数执行排序，移除 5% 的执行次数最少的语句，然后用剩余的条目重新填充哈希表。
+ 当 `pg_stat_statements` 对磁盘上的 `pgss_query_texts.stat` 文件执行 `garbage collection` 操作并重新写入该文件时。

**Topics**
+ [支持的引擎版本](#apg-rpg-lwlockpgstat.supported)
+ [上下文](#apg-rpg-lwlockpgstat.context)
+ [等待次数增加的可能原因](#apg-rpg-lwlockpgstat.causes)
+ [操作](#apg-rpg-lwlockpgstat.actions)

## 支持的引擎版本
<a name="apg-rpg-lwlockpgstat.supported"></a>

 RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="apg-rpg-lwlockpgstat.context"></a>

**了解 pg\$1stat\$1statements 扩展**：pg\$1stat\$1statements 扩展在哈希表中跟踪 SQL 语句执行统计数据。该扩展可跟踪 SQL 语句，直至达到由 `pg_stat_statements.max` 参数定义的限制。此参数确定可以跟踪的最大语句数，该数量对应于 pg\$1stat\$1statements 视图中的最大行数。

**语句统计数据持久性**：该扩展通过以下方式，在实例重新启动时持久保留语句统计数据：
+ 将数据写入名为 pg\$1stat\$1statements.stat 的文件
+ 使用 pg\$1stat\$1statements.save 参数来控制持久行为

当 pg\$1stat\$1statements.save 设为以下设置时：
+ 开启（默认）：关闭时保存统计数据，并在服务器启动时重新加载它们
+ 关闭：既不会在服务器关闭时保存统计数据，也不会在服务器启动时重新加载它们

**查询文本存储**：该扩展将所跟踪的查询的文本存储在一个名为 `pgss_query_texts.stat` 的文件中。在进行垃圾回收之前，该文件可以增长到所有跟踪的 SQL 语句平均大小的两倍。该扩展需要在清理操作和重新写入 `pgss_query_texts.stat` 文件期间对哈希表实施独占锁定。

**语句取消分配流程**：当所跟踪语句的数量达到 `pg_stat_statements.max` 限制并且需要跟踪新的语句时，此扩展会：
+ 对哈希表实施独占锁定（LWLock:pg\$1stat\$1statements）。
+ 将现有数据加载到本地内存中。
+ 根据调用次数执行快速排序。
+ 移除调用次数最少的语句（底部 5%）。
+ 用剩余的条目重新填充哈希表。

**监控语句取消分配**：在 PostgreSQL 14 及更高版本中，可以使用 pg\$1stat\$1statements\$1info 视图来监控语句取消分配。此视图包括一个 dealloc 列，该列显示对语句取消分配来为新语句腾出空间的次数

如果频繁地对语句取消分配，则会导致更频繁地对磁盘上的 `pgss_query_texts.stat` 文件进行垃圾回收。

## 等待次数增加的可能原因
<a name="apg-rpg-lwlockpgstat.causes"></a>

`LWLock:pg_stat_statements` 等待次数增加的典型原因包括：
+ 应用程序使用的唯一查询的数量有所增加。
+ 与正在使用的唯一查询的数量相比，`pg_stat_statements.max` 参数值较小。

## 操作
<a name="apg-rpg-lwlockpgstat.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。可以通过使用 Amazon RDS 性能详情或查询视图 `pg_stat_activity` 来识别 `LWLock:pg_stat_statements` 事件。

调整以下 `pg_stat_statements` 参数，以控制跟踪行为并减少 LWLock:pg\$1stat\$1 statements 等待事件。

**Topics**
+ [禁用 pg\$1stat\$1statements.track 参数](#apg-rpg-lwlockpgstat.actions.disabletrack)
+ [提高 pg\$1stat\$1statements.max 参数的值](#apg-rpg-lwlockpgstat.actions.increasemax)
+ [禁用 pg\$1stat\$1statements.track\$1utility 参数](#apg-rpg-lwlockpgstat.actions.disableutility)

### 禁用 pg\$1stat\$1statements.track 参数
<a name="apg-rpg-lwlockpgstat.actions.disabletrack"></a>

如果 LWLock:pg\$1stat\$1statements 等待事件对数据库性能产生不利影响，并且在进一步分析 `pg_stat_statements` 视图以确定根本原因之前需要快速的解决方案，则可以通过将 `pg_stat_statements.track` 参数设置为 `none` 来禁用该参数。这将禁用对语句统计数据的回收。

### 提高 pg\$1stat\$1statements.max 参数的值
<a name="apg-rpg-lwlockpgstat.actions.increasemax"></a>

要减少取消分配并最大限度地减少磁盘上 `pgss_query_texts.stat` 文件的垃圾回收，请提高 `pg_stat_statements.max` 参数的值。默认值为 `5,000`。

**注意**  
`pg_stat_statements.max` 参数为静态参数。必须重新启动数据库实例，才能应用对此参数的任何更改。

### 禁用 pg\$1stat\$1statements.track\$1utility 参数
<a name="apg-rpg-lwlockpgstat.actions.disableutility"></a>

您可以分析 pg\$1stat\$1statements 视图，以确定哪些实用程序命令正在消耗由 `pg_stat_statements` 跟踪的大部分资源。

`pg_stat_statements.track_utility` 参数控制模块是否跟踪实用程序命令，包括除 SELECT、INSERT、UPDATE、DELETE 和 MERGE 之外的所有命令。默认情况下，此参数设置为 `on`。

例如，当应用程序使用许多本质上为唯一的保存点查询时，它可能会增加语句取消分配。要解决此问题，您可以禁用 `pg_stat_statements.track_utility` 参数以停止 `pg_stat_statements` 跟踪保存点查询。

**注意**  
`pg_stat_statements.track_utility` 参数是一个动态参数。无需重新启动数据库实例即可更改其值。

**Example pg\$1stat\$1statements 中的唯一保存点查询示例**  <a name="savepoint-queries"></a>

```
                     query                       |       queryid       
-------------------------------------------------+---------------------
 SAVEPOINT JDBC_SAVEPOINT_495701                 | -7249565344517699703
 SAVEPOINT JDBC_SAVEPOINT_1320                   | -1572997038849006629
 SAVEPOINT JDBC_SAVEPOINT_26739                  |  54791337410474486
 SAVEPOINT JDBC_SAVEPOINT_1294466                |  8170064357463507593
 ROLLBACK TO SAVEPOINT JDBC_SAVEPOINT_65016      | -33608214779996400
 SAVEPOINT JDBC_SAVEPOINT_14185                  | -2175035613806809562
 SAVEPOINT JDBC_SAVEPOINT_45837                  | -6201592986750645383
 SAVEPOINT JDBC_SAVEPOINT_1324                   |  6388797791882029332
```

PostgreSQL 17 引入了多项增强功能来进行实用程序命令跟踪：
+ 保存点名称现在显示为常量。
+ 现在，两阶段提交命令的全局事务 ID（GID）显示为常量。
+ DEALLOCATE 语句的名称显示为常量。
+ CALL 参数现在显示为常量。

# LWLock:SubtransSLRU (LWLock:SubtransControlLock)
<a name="wait-event.lwlocksubtransslru"></a>

`LWLock:SubtransSLRU` 和 `LWLock:SubtransBuffer` 等待事件表示某个会话正在等待访问用于子事务信息的简单最近最少使用（SLRU）缓存。在确定事务可见性和父子关系时会发生这种情况。
+ `LWLock:SubtransSLRU`：某个进程正在等待访问子事务的最近使用最少的（SLRU）简单缓存。在 RDS for PostgreSQL 版本 13 之前，此等待事件称为 `SubtransControlLock`。
+ `LWLock:SubtransBuffer`：某个进程正在等待子事务的最近使用最少的（SLRU）简单缓冲区上的输入/输出。在 RDS for PostgreSQL 版本 13 之前，此等待事件称为 `subtrans`。

**Topics**
+ [支持的引擎版本](#wait-event.lwlocksubtransslru.supported)
+ [上下文](#wait-event.lwlocksubtransslru.context)
+ [等待次数增加的可能原因](#wait-event.lwlocksubtransslru.causes)
+ [操作](#wait-event.lwlocksubtransslru.actions)

## 支持的引擎版本
<a name="wait-event.lwlocksubtransslru.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.lwlocksubtransslru.context"></a>

**了解子事务** – 在 PostgreSQL 中，子事务是事务中的事务。它也称为嵌套事务。

子事务通常是在您使用以下内容时创建的：
+ `SAVEPOINT` 命令
+ 异常块（`BEGIN/EXCEPTION/END`）

子事务允许您在不影响整个事务的情况下回滚部分事务。这样就对事务管理提供了精细控制。

**实现细节** – PostgreSQL 将子事务实现为主事务中的嵌套结构。每个子事务都有自己的事务 ID。

关键实施方面：
+ 事务 ID 在 `pg_xact` 中进行跟踪
+ 父子关系存储在 `PGDATA` 下的 `pg_subtrans` 子目录中
+ 每个数据库会话最多可以维护 `64` 个处于活跃状态的子事务
+ 超过此限制会导致子事务溢出，从而需要访问用于子事务信息的简单最近最少使用（SLRU）缓存

## 等待次数增加的可能原因
<a name="wait-event.lwlocksubtransslru.causes"></a>

子事务 SLRU 争用的常见原因包括：
+ **过度使用 SAVEPOINT 和 EXCEPTION 处理** – 无论是否发生异常，带有 `EXCEPTION` 处理程序的 PL/pgSQL 过程都会自动创建隐式保存点。每个 `SAVEPOINT` 都会启动一个新的子事务。当单个事务累积超过 64 个子事务时，它会触发子事务 SLRU 溢出。
+ **驱动程序和 ORM 配置** – `SAVEPOINT` 使用方式可以在应用程序代码中显式指定，也可以通过驱动程序配置隐式生效。许多常用的 ORM 工具和应用程序框架本身都支持嵌套事务。下面是一些常见的示例：
  + 如果将 JDBC 驱动程序参数 `autosave` 设置为 `always` 或 `conservative`，则会在每次查询之前生成保存点。
  + 当设置为 `propagation_nested` 时，为 Spring Framework 事务定义。
  + 设置 `requires_new: true` 时为 Rails。
  + 使用 `session.begin_nested` 时为 SQLAlchemy。
  + 使用嵌套 `atomic()` 块时为 Django。
  + 使用 `Savepoint` 时为 GORM。
  + 当回滚级别设置设为语句级回滚（例如 `PROTOCOL=7.4-2`）时，为 psqlODBC。
+ **具有长时间运行的事务和子事务的高并发工作负载** – 当在高并发工作负载以及长时间运行的事务和子事务期间发生子事务 SLRU 溢出时，PostgreSQL 会遇到更多的争用。这表现为 `LWLock:SubtransBuffer` 和 `LWLock:SubtransSLRU` 锁的等待事件时间较长。

## 操作
<a name="wait-event.lwlocksubtransslru.actions"></a>

根据等待事件的原因，我们建议采取不同的操作。有些操作可以立即提供缓解措施，而另一些则需要调查和长期纠正。

**Topics**
+ [监控子事务使用情况](#wait-event.lwlocksubtransslru.actions.monitor)
+ [配置内存参数](#wait-event.lwlocksubtransslru.actions.memory)
+ [长期操作](#wait-event.lwlocksubtransslru.actions.longterm)

### 监控子事务使用情况
<a name="wait-event.lwlocksubtransslru.actions.monitor"></a>

对于 PostgreSQL 版本 16.1 及更高版本，使用以下查询来监控每个后端的子事务计数和溢出状态。此查询将后端统计数据与活动信息联接起来，以显示哪些进程正在使用子事务：

```
SELECT a.pid, usename, query, state, wait_event_type,
       wait_event, subxact_count, subxact_overflowed
FROM (SELECT id, pg_stat_get_backend_pid(id) pid, subxact_count, subxact_overflowed
      FROM pg_stat_get_backend_idset() id
           JOIN LATERAL pg_stat_get_backend_subxact(id) AS s ON true
     ) a
JOIN pg_stat_activity b ON a.pid = b.pid;
```

对于 PostgreSQL 版本 13.3 及更高版本，请监控 `pg_stat_slru` 视图中的子事务缓存压力。以下 SQL 会查询检索 Subtrans 组件的 SLRU 缓存统计信息：

```
SELECT * FROM pg_stat_slru WHERE name = 'Subtrans';
```

`blks_read` 值持续增加表示未缓存的子事务经常访问磁盘，这表明潜在的 SLRU 缓存压力很大。

### 配置内存参数
<a name="wait-event.lwlocksubtransslru.actions.memory"></a>

对于 PostgreSQL 17.1 及更高版本，您可以使用 `subtransaction_buffers` 参数配置子事务 SLRU 缓存大小。以下配置示例演示如何设置子事务缓冲区参数：

```
subtransaction_buffers = 128
```

此参数指定用于缓存子事务内容（`pg_subtrans`）的共享内存量。如果不带单位指定，则该值表示 `BLCKSZ` 字节的块，通常每个块 8KB。例如，将该值设置为 128 会为子事务缓存分配 1MB（128 \$1 8KB）的内存。

**注意**  
可以在集群级别设置此参数，以使所有实例保持一致。测试和调整该值，使其最适合您的特定工作负载要求和实例类。必须重启写入器实例才能使参数更改生效。

### 长期操作
<a name="wait-event.lwlocksubtransslru.actions.longterm"></a>
+ **检查应用程序代码和配置** - 查看您的应用程序代码和数据库驱动程序配置，了解显式和隐式 `SAVEPOINT` 用法以及子事务的总体使用情况。识别可能生成超过 64 个子事务的事务。
+ **减少保存点使用量** – 尽量在事务中少用保存点：
  + 检查带有 EXCEPTION 块的 PL/pgSQL 过程和函数。EXCEPTION 块会自动创建隐式保存点，这可能会导致子事务溢出。每个 EXCEPTION 子句都会创建一个子事务，无论在执行过程中是否实际发生异常。  
**Example**  

    示例 1：EXCEPTION 块使用有问题

    以下代码示例演示了创建多个子事务的有问题 EXCEPTION 块用法：

    ```
    CREATE OR REPLACE FUNCTION process_user_data()
    RETURNS void AS $$
    DECLARE
        user_record RECORD;
    BEGIN
        FOR user_record IN SELECT * FROM users LOOP
            BEGIN
                -- This creates a subtransaction for each iteration
                INSERT INTO user_audit (user_id, action, timestamp)
                VALUES (user_record.id, 'processed', NOW());
                
                UPDATE users 
                SET last_processed = NOW() 
                WHERE id = user_record.id;
                
            EXCEPTION
                WHEN unique_violation THEN
                    -- Handle duplicate audit entries
                    UPDATE user_audit 
                    SET timestamp = NOW() 
                    WHERE user_id = user_record.id AND action = 'processed';
            END;
        END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    ```

    以下经过改进的代码示例通过使用 UPSERT 代替异常处理来减少子事务的使用量：

    ```
    CREATE OR REPLACE FUNCTION process_user_data()
    RETURNS void AS $$
    DECLARE
        user_record RECORD;
    BEGIN
        FOR user_record IN SELECT * FROM users LOOP
            -- Use UPSERT to avoid exception handling
            INSERT INTO user_audit (user_id, action, timestamp)
            VALUES (user_record.id, 'processed', NOW())
            ON CONFLICT (user_id, action) 
            DO UPDATE SET timestamp = NOW();
            
            UPDATE users 
            SET last_processed = NOW() 
            WHERE id = user_record.id;
        END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    ```  
**Example**  

    示例 2：STRICT 异常处理程序

    以下代码示例演示了使用 NO\$1DATA\$1FOUND 时存在问题的 EXCEPTION 处理方式：

    ```
    CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER)
    RETURNS TEXT AS $$
    DECLARE
        user_email TEXT;
    BEGIN
        BEGIN
            -- STRICT causes an exception if no rows or multiple rows found
            SELECT email INTO STRICT user_email 
            FROM users 
            WHERE id = p_user_id;
            
            RETURN user_email;
            
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN 'Email not found';
        END;
    END;
    $$ LANGUAGE plpgsql;
    ```

    以下经过改进的代码示例通过使用 IF NOT FOUND 代替异常处理来避免子事务：

    ```
    CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER)
    RETURNS TEXT AS $$
    DECLARE
        user_email TEXT;
    BEGIN
         SELECT email INTO user_email 
         FROM users 
         WHERE id = p_user_id;
            
         IF NOT FOUND THEN
             RETURN 'Email not found';
         ELSE
             RETURN user_email;
         END IF;
    END;
    $$ LANGUAGE plpgsql;
    ```
  + JDBC 驱动程序 - 如果 `autosave` 参数设置为 `always` 或 `conservative`，则会在每次查询之前生成保存点。评估您的应用程序是否可以接受 `never` 设置。
  + PostgreSQL ODBC 驱动程序（psqlODBC）– 回滚级别设置（用于语句级回滚）创建隐式保存点以启用语句回滚功能。评估您的应用程序是否可以接受事务级别的回滚或不进行回滚。
  + 检查 ORM 事务配置
  + 考虑不需要保存点的替代错误处理策略
+ **优化事务设计** – 重组事务以避免过度嵌套，并降低出现子事务溢出情况的可能性。
+ **减少长时间运行的事务** – 长时间运行的事务会因为更长时间地保留子事务信息而加剧子事务问题。监控性能详情指标并将 `idle_in_transaction_session_timeout` 参数配置为自动终止空闲事务。
+ 监控性能详情指标 – 跟踪包括 `idle_in_transaction_count`（处于空闲事务状态的会话数）和 `idle_in_transaction_max_time`（运行时间最长的空闲事务持续时间）在内的指标，以检测长时间运行的事务。
+ 配置 `idle_in_transaction_session_timeout` - 在参数组中设置此参数，以便在指定持续时间后自动终止空闲事务。
+ 主动监控 – 监控 `LWLock:SubtransBuffer` 和 `LWLock:SubtransSLRU` 等待事件的高发生率，以在与子事务相关的争用变得严重之前将其检测出来。

# Timeout:PgSleep
<a name="wait-event.timeoutpgsleep"></a>

当服务器进程调用 `pg_sleep` 函数并且等待睡眠超时过期时，会发生 `Timeout:PgSleep` 事件。

**Topics**
+ [支持的引擎版本](#wait-event.timeoutpgsleep.context.supported)
+ [等待次数增加的可能原因](#wait-event.timeoutpgsleep.causes)
+ [操作](#wait-event.timeoutpgsleep.actions)

## 支持的引擎版本
<a name="wait-event.timeoutpgsleep.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 等待次数增加的可能原因
<a name="wait-event.timeoutpgsleep.causes"></a>

当应用程序、存储函数或用户发出调用以下函数之一的 SQL 语句时，会发生此等待事件：
+ `pg_sleep`
+ `pg_sleep_for`
+ `pg_sleep_until`

前面的函数会延迟执行，直到经过指定的秒数为止。例如，`SELECT pg_sleep(1)` 暂停 1 秒。有关更多信息，请参阅 PostgreSQL 文档中的[延迟执行](https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-DELAY)。

## 操作
<a name="wait-event.timeoutpgsleep.actions"></a>

确定正在运行 `pg_sleep` 函数的语句。确定使用该功能是否合适。

# Timeout:VacuumDelay
<a name="wait-event.timeoutvacuumdelay"></a>

`Timeout:VacuumDelay` 事件表明已超过 vacuum 输入输出的成本限制，vacuum 进程已进入休眠状态。vacuum 操作在相应的成本延迟参数中指定的持续时间内停止，然后恢复工作。对于手动 vacuum 命令，延迟在 `vacuum_cost_delay` 参数中指定。对于 autovacuum 进程守护程序，延迟在 `autovacuum_vacuum_cost_delay parameter.` 中指定。

**Topics**
+ [支持的引擎版本](#wait-event.timeoutvacuumdelay.context.supported)
+ [上下文](#wait-event.timeoutvacuumdelay.context)
+ [等待次数增加的可能原因](#wait-event.timeoutvacuumdelay.causes)
+ [操作](#wait-event.timeoutvacuumdelay.actions)

## 支持的引擎版本
<a name="wait-event.timeoutvacuumdelay.context.supported"></a>

RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文
<a name="wait-event.timeoutvacuumdelay.context"></a>

PostgreSQL 既有 autovacuum 进程守护程序，也有手动 vacuum 命令。RDS for PostgreSQL 数据库实例的 autovacuum 进程原定设置为“on”。手动 vacuum 命令可根据需要使用，例如，用于清除不活动元组表或生成新的统计数据。

在执行 vacuum 操作时，PostgreSQL 在系统执行各种输入输出操作时使用内部计数器来跟踪估计成本。当计数器达到由成本限制参数指定的值时，执行操作的进程将在成本延迟参数中指定的短暂持续时间内休眠。然后，它重置计数器并继续操作。

vacuum 进程具有可用于调节资源消耗的参数。autovacuum 和手动 vacuum 命令有自己的参数来设置成本限制值。它们也有自己的参数来指定成本延迟，即达到极限时让 vacuum 进入休眠状态的时间量。通过这种方式，成本延迟参数可以作为资源消耗的限制机制。在下面的列表中，您可以找到这些参数的说明。

**影响 autovacuum 进程守护程序限制的参数**
+ `[autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)` – 指定要在自动 vacuum 操作中使用的成本限制值。增加此参数的设置可使 Vacuum 进程使用更多资源并减少 `Timeout:VacuumDelay` 等待事件。
+ `[autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)` – 指定要在自动 vacuum 操作中使用的成本延迟值。原定设置值为 2 毫秒。将延迟参数设置为 0 会关闭限制机制，因此，不会出现 `Timeout:VacuumDelay` 等待事件。

有关更多信息，请参阅 PostgreSQL 文档中的 [Automatic Vacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)。

**影响限制手动 vacuum 进程的参数**
+ `vacuum_cost_limit` – vacuum 进程进入休眠状态的阈值。原定设置情况下，此限制为 200。此数字表示各种资源所需的额外输入输出的累计成本估计值。增加此值会减少 `Timeout:VacuumDelay` 等待事件的数量。
+ `vacuum_cost_delay` – 达到 vacuum 成本限制时 vacuum 进程休眠的时间量。原定设置为 0，这意味着此功能关闭。您可以将其设置为整数值以指定开启此功能的毫秒数，但我们建议您将其保留为原定设置。

有关 `vacuum_cost_delay` 参数的更多信息，请参阅 PostgreSQL 文档中的[资源消耗量](https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST)。

要了解有关如何在 RDS for PostgreSQL 中配置和使用 autovacuum 的更多信息，请参阅 [在 Amazon RDS for PostgreSQL 上使用 PostgreSQL autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md)。

## 等待次数增加的可能原因
<a name="wait-event.timeoutvacuumdelay.causes"></a>

`Timeout:VacuumDelay` 受成本限制参数设置（`vacuum_cost_limit`、`autovacuum_vacuum_cost_limit`）与控制 vacuum 的休眠持续时间的成本延迟参数（`vacuum_cost_delay`、`autovacuum_vacuum_cost_delay`）之间平衡的影响。提高成本限制参数值允许 vacuum 在进入休眠状态之前使用更多资源。这样可以减少 `Timeout:VacuumDelay` 等待事件。增加任一延迟参数都会使 `Timeout:VacuumDelay` 等待事件发生的频率更高且持续的时间更长。

`autovacuum_max_workers` 参数设置还可以增加 `Timeout:VacuumDelay` 的数量。每个额外的 autovacuum 工作进程都有助于内部计数器机制，因此，与单个 autovacuum 工作进程相比，可以更快地达到限制。随着更快地达到成本限制，成本延迟会更频繁地生效，从而导致更多的 `Timeout:VacuumDelay` 等待事件。有关更多信息，请参阅 PostgreSQL 文档中的 [autovacuum\$1max\$1workers](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MAX-WORKERS)。

大型对象（如 500GB 或更大）也会引发此等待事件，因为 vacuum 可能需要一些时间才能完成处理大型对象。

## 操作
<a name="wait-event.timeoutvacuumdelay.actions"></a>

如果 vacuum 操作按预期完成，则无需补救。换句话说，此等待事件不一定表示有问题。它表示 vacuum 在延迟参数中指定的时间段内进入休眠状态，以便可以将资源应用于需要完成的其他进程。

如果您希望更快地完成 vacuum 操作，可以降低延迟参数。这可缩短 vacuum 休眠的时间。

# 使用 Amazon DevOps Guru 主动见解优化 RDS for PostgreSQL
<a name="PostgreSQL.Tuning_proactive_insights"></a>

DevOps Guru 主动见解可检测 RDS for PostgreSQL 数据库实例上可能导致问题的情况，并在问题发生之前告知您。主动的洞察可以提醒您具有长时间运行的事务空闲连接。有关排查长时间运行的事务空闲连接的更多信息，请参阅[数据库具有长时间运行的事务空闲连接](#proactive-insights.idle-txn)。

DevOps Guru 可以执行以下操作：
+ 通过对照常见的建议设置交叉检查数据库配置，可以防止许多常见的数据库问题。
+ 提醒您注意实例集中的关键问题，如果不加以检查，以后可能会导致更大的问题。
+ 提醒您注意新发现的问题。

每项主动见解都包含对问题原因的分析和纠正措施建议。

有关适用于 Amazon RDS 的 Amazon DevOps Guru 的更多信息，请参阅[使用适用于 Amazon RDS 的 Amazon DevOps Guru 分析性能异常](devops-guru-for-rds.md)。

## 数据库具有长时间运行的事务空闲连接
<a name="proactive-insights.idle-txn"></a>

与数据库的连接处于 `idle in transaction` 状态的时间已超过 1800 秒。

**Topics**
+ [支持的引擎版本](#proactive-insights.idle-txn.context.supported)
+ [上下文](#proactive-insights.idle-txn.context)
+ [这个问题的可能原因](#proactive-insights.idle-txn.causes)
+ [操作](#proactive-insights.idle-txn.actions)
+ [相关指标](#proactive-insights.idle-txn.metrics)

### 支持的引擎版本
<a name="proactive-insights.idle-txn.context.supported"></a>

RDS for PostgreSQL 的所有版本都支持此见解信息。

### 上下文
<a name="proactive-insights.idle-txn.context"></a>

处于 `idle in transaction` 状态的事务可能持有旨在阻止其他查询的锁。它还可以防止 `VACUUM`（包括 autovaum）清理死行，从而导致索引或表膨胀或事务 ID 重叠。

### 这个问题的可能原因
<a name="proactive-insights.idle-txn.causes"></a>

在使用 BEGIN 或 START TRANSATION 的交互式会话中启动的事务尚未通过使用 COMMIT、ROLLBACK 或 END 命令结束。这会导致事务移至 `idle in transaction` 状态。

### 操作
<a name="proactive-insights.idle-txn.actions"></a>

您可以通过查询 `pg_stat_activity` 来查找空闲的事务。

在 SQL 客户端中，运行以下查询以列出所有处于 `idle in transaction` 状态的连接，并按持续时间对它们进行排序：

```
SELECT now() - state_change as idle_in_transaction_duration, now() - xact_start as xact_duration,* 
FROM  pg_stat_activity 
WHERE state  = 'idle in transaction'
AND   xact_start is not null
ORDER BY 1 DESC;
```

根据见解的原因，我们建议采取不同的操作。

**Topics**
+ [结束事务](#proactive-insights.idle-txn.actions.end-txn)
+ [终止连接](#proactive-insights.idle-txn.actions.end-connection)
+ [配置 idle\$1in\$1transaction\$1session\$1timeout 参数](#proactive-insights.idle-txn.actions.parameter)
+ [检查 AUTOCOMMIT 状态](#proactive-insights.idle-txn.actions.autocommit)
+ [检查应用程序代码中的事务逻辑](#proactive-insights.idle-txn.actions.app-logic)

#### 结束事务
<a name="proactive-insights.idle-txn.actions.end-txn"></a>

当您在交互式会话中使用 BEGIN 或 START TRANSACTION 启动事务时，它会转入 `idle in transaction` 状态。它会一直保持此状态，直到您通过发出 COMMIT、ROLLBACK、END 命令结束事务，或完全断开连接以回滚事务。

#### 终止连接
<a name="proactive-insights.idle-txn.actions.end-connection"></a>

使用以下查询终止与空闲事务的连接：

```
SELECT pg_terminate_backend(pid);
```

pid 是连接的进程 ID。

#### 配置 idle\$1in\$1transaction\$1session\$1timeout 参数
<a name="proactive-insights.idle-txn.actions.parameter"></a>

在参数组中配置 `idle_in_transaction_session_timeout` 参数。配置此参数的优势在于，它不需要手动干预即可终止长时间空闲的事务。有关此参数的更多信息，请参阅 [PostgreSQL 文档](https://www.postgresql.org/docs/current/runtime-config-client.html)。

当事务处于 idle\$1in\$1transaction 状态超过指定时间时，连接终止后，PostgreSQL 日志文件中将报告以下消息。

```
FATAL: terminating connection due to idle in transaction timeout
```

#### 检查 AUTOCOMMIT 状态
<a name="proactive-insights.idle-txn.actions.autocommit"></a>

原定设置情况下，AUTOCOMMIT 处于开启状态。但是，如果在客户端中意外将其关闭，请确保将其重新开启。
+ 在 psql 客户端中，运行以下命令：

  ```
  postgres=> \set AUTOCOMMIT on
  ```
+ 在 pgadmin 中，通过从向下箭头中选择 AUTOCOMMIT 选项将其开启。  
![\[在 pgadmin 中，选择 AUTOCOMMIT 将其开启。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/apg-insight-pgadmin-autocommit.png)

#### 检查应用程序代码中的事务逻辑
<a name="proactive-insights.idle-txn.actions.app-logic"></a>

调查应用程序逻辑中可能存在的问题。请考虑以下操作：
+ 检查应用程序中 JDBC 自动提交是否设置为 true。另外，可以考虑在代码中使用显式 `COMMIT` 命令。
+ 检查错误处理逻辑，看看它是否会在错误后关闭事务。
+ 在事务打开时，检查您的应用程序处理查询所返回的行是否花费了很长时间。如果是，请考虑在处理行之前对应用程序进行编码以关闭事务。
+ 检查事务是否包含许多长时间运行的操作。如果是，请将单个事务分成多个事务。

### 相关指标
<a name="proactive-insights.idle-txn.metrics"></a>

以下 PI 指标与此见解相关：
+ idle\$1in\$1transaction\$1count - 处于 `idle in transaction` 状态的会话数。
+ idle\$1in\$1transaction\$1max\$1time - 处于 `idle in transaction` 状态的运行时间最长的事务的持续时间。

# 将 PostgreSQL 扩展与 Amazon RDS for PostgreSQL 结合使用
<a name="Appendix.PostgreSQL.CommonDBATasks.Extensions"></a>

您可以通过安装各种扩展和模块来扩展 PostgreSQL 的功能。例如，要处理空间数据，您可以安装和使用 PostGIS 扩展。有关更多信息，请参阅 [使用 PostGIS 扩展管理空间数据](Appendix.PostgreSQL.CommonDBATasks.PostGIS.md)。作为另一个例子，如果要改进非常大的表的数据输入，您可以考虑使用 `pg_partman` 扩展对数据进行分区。要了解更多信息，请参阅[使用 pg\$1partman 扩展管理 PostgreSQL 分区](PostgreSQL_Partitions.md)。

**注意**  
RDS for PostgreSQL 通过 `pg_tle` 扩展支持 PostgreSQL 的可信语言扩展，您可以将该扩展添加到数据库实例中。通过使用此扩展，开发人员可以在安全的环境中创建自己的 PostgreSQL 扩展，从而简化设置和配置要求。要了解支持 `pg_tle` 扩展的 RDS for PostgreSQL 版本以及更多信息，请参阅[使用适用于 PostgreSQL 的可信语言扩展](PostgreSQL_trusted_language_extension.md)。

在某些情况下，您可以将特定模块添加到 RDS for PostgreSQL 数据库实例的自定义数据库参数组中的 `shared_preload_libraries` 列表中，而不是安装扩展。通常，默认的数据库集群参数组仅加载 `pg_stat_statements`，但还有其他几个模块可供添加到此列表中。例如，您可以通过添加 `pg_cron` 模块来添加调度功能，详情请见[使用 PostgreSQL pg\$1cron 扩展计划维护](PostgreSQL_pg_cron.md)。再举一个例子，您可以通过加载 `auto_explain` 模块来记录查询执行计划。要了解更多信息，请参阅 AWS 知识中心中的[记录查询执行计划](https://aws.amazon.com/premiumsupport/knowledge-center/rds-postgresql-tune-query-performance/#)。

根据您的 RDS for PostgreSQL 版本，安装扩展可能需要 `rds_superuser` 权限，如下所示：
+ 对于 RDS for PostgreSQL 版本 12 和更早版本，安装扩展需要 `rds_superuser` 权限。
+ 对于 RDS for PostgreSQL 版本 13 及更高版本，对给定数据库实例具有创建权限的用户（角色）可以安装和使用任何*可信扩展*。有关可信扩展清单，请参阅[PostgreSQL 可信扩展](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md#PostgreSQL.Concepts.General.Extensions.Trusted)。

您还可以通过在 `rds.allowed_extensions` 参数中列出扩展，来精确指定可以在 RDS for PostgreSQL 数据库实例上安装的扩展。有关更多信息，请参阅 [限制 PostgreSQL 扩展的安装](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)。

要了解有关 `rds_superuser` 角色的更多信息，请参阅[了解 PostgreSQL 角色和权限](Appendix.PostgreSQL.CommonDBATasks.Roles.md)。

**Topics**
+ [使用 orafce 扩展中的函数](Appendix.PostgreSQL.CommonDBATasks.orafce.md)
+ [使用适用于 PostgreSQL 的 Amazon RDS 委派扩展支持](RDS_delegated_ext.md)
+ [使用 pg\$1partman 扩展管理 PostgreSQL 分区](PostgreSQL_Partitions.md)
+ [使用 pgAudit 记录数据库活动](Appendix.PostgreSQL.CommonDBATasks.pgaudit.md)
+ [使用 PostgreSQL pg\$1cron 扩展计划维护](PostgreSQL_pg_cron.md)
+ [使用 pglogical 跨实例同步数据](Appendix.PostgreSQL.CommonDBATasks.pglogical.md)
+ [使用 pgactive 支持主动-主动复制](Appendix.PostgreSQL.CommonDBATasks.pgactive.md)
+ [使用 pg\$1repack 扩展减少表和索引的膨胀](Appendix.PostgreSQL.CommonDBATasks.pg_repack.md)
+ [升级和使用 PLV8 扩展](PostgreSQL.Concepts.General.UpgradingPLv8.md)
+ [使用 PL/Rust 通过 Rust 语言编写 PostgreSQL 函数](PostgreSQL.Concepts.General.Using.PL_Rust.md)
+ [使用 PostGIS 扩展管理空间数据](Appendix.PostgreSQL.CommonDBATasks.PostGIS.md)

# 使用 orafce 扩展中的函数
<a name="Appendix.PostgreSQL.CommonDBATasks.orafce"></a>

orafce 扩展提供了模拟 Oracle 数据库中的函数和软件包子集的函数和运算符。orafce 扩展使您能够更轻松地将 Oracle 应用程序移植到 PostgreSQL。RDS for PostgreSQL 版本 9.6.6 及更高版本支持该扩展。有关 orafce 的更多信息，请参阅 GitHub 上的 [orafce](https://github.com/orafce/orafce)。

**注意**  
RDS for PostgreSQL 不支持属于 orafce 扩展一部分的 `utl_file` 软件包。这是因为 `utl_file` 架构函数可提供对操作系统文本文件的读取和写入操作，这需要对底层主机拥有超级用户访问权限。作为一项托管服务，RDS for PostgreSQL 不提供主机访问权限。

**使用 orafce 扩展**

1. 使用用于创建数据库实例的主用户名连接到数据库实例。

   如果要为同一数据库实例中的不同数据库启用 orafce，请使用 `/c dbname` psql 命令。使用此命令，您可以在启动连接后从主数据库进行更改。

1. 使用 `CREATE EXTENSION` 语句启用 orafce 扩展。

   ```
   CREATE EXTENSION orafce;
   ```

1. 使用 `ALTER SCHEMA` 语句将 oracle 架构的所有权移交给 rds\$1superuser 角色。

   ```
   ALTER SCHEMA oracle OWNER TO rds_superuser;
   ```

   如果要查看 oracle 架构的所有者列表，请使用 `\dn` psql 命令。

# 使用适用于 PostgreSQL 的 Amazon RDS 委派扩展支持
<a name="RDS_delegated_ext"></a>

使用适用于 PostgreSQL 的 Amazon RDS 委派扩展支持，您可以将扩展管理委派给其它用户，而且不必让该用户成为 `rds_superuser`。通过这种委派扩展支持，将创建一个名为 `rds_extension` 的新角色，您必须将其分配给用户才能管理其他扩展。此角色可以创建、更新和删除扩展。

可以通过在 `rds.allowed_extensions` 参数中列出扩展，指定可以在 RDS 数据库实例上安装哪些扩展。有关更多信息，请参阅[将 PostgreSQL 扩展与 Amazon RDS for PostgreSQL 结合使用](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Extensions.html)。

您可以通过 `rds.allowed_delegated_extensions` 参数来限制具有 `rds_extension` 角色的用户可以管理的可用扩展列表。

委派扩展支持在以下版本中可用：
+ 所有更高版本
+ 16.4 及更高的 16 版本
+ 15.8 及更高的 15 版本
+ 14.13 及更高的 14 版本
+ 13.16 及更高的 13 版本
+ 12.20 及更高的 12 版本

**Topics**
+ [为用户开启委派扩展支持](#RDSPostgreSQL.delegated_ext_mgmt)
+ [在适用于 PostgreSQL 的 RDS 委派扩展支持中使用的配置](#RDSPostgreSQL.delegated_ext_config)
+ [关闭对委派扩展的支持](#RDSPostgreSQL.delegated_ext_disable)
+ [使用 Amazon RDS 委派扩展支持的优势](#RDSPostgreSQL.delegated_ext_benefits)
+ [适用于 PostgreSQL 的 Amazon RDS 委派扩展支持的限制](#RDSPostgreSQL.delegated_ext_limit)
+ [某些扩展所需的权限](#RDSPostgreSQL.delegated_ext_perm)
+ [安全考虑因素](#RDSPostgreSQL.delegated_ext_sec)
+ [已禁用删除扩展级联](#RDSPostgreSQL.delegated_ext_drop)
+ [可以使用委派扩展支持添加的扩展示例](#RDSPostgreSQL.delegated_ext_support)

## 为用户开启委派扩展支持
<a name="RDSPostgreSQL.delegated_ext_mgmt"></a>

必须执行以下操作才能为用户启用委派扩展支持：

1. **向用户授予 `rds_extension` 角色**：以 `rds_superuser` 身份连接到数据库并执行以下命令：

   ```
   Postgres => grant rds_extension to user_name;
   ```

1. **设置可供委派用户管理的扩展列表**：`rds.allowed_delegated_extensions` 允许您使用 `rds.allowed_extensions` 在数据库集群参数中指定可用扩展的子集。您可以在以下级别之一执行此操作：
   + 在集群或实例参数组中，通过 AWS 管理控制台或 API。有关更多信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。
   + 在数据库级别使用以下命令：

     ```
     alter database database_name set rds.allowed_delegated_extensions = 'extension_name_1,
                         extension_name_2,...extension_name_n';
     ```
   + 在用户级别使用以下命令：

     ```
     alter user user_name set rds.allowed_delegated_extensions = 'extension_name_1,
                         extension_name_2,...extension_name_n';
     ```
**注意**  
更改 `rds.allowed_delegated_extensions` 动态参数后，无需重启数据库。

1. **允许委派用户访问在扩展创建过程中创建的对象**：某些扩展创建的对象要求先授予其它权限，然后具有 `rds_extension` 角色的用户才能访问它们。`rds_superuser` 必须向委派用户授予对这些对象的访问权限。其中一个选项是使用事件触发器自动向委派用户授予权限。

   **事件触发器示例**

   如果您希望允许具有 `rds_extension` 的委派用户使用扩展，而此类扩展要求对通过扩展创建过程所创建的对象设置权限，则可以自定义以下事件触发器示例，并仅添加您希望委派用户有权访问其全部功能的扩展。此事件触发器可以在 template1（默认模板）上创建，因此所有从 template1 创建的数据库都将具有该事件触发器。当委派用户安装扩展时，此触发器将自动授予对扩展创建的对象的所有权。

   ```
   CREATE OR REPLACE FUNCTION create_ext()
   
     RETURNS event_trigger AS $$
   
   DECLARE
   
     schemaname TEXT;
     databaseowner TEXT;
   
     r RECORD;
   
   BEGIN
   
     IF tg_tag = 'CREATE EXTENSION' and current_user != 'rds_superuser' THEN
       RAISE NOTICE 'SECURITY INVOKER';
       RAISE NOTICE 'user: %', current_user;
       FOR r IN SELECT * FROM pg_catalog.pg_event_trigger_ddl_commands()
       LOOP
           CONTINUE WHEN r.command_tag != 'CREATE EXTENSION' OR r.object_type != 'extension';
   
           schemaname = (
               SELECT n.nspname
               FROM pg_catalog.pg_extension AS e
               INNER JOIN pg_catalog.pg_namespace AS n
               ON e.extnamespace = n.oid
               WHERE e.oid = r.objid
           );
   
           databaseowner = (
               SELECT pg_catalog.pg_get_userbyid(d.datdba)
               FROM pg_catalog.pg_database d
               WHERE d.datname = current_database()
           );
           RAISE NOTICE 'Record for event trigger %, objid: %,tag: %, current_user: %, schema: %, database_owenr: %', r.object_identity, r.objid, tg_tag, current_user, schemaname, databaseowner;
           IF r.object_identity = 'address_standardizer_data_us' THEN
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_gaz TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_lex TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_rules TO %I WITH GRANT OPTION;', schemaname, databaseowner);
           ELSIF r.object_identity = 'dict_int' THEN
               EXECUTE pg_catalog.format('ALTER TEXT SEARCH DICTIONARY %I.intdict OWNER TO %I;', schemaname, databaseowner);
           ELSIF r.object_identity = 'pg_partman' THEN
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config_sub TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.custom_time_partitions TO %I WITH GRANT OPTION;', schemaname, databaseowner);
           ELSIF r.object_identity = 'postgis_topology' THEN
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
               EXECUTE pg_catalog.format('GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
               EXECUTE pg_catalog.format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
               EXECUTE pg_catalog.format('GRANT USAGE ON SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
           END IF;
       END LOOP;
     END IF;
   END;
   $$ LANGUAGE plpgsql SECURITY DEFINER;
   
   CREATE EVENT TRIGGER log_create_ext ON ddl_command_end EXECUTE PROCEDURE create_ext();
   ```

## 在适用于 PostgreSQL 的 RDS 委派扩展支持中使用的配置
<a name="RDSPostgreSQL.delegated_ext_config"></a>


| 配置名称 | 说明 | 默认值 | 备注 | 谁可以修改或授予权限 | 
| --- | --- | --- | --- | --- | 
| `rds.allowed_delegated_extensions` | 此参数限制 rds\$1extension 角色可以在数据库中管理的扩展。它必须是 rds.allowed\$1extensions 的子集。 | 空字符串 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/RDS_delegated_ext.html) 要了解有关设置此参数的更多信息，请参阅[为用户开启委派扩展支持](#RDSPostgreSQL.delegated_ext_mgmt)。 | rds\$1superuser | 
| `rds.allowed_extensions` | 此参数可让客户限制可以在 RDS 数据库实例中安装的扩展。有关更多信息，请参阅[限制 PostgreSQL 扩展的安装](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)。 | "\$1" | 默认情况下，此参数设置为“\$1”，这意味着具有必要权限的用户能够创建 RDS for PostgreSQL 和 Aurora PostgreSQL 支持的所有扩展。 空表示无法在 RDS 数据库实例中安装任何扩展。 | 管理员 | 
| `rds-delegated_extension_allow_drop_cascade` | 此参数控制拥有 `rds_extension` 的用户使用级联选项删除扩展的能力。 | off | 默认情况下，将 `rds-delegated_extension_allow_drop_cascade` 设置为 `off`。这意味着不允许拥有 `rds_extension` 的用户使用级联选项删除扩展。 要授予该能力，`rds.delegated_extension_allow_drop_cascade` 参数应设置为 `on`。 | rds\$1superuser | 

## 关闭对委派扩展的支持
<a name="RDSPostgreSQL.delegated_ext_disable"></a>

**部分关闭**  
委派用户无法创建新的扩展，但仍然可以更新现有的扩展。
+ 在数据库集群参数组中将 `rds.allowed_delegated_extensions` 重置为默认值。
+ 在数据库级别使用以下命令：

  ```
  alter database database_name reset rds.allowed_delegated_extensions;
  ```
+ 在用户级别使用以下命令：

  ```
  alter user user_name reset rds.allowed_delegated_extensions;
  ```

**完全关闭**  
撤销用户的 `rds_extension` 角色会将该用户恢复为标准权限。用户无法再创建、更新或删除扩展。

```
postgres => revoke rds_extension from user_name;
```

## 使用 Amazon RDS 委派扩展支持的优势
<a name="RDSPostgreSQL.delegated_ext_benefits"></a>

通过使用适用于 PostgreSQL 的 Amazon RDS 委派扩展支持，您可以安全地将扩展管理委派给没有 `rds_superuser` 角色的用户。该功能具有以下优势：
+ 您可以轻松地将扩展管理委派给您选择的用户。
+ 这不需要 `rds_superuser` 角色。
+ 支持为同一个数据库集群中的不同数据库提供不同的扩展集。

## 适用于 PostgreSQL 的 Amazon RDS 委派扩展支持的限制
<a name="RDSPostgreSQL.delegated_ext_limit"></a>
+ 在扩展创建过程中创建的对象可能需要额外的权限才能使扩展正常运行。
+ 默认情况下，委派扩展用户无法管理某些扩展，包括以下各项：`log_fdw`、`pg_cron`、`pg_tle`、`pgactive`、`pglogical`、`postgis_raster`、`postgis_tiger_geocoder`、`postgis_topology`。

## 某些扩展所需的权限
<a name="RDSPostgreSQL.delegated_ext_perm"></a>

要创建、使用或更新以下扩展，委派用户应具有对以下函数、表和架构的必要权限。


| 需要所有权或权限的扩展 | 函数 | 表 | 架构 | 文本搜索词典 | Comment | 
| --- | --- | --- | --- | --- | --- | 
| address\$1standardizer\$1data\$1us | none | us\$1gaz、us\$1lex、us\$1lex、I.us\$1rules | none | none | none | 
| amcheck | bt\$1index\$1check、bt\$1index\$1parent\$1check | none | none | none | none | 
| dict\$1int | none | none | none | intdict | none | 
| pg\$1partman | none | custom\$1time\$1partitions、part\$1config、part\$1config\$1sub | none | none | none | 
| pg\$1stat\$1statements | none | none | none | none | none | 
| PostGIS | st\$1tileenvelope | spatial\$1ref\$1sys | none | none | none | 
| postgis\$1raster | none | none | none | none | none | 
| postgis\$1topology | none | topology、layer | topology | none | 委派用户必须是数据库所有者 | 
| log\$1fdw | create\$1foreign\$1table\$1for\$1log\$1file | none | none | none | none | 
| rds\$1tools | role\$1password\$1encryption\$1type | none | none | none | none | 
| postgis\$1tiger\$1geocoder | none | geocode\$1settings\$1default、geocode\$1settings | tiger | none | none | 
| pg\$1freespacemap | pg\$1freespace | none | none | none | none | 
| pg\$1visibility | pg\$1visibility | none | none | none | none | 

## 安全考虑因素
<a name="RDSPostgreSQL.delegated_ext_sec"></a>

 请记住，具有 `rds_extension` 角色的用户将能够管理他们拥有连接权限的所有数据库上的扩展。如果打算让委派用户管理单个数据库上的扩展，那么一个好的做法是撤销每个数据库上的公有权限，然后向委派用户显式授予对该特定数据库的连接权限。

 有几个扩展可以允许用户访问多个数据库中的信息。在向 `rds.allowed_delegated_extensions` 添加这些扩展之前，请确保您授予 `rds_extension` 的用户具有跨数据库功能。例如，`postgres_fdw` 和 `dblink` 提供在同一实例或远程实例上跨数据库进行查询的功能。`log_fdw` 读取 postgres 引擎日志文件，这些文件适用于实例中的所有数据库，可能包含来自多个数据库的慢速查询或错误消息。`pg_cron` 允许在数据库实例上运行计划的后台任务，并且可以将任务配置为在不同的数据库中运行。

## 已禁用删除扩展级联
<a name="RDSPostgreSQL.delegated_ext_drop"></a>

 具有 `rds_extension` 角色的用户使用级联选项删除扩展的能力由 `rds.delegated_extension_allow_drop_cascade` 参数控制。默认情况下，将 `rds-delegated_extension_allow_drop_cascade` 设置为 `off`。这意味着不允许具有 `rds_extension` 角色的用户使用级联选项删除扩展，如以下查询所示。

```
DROP EXTENSION CASCADE;
```

因为这将自动删除依赖于扩展的对象，进而删除依赖于这些对象的所有对象。尝试使用级联选项将会导致错误。

 要授予该能力，`rds.delegated_extension_allow_drop_cascade` 参数应设置为 `on`。

 更改 `rds.delegated_extension_allow_drop_cascade` 动态参数不需要重启数据库。您可以在以下级别之一执行此操作：
+ 在集群或实例参数组中，通过 AWS 管理控制台或 API。
+ 在数据库级别使用以下命令：

  ```
  alter database database_name set rds.delegated_extension_allow_drop_cascade = 'on';
  ```
+ 在用户级别使用以下命令：

  ```
  alter role tenant_user set rds.delegated_extension_allow_drop_cascade = 'on';
  ```

## 可以使用委派扩展支持添加的扩展示例
<a name="RDSPostgreSQL.delegated_ext_support"></a>
+ `rds_tools`

  ```
  extension_test_db=> create extension rds_tools;
  CREATE EXTENSION
  extension_test_db=> SELECT * from rds_tools.role_password_encryption_type() where rolname = 'pg_read_server_files';
  ERROR: permission denied for function role_password_encryption_type
  ```
+ `amcheck`

  ```
  extension_test_db=> CREATE TABLE amcheck_test (id int);
  CREATE TABLE
  extension_test_db=> INSERT INTO amcheck_test VALUES (generate_series(1,100000));
  INSERT 0 100000
  extension_test_db=> CREATE INDEX amcheck_test_btree_idx ON amcheck_test USING btree (id);
  CREATE INDEX
  extension_test_db=> create extension amcheck;
  CREATE EXTENSION
  extension_test_db=> SELECT bt_index_check('amcheck_test_btree_idx'::regclass);
  ERROR: permission denied for function bt_index_check
  extension_test_db=> SELECT bt_index_parent_check('amcheck_test_btree_idx'::regclass);
  ERROR: permission denied for function bt_index_parent_check
  ```
+ `pg_freespacemap`

  ```
  extension_test_db=> create extension pg_freespacemap;
  CREATE EXTENSION
  extension_test_db=> SELECT * FROM pg_freespace('pg_authid');
  ERROR: permission denied for function pg_freespace
  extension_test_db=> SELECT * FROM pg_freespace('pg_authid',0);
  ERROR: permission denied for function pg_freespace
  ```
+ `pg_visibility`

  ```
  extension_test_db=> create extension pg_visibility;
  CREATE EXTENSION
  extension_test_db=> select * from pg_visibility('pg_database'::regclass);
  ERROR: permission denied for function pg_visibility
  ```
+ `postgres_fdw`

  ```
  extension_test_db=> create extension postgres_fdw;
  CREATE EXTENSION
  extension_test_db=> create server myserver foreign data wrapper postgres_fdw options (host 'foo', dbname 'foodb', port '5432');
  ERROR: permission denied for foreign-data wrapper postgres_fdw
  ```

# 使用 pg\$1partman 扩展管理 PostgreSQL 分区
<a name="PostgreSQL_Partitions"></a>

PostgreSQL 表分区为数据输入和报告的高性能处理提供了框架。对于需要非常快速地输入大量数据的数据库，请使用分区。分区还可以更快地查询大型表。分区有助于在不影响数据库实例的情况下维护数据，因为它需要的 I/O 资源较少。

通过使用分区，您可以将数据拆分为自定义大小的块进行处理。例如，您可以将时间序列数据分区为范围，例如每小时、每日、每周、每月、每季度、每年、自定义或这些范围的任意组合。对于时间序列数据示例，如果您按小时对表进行分区，则每个分区会包含一小时的数据。如果您按天对时间序列表进行分区，则分区会保存一天的数据，以此类推。分区键控制分区的大小。

在分区表上使用 `INSERT` 或 `UPDATE` SQL 命令时，数据库引擎会将数据路由到相应的分区。存储数据的 PostgreSQL 表分区是主表的子表。

在数据库查询读取期间，PostgreSQL 优化程序会检查查询的 `WHERE` 子句，如果可能的话，将数据库扫描定向到仅相关分区。

从版本 10 开始，PostgreSQL 使用声明性分区来实现表分区，这也称为本机 PostgreSQL 分区。在 PostgreSQL 版本 10 之前，使用触发器来实现分区。

PostgreSQL 表分区提供了以下功能：
+ 随时创建新分区。
+ 可变分区范围。
+ 使用数据定义语言 (DDL) 语句可分离和可重新连接的分区。

  例如，可分离的分区对于从主分区中删除历史数据但保留历史数据以供分析很有用。
+ 新分区继承了父数据库表的属性，包括以下属性：
  + 索引
  + 主键，其必须包括分区键列
  + 外键
  + 检查约束
  + 参考
+ 为完整表或每个特定分区创建索引。

您不能更改单个分区的架构。但是，您可以更改传播到分区的父表（例如添加新列）。

**Topics**
+ [PostgreSQL pg\$1partman 扩展概述](#PostgreSQL_Partitions.pg_partman)
+ [启用 pg\$1partman 扩展](#PostgreSQL_Partitions.enable)
+ [使用 create\$1parent 函数配置分区](#PostgreSQL_Partitions.create_parent)
+ [使用 run\$1maintenance\$1proc 函数配置分区维护](#PostgreSQL_Partitions.run_maintenance_proc)

## PostgreSQL pg\$1partman 扩展概述
<a name="PostgreSQL_Partitions.pg_partman"></a>

您可以使用 PostgreSQL `pg_partman` 扩展自动创建和维护表分区。有关更多一般信息，请参阅 `pg_partman` 文档中的 [PG 分区管理器](https://github.com/pgpartman/pg_partman)。

**注意**  
RDS for PostgreSQL 版本 12.5 及更高版本支持该 `pg_partman` 扩展。

您可以使用以下设置来配置 `pg_partman`，而不必手动创建每个分区：
+ 要分区的表
+ 分区类型
+ 分区键
+ 分区粒度
+ 分区预创建和管理选项

创建 PostgreSQL 分区表后，您可以通过调用 `create_parent` 函数向 `pg_partman` 注册该表。此举会根据传递给函数的参数创建必要的分区。

该 `pg_partman` 扩展还提供了 `run_maintenance_proc` 函数，您可以按计划调用该函数来自动管理分区。为确保根据需要创建正确的分区，请将此函数计划为定期运行（例如每小时）。您还可以确保自动删除分区。

## 启用 pg\$1partman 扩展
<a name="PostgreSQL_Partitions.enable"></a>

如果要管理分区的同一 PostgreSQL 数据库实例中有多个数据库，请为每个数据库分别启用 `pg_partman` 扩展。要为特定数据库启用 `pg_partman` 扩展，请创建分区维护架构，然后按如下所示创建 `pg_partman` 扩展。

```
CREATE SCHEMA partman;
CREATE EXTENSION pg_partman WITH SCHEMA partman;
```

**注意**  
要创建 `pg_partman` 扩展，请确保您具有 `rds_superuser` 权限。

如果您收到以下错误，请向该账户授予 `rds_superuser` 权限或使用您的超级用户帐户。

```
ERROR: permission denied to create extension "pg_partman"
HINT: Must be superuser to create this extension.
```

要授予 `rds_superuser` 权限，请连接您的超级用户账户并运行以下命令。

```
GRANT rds_superuser TO user-or-role;
```

对于显示使用 pg\$1partman 扩展的示例，我们使用以下示例数据库表和分区。此数据库使用基于时间戳的分区表。架构 `data_mart` 包含名为 `events` 的表，当中包含名为 `created_at` 的列。`events` 表中包含以下设置：
+  主键 `event_id` 和 `created_at`，其必须具有用于指导分区的列。
+ 用于强制 `ck_valid_operation` 表列值的检查约束 `operation`。
+ 两个外键，其中一个 (`fk_orga_membership)`) 指向外部表 `organization`，另一个 (`fk_parent_event_id`) 是自引用的外键。
+ 两个索引，其中一个 (`idx_org_id`) 用于外键，另一个 (`idx_event_type`) 用于事件类型。

以下 DDL 语句创建这些对象，这些对象自动包含在每个分区中。

```
CREATE SCHEMA data_mart;
CREATE TABLE data_mart.organization ( org_id BIGSERIAL,
        org_name TEXT,
        CONSTRAINT pk_organization PRIMARY KEY (org_id)  
    );

CREATE TABLE data_mart.events(
        event_id        BIGSERIAL, 
        operation       CHAR(1), 
        value           FLOAT(24), 
        parent_event_id BIGINT, 
        event_type      VARCHAR(25), 
        org_id          BIGSERIAL, 
        created_at      timestamp, 
        CONSTRAINT pk_data_mart_event PRIMARY KEY (event_id, created_at), 
        CONSTRAINT ck_valid_operation CHECK (operation = 'C' OR operation = 'D'), 
        CONSTRAINT fk_orga_membership 
            FOREIGN KEY(org_id) 
            REFERENCES data_mart.organization (org_id),
        CONSTRAINT fk_parent_event_id 
            FOREIGN KEY(parent_event_id, created_at) 
            REFERENCES data_mart.events (event_id,created_at)
    ) PARTITION BY RANGE (created_at);

CREATE INDEX idx_org_id     ON  data_mart.events(org_id);
CREATE INDEX idx_event_type ON  data_mart.events(event_type);
```



## 使用 create\$1parent 函数配置分区
<a name="PostgreSQL_Partitions.create_parent"></a>

启用 `pg_partman` 扩展后，使用 `create_parent` 函数在分区维护架构中配置分区。以下示例使用在 `events` 中创建的 [启用 pg\$1partman 扩展使用 run\$1maintenance\$1proc 函数配置分区维护](#PostgreSQL_Partitions.enable) 表示例。按如下方式调用 `create_parent` 函数。

```
SELECT partman.create_parent( 
 p_parent_table => 'data_mart.events',
 p_control      => 'created_at',
 p_type         => 'range',
 p_interval     => '1 day',
 p_premake      => 30);
```

参数如下所示：
+ `p_parent_table` – 父分区表。此表必须已存在并完全限定（包括架构在内）。
+ `p_control` – 分区所依据的列。数据类型必须是整数或基于时间的。
+ `p_type` – 该类型是 `'range'` 或者 `'list'`。
+ `p_interval` – 每个分区的时间间隔或整数范围。示例值包括 `1 day`、`1 hour` 等。
+ `p_premake` – 为支持新插入而提前创建的分区数量。

有关 `create_parent` 函数的完整说明，请参阅 `pg_partman` 文档中的[创建函数](https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md#user-content-creation-functions)。

## 使用 run\$1maintenance\$1proc 函数配置分区维护
<a name="PostgreSQL_Partitions.run_maintenance_proc"></a>

您可以运行分区维护操作来自动创建新分区、分离分区或删除旧分区。分区维护依赖于 `pg_partman` 扩展和 `pg_cron` 扩展的 `run_maintenance_proc` 函数，其将启动内部调度程序。调度程序 `pg_cron` 自动执行数据库中定义的 SQL 语句、函数和程序。

以下示例使用在 `events` 中创建的 [启用 pg\$1partman 扩展使用 run\$1maintenance\$1proc 函数配置分区维护](#PostgreSQL_Partitions.enable) 表示例将分区维护操作设置为自动运行。作为先决条件，请将 `pg_cron` 添加到数据库实例的参数组中的 `shared_preload_libraries` 参数。

```
CREATE EXTENSION pg_cron;

UPDATE partman.part_config 
SET infinite_time_partitions = true,
    retention = '3 months', 
    retention_keep_table=true 
WHERE parent_table = 'data_mart.events';
SELECT cron.schedule('@hourly', $$CALL partman.run_maintenance_proc()$$);
```

以下是前述示例的分步说明：

1. 修改与数据库实例关联的参数组并将 `pg_cron` 添加到 `shared_preload_libraries` 参数值中。此更改需要重启数据库实例才能生效。有关更多信息，请参阅“[在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)”。

1. `CREATE EXTENSION pg_cron;` 使用具有 `rds_superuser` 权限的账户运行此命令。这将启用 `pg_cron` 扩展。有关更多信息，请参阅“[使用 PostgreSQL pg\$1cron 扩展计划维护](PostgreSQL_pg_cron.md)”。

1. 运行命令 `UPDATE partman.part_config` 以调整 `data_mart.events` 表的 `pg_partman` 设置。

1. 运行命令 `SET`… 配置 `data_mart.events` 表，其中包含以下子句：

   1. `infinite_time_partitions = true,` – 将表配置为能够在没有任何限制的情况下自动创建新分区。

   1. `retention = '3 months',` – 将表配置为最长保留三个月。

   1. `retention_keep_table=true ` – 对表进行配置，以便在保留期到期时表不会自动删除。相反，早于保留期的分区只能从父表中分离。

1. 运行命令 `SELECT cron.schedule`… 创建一个 `pg_cron` 函数调用。此调用定义了计划程序运行 `pg_partman` 维护程序的频率，`partman.run_maintenance_proc`。对于此示例，该程序每小时运行一次。

有关 `run_maintenance_proc` 函数的完整说明，请参阅 `pg_partman` 文档中的[维护函数](https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md#maintenance-functions)。

# 使用 pgAudit 记录数据库活动
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit"></a>

金融机构、政府机构和许多行业需要保留*审计日志*以满足监管要求。通过将 PostgreSQL Audit 扩展（pgAudit）与 RDS for PostgreSQL 数据库实例结合使用，您可以捕获审计人员通常需要或满足监管要求的详细记录。例如，您可以设置 pgAudit 扩展来跟踪对特定数据库和表所做的更改，记录进行更改的用户以及许多其他详细信息。

pgAudit 扩展通过更详细地扩展日志消息，进一步构建原生 PostgreSQL 日志记录基础设施的功能。换句话说，您将使用与查看任何日志消息相同的方法来查看审计日志。有关 PostgreSQL 日志记录的更多信息，请参阅 [RDS for PostgreSQL 数据库日志文件](USER_LogAccess.Concepts.PostgreSQL.md)。

pgAudit 扩展会编辑日志中的敏感数据，例如明文密码。如果您的 RDS for PostgreSQL 数据库实例配置为记录数据操作语言（DML）语句（详情请见[为您的 RDS for PostgreSQL 数据库实例开启查询日志记录](USER_LogAccess.Concepts.PostgreSQL.Query_Logging.md)），则可以使用 PostgreSQL Audit 扩展来避免明文密码问题。

您可以在数据库实例上配置具有高度明确性的审计。您可以审计所有数据库和所有用户。或者，您可以选择仅审计某些数据库、用户和其他对象。您也可以明确排除对某些用户和数据库进行审计。有关更多信息，请参阅 [从审计日志记录中排除用户或数据库](Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db.md)。

考虑到可以捕获的详细信息量，我们建议您在使用 pgAudit 时监控存储消耗。

所有可用的 RDS for PostgreSQL 版本。有关可用 RDS for PostgreSQL 版本支持的 pgAudit 版本的列表，请参阅《Amazon RDS for PostgreSQL 版本注释》**中的 [Amazon RDS for PostgreSQL 的扩展版本](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)。

**Topics**
+ [设置 pgAudit 扩展](Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.md)
+ [审计数据库对象](Appendix.PostgreSQL.CommonDBATasks.pgaudit.auditing.md)
+ [从审计日志记录中排除用户或数据库](Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db.md)
+ [pgAudit 扩展的参考](Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.md)

# 设置 pgAudit 扩展
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup"></a>

要在 RDS for PostgreSQL 数据库实例 上设置 pgAudit 扩展，首先要将 pgAudit 添加到 RDS for PostgreSQL 数据库实例的自定义数据库参数组 上的共享库中。有关创建自定义数据库参数组的信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。接下来，安装 pgAudit 扩展。最后，指定要审计的数据库和对象。本部分中的过程向您展示如何操作。您可以使用 AWS 管理控制台或 AWS CLI。

您必须拥有 `rds_superuser` 角色的权限才能执行所有这些任务。

以下步骤假设您的 RDS for PostgreSQL 数据库实例与自定义 数据库参数组相关联。

## 控制台
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.CON"></a>

**设置 pgAudit 扩展**

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

1. 在导航窗格中，选择 RDS for PostgreSQL 数据库实例。

1. 打开 的**配置**选项卡。RDS for PostgreSQL 数据库实例的 Configuration（配置）选项卡。在实例详细信息中，找到 **Parameter group**（参数组）链接。

1. 选择此链接以打开与您的 RDS for PostgreSQL 数据库实例关联的自定义参数。

1. 在 **Parameters**（参数）搜索字段中，键入 `shared_pre` 以查找 `shared_preload_libraries` 参数。

1. 选择 **Edit parameters**（编辑参数）以访问属性值。

1. 将 `pgaudit` 添加到 **Values**（值）字段的列表中。使用逗号分隔值列表中的项目。  
![\[添加了 pgAudit 的 shared_preload_libaries 参数的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pgaudit.png)

1. 重启 RDS for PostgreSQL 数据库实例，以使对 `shared_preload_libraries` 参数的更改生效。

1. 当实例可用时，请验证 pgAudit 是否已初始化。使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，然后运行以下命令。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

1. 初始化 pgAudit 后，您现在可以创建扩展了。您需要在初始化库后创建扩展，因为 `pgaudit` 扩展会为审计数据定义语言（DDL）语句安装事件触发器。

   ```
   CREATE EXTENSION pgaudit;
   ```

1. 关闭 `psql` 会话。

   ```
   labdb=> \q
   ```

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

1. 在列表中找到 `pgaudit.log` 参数并设置为适合您的使用案例的值。例如，将 `pgaudit.log` 参数设置为 `write`（如下图所示），可以捕获对日志的插入、更新、删除和其他一些类型的更改。  
![\[带有设置的 pgaudit.log 参数的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/rpg_set_pgaudit-log-level.png)

   还可以为 `pgaudit.log` 参数选择以下值之一。
   + none – 这是默认值。不记录任何数据库更改。
   + all – 记录所有内容（read、write、function、role、ddl、misc）。
   + ddl – 记录所有数据定义语言（DDL）语句（不包括在 `ROLE` 类中）。
   + function – 记录函数调用和 `DO` 块。
   + misc – 记录其他命令，例如 `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM` 和 `SET`。
   + read –当源为关系（例如表）或查询时记录 `SELECT` 和 `COPY`。
   + role – 记录与角色和权限相关的语句，例如 `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE` 和 `DROP ROLE`。
   + write – 当目标为关系（表）时，记录 `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE` 和 `COPY`。

1. 选择 **Save changes**（保存更改）。

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

1. 从“数据库”列表中选择 RDS for PostgreSQL 数据库实例。

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.CLI"></a>

**设置 pgAudit**

要使用 AWS CLI 设置 pgAudit，您可以调用 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) 操作来修改自定义参数组中的审计日志参数，如以下过程所示。

1. 使用以下 AWS CLI 命令向 `shared_preload_libraries` 参数中添加 `pgaudit`。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=pgaudit,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例，以便初始化 pgaudit 库。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 当实例可用时，您可以验证 `pgaudit` 是否已初始化。使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，然后运行以下命令。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

   初始化 pgAudit 后，您现在可以创建扩展了。

   ```
   CREATE EXTENSION pgaudit;
   ```

1. 关闭 `psql` 会话以便您可以使用 AWS CLI。

   ```
   labdb=> \q
   ```

1. 使用以下 AWS CLI 命令指定要由会话审计日志记录所记录的语句类别。该示例将 `pgaudit.log` 参数设置为 `write`，用于捕获对日志的插入、更新和删除。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=pgaudit.log,ParameterValue=write,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

   还可以为 `pgaudit.log` 参数选择以下值之一。
   + none – 这是默认值。不记录任何数据库更改。
   + all – 记录所有内容（read、write、function、role、ddl、misc）。
   + ddl – 记录所有数据定义语言（DDL）语句（不包括在 `ROLE` 类中）。
   + function – 记录函数调用和 `DO` 块。
   + misc – 记录其他命令，例如 `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM` 和 `SET`。
   + read –当源为关系（例如表）或查询时记录 `SELECT` 和 `COPY`。
   + role – 记录与角色和权限相关的语句，例如 `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE` 和 `DROP ROLE`。
   + write – 当目标为关系（表）时，记录 `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE` 和 `COPY`。

   使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

# 审计数据库对象
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.auditing"></a>

在 RDS for PostgreSQL 数据库实例上设置 pgAudit 并根据您的要求进行配置后，将在 PostgreSQL 日志中捕获更多详细信息。例如，虽然默认 PostgreSQL 日志记录配置标识数据库表中发生更改的日期和时间，但使用 pgAudit 扩展后，日志条目可以包括模式、进行更改的用户和其他详细信息，具体取决于扩展参数的配置方式。您可以设置审计以通过以下方法跟踪更改。
+ 对于每个会话，按用户进行跟踪。对于会话级别，您可以捕获完全限定的命令文本。
+ 对于每个对象，按用户和数据库进行跟踪。

当您在系统上创建 `rds_pgaudit` 角色，然后将此角色添加到自定义参数组中的 `pgaudit.role` 参数时，将激活对象审计功能。默认情况下，`pgaudit.role` 参数处于未设置状态，唯一允许的值是 `rds_pgaudit`。以下步骤假设 `pgaudit` 已初始化，并且您已按照[设置 pgAudit 扩展](Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.md)中的步骤创建了 `pgaudit` 扩展。

![\[设置 pgAudit 后 PostgreSQL 日志文件的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/pgaudit-log-example.png)


如本示例所示，“LOG: AUDIT: SESSION”行提供了有关表及其架构的信息以及其他详细信息。

**设置对象审计**

1. 使用 `psql` 连接到 RDS for PostgreSQL 数据库实例。

   ```
   psql --host=your-instance-name.aws-region.rds.amazonaws.com --port=5432 --username=postgrespostgres --password --dbname=labdb
   ```

1. 使用以下命令创建名为 `rds_pgaudit` 的数据库角色。

   ```
   labdb=> CREATE ROLE rds_pgaudit;
   CREATE ROLE
   labdb=>
   ```

1. 关闭 `psql` 会话。

   ```
   labdb=> \q
   ```

   在接下来的几步中，使用 AWS CLI 修改自定义参数组中的审计日志参数。

1. 使用以下 AWS CLI 命令将 `pgaudit.role` 参数设置为 `rds_pgaudit`。默认情况下，此参数为空，`rds_pgaudit` 是唯一允许的值。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=pgaudit.role,ParameterValue=rds_pgaudit,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例，以使对参数的更改生效。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 运行以下命令确认 `pgaudit.role` 设置为 `rds_pgaudit`。

   ```
   SHOW pgaudit.role;
   pgaudit.role 
   ------------------
   rds_pgaudit
   ```

要测试 pgAudit 日志记录，您可以运行几条要审计的示例命令。例如，您可以运行以下命令。

```
CREATE TABLE t1 (id int);
GRANT SELECT ON t1 TO rds_pgaudit;
SELECT * FROM t1;
id 
----
(0 rows)
```

数据库日志应包含类似于以下内容的条目。

```
...
2017-06-12 19:09:49 UTC:...:rds_test@postgres:[11701]:LOG: AUDIT:
OBJECT,1,1,READ,SELECT,TABLE,public.t1,select * from t1;
...
```

有关查看日志的信息，请参阅[监控 Amazon RDS 日志文件](USER_LogAccess.md)。

要了解关于 pgAudit 扩展的更多信息，请参阅 GitHub 上的 [pgAudit](https://github.com/pgaudit/pgaudit/blob/master/README.md)。

# 从审计日志记录中排除用户或数据库
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db"></a>

如 [RDS for PostgreSQL 数据库日志文件](USER_LogAccess.Concepts.PostgreSQL.md)中所述，PostgreSQL 日志会消耗存储空间。使用 pgAudit 扩展会在不同程度上增加日志中收集的数据量，具体取决于您跟踪的更改。您可能不需要审计 RDS for PostgreSQL 数据库实例中的每个用户或数据库。

为了最大限度地减少对存储的影响，避免不必要地捕获审计记录，您可以将用户和数据库排除在审计范围之外。您还可以在给定会话中更改日志记录。下面的示例向您演示如何操作。

**注意**  
会话级别的参数设置优先于 RDS for PostgreSQL 数据库实例的自定义数据库参数组中的设置。如果您不希望数据库用户绕过您的审计日志记录配置设置，请务必更改其权限。

假设您的 RDS for PostgreSQL 数据库实例配置为审计所有用户和数据库的相同级别的活动。然后，您决定不想对用户 `myuser` 进行审计。您可以使用以下 SQL 命令对 `myuser` 关闭审计功能。

```
ALTER USER myuser SET pgaudit.log TO 'NONE';
```

然后，您可以使用以下查询来检查 `pgaudit.log` 的 `user_specific_settings` 列，以确认该参数已设置为 `NONE`。

```
SELECT
    usename AS user_name,
    useconfig AS user_specific_settings
FROM
    pg_user
WHERE
    usename = 'myuser';
```

您将看到如下输出。

```
 user_name | user_specific_settings
-----------+------------------------
 myuser    | {pgaudit.log=NONE}
(1 row)
```

在给定用户与数据库的会话期间，您可以使用以下命令对此用户关闭日志记录功能。

```
ALTER USER myuser IN DATABASE mydatabase SET pgaudit.log TO 'none';
```

使用以下查询，对于特定用户和数据库组合检查 pgaudit.log 的设置列。

```
SELECT
    usename AS "user_name",
    datname AS "database_name",
    pg_catalog.array_to_string(setconfig, E'\n') AS "settings"
FROM
    pg_catalog.pg_db_role_setting s
    LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase
    LEFT JOIN pg_catalog.pg_user r ON r.usesysid = setrole
WHERE
    usename = 'myuser'
    AND datname = 'mydatabase'
ORDER BY
    1,
    2;
```

您将看到类似以下内容的输出。

```
  user_name | database_name |     settings
-----------+---------------+------------------
 myuser    | mydatabase    | pgaudit.log=none
(1 row)
```

对 `myuser` 关闭审计后，您决定不想跟踪对 `mydatabase` 的更改。您可以使用以下命令对该特定数据库关闭审计。

```
ALTER DATABASE mydatabase SET pgaudit.log to 'NONE';
```

然后，使用以下查询检查 database\$1specific\$1settings 列，以确认 pgaudit.log 已设置为 NONE。

```
SELECT
a.datname AS database_name,
b.setconfig AS database_specific_settings
FROM
pg_database a
FULL JOIN pg_db_role_setting b ON a.oid = b.setdatabase
WHERE
a.datname = 'mydatabase';
```

您将看到如下输出。

```
 database_name | database_specific_settings
---------------+----------------------------
 mydatabase    | {pgaudit.log=NONE}
(1 row)
```

要将 myuser 的设置恢复为默认设置，请使用以下命令：

```
ALTER USER myuser RESET pgaudit.log;
```

要将数据库的设置恢复为默认设置，请使用以下命令。

```
ALTER DATABASE mydatabase RESET pgaudit.log;
```

要将用户和数据库重置为默认设置，请使用以下命令。

```
ALTER USER myuser IN DATABASE mydatabase RESET pgaudit.log;
```

还可以通过将 `pgaudit.log` 设置为 `pgaudit.log` 参数的其他允许值之一，将特定事件捕获到日志中。有关更多信息，请参阅 [`pgaudit.log` 参数允许的设置列表](Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.md#Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings)。

```
ALTER USER myuser SET pgaudit.log TO 'read';
ALTER DATABASE mydatabase SET pgaudit.log TO 'function';
ALTER USER myuser IN DATABASE mydatabase SET pgaudit.log TO 'read,function'
```

# pgAudit 扩展的参考
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference"></a>

您可以通过更改本节中列出的一个或多个参数来为审计日志指定所需的详细级别。

## 控制 pgAudit 行为
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.basic-setup.parameters"></a>

您可以通过更改下表中列出的一个或多个参数来控制审计日志记录。


| 参数 | 说明 | 
| --- | --- | 
| `pgaudit.log`  | 指定会话审计日志记录将记录哪些语句类。允许的值包括 ddl、function、misc、read、role、write、none、all。有关更多信息，请参阅 [`pgaudit.log` 参数允许的设置列表](#Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings)。 | 
| `pgaudit.log_catalog` | 启用（设置为 1）时，如果语句中的所有关系都在 pg\$1catalog 中，则将语句添加到审计跟踪中。 | 
| `pgaudit.log_level` | 指定要用于日志条目的日志级别。允许的值：debug5、debug4、debug3、debug2、debug1、info、notice、warning、log | 
| `pgaudit.log_parameter` | 启用（设置为 1）时，将在审计日志中捕获随语句传递的参数。 | 
| `pgaudit.log_relation` | 启用（设置为 1）时，会话的审计日志为 SELECCT 或 DML 语句中引用的每个关系（TABLE、VIEW 等）创建单独的日志条目。 | 
| `pgaudit.log_statement_once` | 指定日志记录在语句/子语句组合中的第一个日志条目中包含语句文本和参数，还是在每个条目中都包含。 | 
| `pgaudit.role` | 指定用于对象审计日志记录的主角色。唯一允许的条目是 `rds_pgaudit`。 | 

## `pgaudit.log` 参数允许的设置列表
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings"></a>

 


| 值 | 说明 | 
| --- | --- | 
| none | 这是默认值。不记录任何数据库更改。 | 
| 全部 | 记录所有内容（read、write、function、role、ddl、misc）。 | 
| ddl | 记录所有数据定义语言（DDL）语句（不包括在 `ROLE` 类中）。 | 
| 函数 | 记录函数调用和 `DO` 块。 | 
| misc | 记录其他命令，例如 `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM` 和 `SET`。 | 
| read | 当源为关系（例如表）或查询时记录 `SELECT` 和 `COPY`。 | 
| 角色 | 记录与角色和权限相关的语句，例如 `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE` 和 `DROP ROLE`。 | 
| 写入 | 当目标为关系（表）时，记录 `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE` 和 `COPY`。 | 

要使用会话审计记录多种事件类型，请使用逗号分隔的列表。要记录所有事件类型，请将 `pgaudit.log` 设置为 `ALL`。重启数据库实例以应用更改。

通过对象审计，您可以细化审计日志记录以使用特定的关系。例如，您可以指定要对一个或多个表上的 `READ` 操作进行审计日志记录。

# 使用 PostgreSQL pg\$1cron 扩展计划维护
<a name="PostgreSQL_pg_cron"></a>

您可以使用 PostgreSQL `pg_cron` 扩展来计划 PostgreSQL 数据库中的维护命令。有关扩展的更多信息，请参阅 pg\$1cron 文档中的[什么是 pg\$1cron？](https://github.com/citusdata/pg_cron) 

RDS for PostgreSQL 引擎版本 12.5 及更高版本支持 `pg_cron` 扩展。

要了解有关使用 `pg_cron` 的更多信息，请参阅[在 RDS for PostgreSQL 或 Aurora PostgreSQL 兼容版数据库上使用 pg\$1cron 计划任务](https://aws.amazon.com/blogs/database/schedule-jobs-with-pg_cron-on-your-amazon-rds-for-postgresql-or-amazon-aurora-for-postgresql-databases/)。

**注意**  
在 pg\$1available\$1extensions 视图中，`pg_cron` 扩展版本显示为两位数的版本，例如 1.6。虽然在某些情况下您可能会看到三位数的版本，例如 1.6.4 或 1.6.5，但在执行扩展升级时必须指定两位数的版本。

**Topics**
+ [设置 pg\$1cron 扩展](#PostgreSQL_pg_cron.enable)
+ [授予数据库用户使用 pg\$1cron 的权限](#PostgreSQL_pg_cron.permissions)
+ [计划 pg\$1cron 作业](#PostgreSQL_pg_cron.examples)
+ [pg\$1cron 扩展的参考](#PostgreSQL_pg_cron.reference)

## 设置 pg\$1cron 扩展
<a name="PostgreSQL_pg_cron.enable"></a>

按如下方式设置 `pg_cron` 扩展：

1. 通过向 `shared_preload_libraries` 参数值添加 `pg_cron`，修改与 PostgreSQL 数据库实例关联的自定义参数组。
   + 如果 RDS for PostgreSQL 数据库实例使用 `rds.allowed_extensions` 参数显式列出可安装的扩展，则需要将 `pg_cron` 扩展添加到列表中。只有某些版本的 RDS for PostgreSQL 支持 `rds.allowed_extensions` 参数。原定设置情况下，允许使用所有可用的扩展。有关更多信息，请参阅 [限制 PostgreSQL 扩展的安装](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)。

   重新启动 PostgreSQL 数据库实例，以使对参数组的更改生效。要了解有关使用参数组的更多信息，请参阅[在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。

1. 重新启动 PostgreSQL 数据库实例后，使用具有 `rds_superuser` 权限的账户运行以下命令。例如，如果在创建 RDS for PostgreSQL 数据库实例时使用默认设置，请以用户 `postgres` 身份进行连接，然后创建扩展。

   ```
   CREATE EXTENSION pg_cron;
   ```

   `pg_cron` 调度程序是在名为 `postgres` 的默认 PostgreSQL 数据库中设置的。这些 `pg_cron` 对象是在此 `postgres` 数据库中创建的，所有调度操作都在此数据库中运行。

1. 您可以使用默认设置，也可以计划作业在 PostgreSQL 数据库实例的其他数据库中运行。要为 PostgreSQL 数据库实例中的其他数据库计划作业，请参阅 [为原定设置数据库以外的数据库计划 cron 任务](#PostgreSQL_pg_cron.otherDB) 中的示例。

## 授予数据库用户使用 pg\$1cron 的权限
<a name="PostgreSQL_pg_cron.permissions"></a>

安装 `pg_cron` 扩展需要 `rds_superuser` 权限。但是，可以（由 `pg_cron` 组/角色的成员）将使用 `rds_superuser` 的权限授予其他数据库用户，以便他们可以计划自己的任务。我们建议您仅在需要时才授予对 `cron` 架构的权限，前提是它可以改进生产环境中的操作。

要在 `cron` 架构中授予数据库用户权限，请运行以下命令：

```
postgres=> GRANT USAGE ON SCHEMA cron TO db-user;
```

这向 *db-user* 授予访问 `cron` 架构的权限，以便为他们有权限访问的对象计划 cron 任务。如果数据库用户没有权限，则在将错误消息发布到 `postgresql.log` 文件后，任务会失败，如下所示：

```
2020-12-08 16:41:00 UTC::@:[30647]:ERROR: permission denied for table table-name
2020-12-08 16:41:00 UTC::@:[27071]:LOG: background worker "pg_cron" (PID 30647) exited with exit code 1
```

换言之，请确保被授予对 `cron` 架构的权限的数据库用户也对他们计划安排的对象（表、架构等）拥有权限。

cron 任务的详细信息及其成功或失败情况也在 `cron.job_run_details` 表中捕获。有关更多信息，请参阅 [用于计划任务和捕获状态的表](#PostgreSQL_pg_cron.tables)。

## 计划 pg\$1cron 作业
<a name="PostgreSQL_pg_cron.examples"></a>

以下各节介绍了如何使用 `pg_cron` 作业安排各种管理任务。

**注意**  
创建 `pg_cron` 任务时，请检查 `max_worker_processes` 设置是否大于 `cron.max_running_jobs` 的数量。如果 `pg_cron` 任务耗尽后台工作进程，它将失败。原定设置的 `pg_cron` 任务数量为 `5`。有关更多信息，请参阅 [用于管理 pg\$1cron 扩展的参数](#PostgreSQL_pg_cron.parameters)。

**Topics**
+ [对表执行清理操作](#PostgreSQL_pg_cron.vacuum)
+ [清除 pg\$1cron 历史记录表](#PostgreSQL_pg_cron.job_run_details)
+ [仅将错误记录到 postgresql.log 文件中](#PostgreSQL_pg_cron.log_run)
+ [为原定设置数据库以外的数据库计划 cron 任务](#PostgreSQL_pg_cron.otherDB)

### 对表执行清理操作
<a name="PostgreSQL_pg_cron.vacuum"></a>

Autovacuum 在大多数情况下处理清理维护。但是，您可能希望在选择的时间计划对特定表执行清理操作。

另请参阅[在 Amazon RDS for PostgreSQL 上使用 PostgreSQL autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md)。

以下示例介绍了使用 `cron.schedule` 函数设置作业，以便每天 22:00 (GMT) 在特定表上使用 `VACUUM FREEZE`。

```
SELECT cron.schedule('manual vacuum', '0 22 * * *', 'VACUUM FREEZE pgbench_accounts');
 schedule
----------
1
(1 row)
```

运行上述示例之后，您可以按如下方式检查 `cron.job_run_details` 表中的历史记录。

```
postgres=> SELECT * FROM cron.job_run_details;
jobid  | runid | job_pid | database | username | command                        | status    | return_message | start_time                    | end_time
-------+-------+---------+----------+----------+--------------------------------+-----------+----------------+-------------------------------+-------------------------------
 1     | 1     | 3395    | postgres | adminuser| vacuum freeze pgbench_accounts | succeeded | VACUUM         | 2020-12-04 21:10:00.050386+00 | 2020-12-04 21:10:00.072028+00
(1 row)
```

下面的内容说明如何查询 `cron.job_run_details` 表以查看失败的任务。

```
postgres=> SELECT * FROM cron.job_run_details WHERE status = 'failed';
jobid | runid | job_pid | database | username | command                       | status | return_message                                   | start_time                    | end_time
------+-------+---------+----------+----------+-------------------------------+--------+--------------------------------------------------+-------------------------------+------------------------------
 5    | 4     | 30339   | postgres | adminuser| vacuum freeze pgbench_account | failed | ERROR: relation "pgbench_account" does not exist | 2020-12-04 21:48:00.015145+00 | 2020-12-04 21:48:00.029567+00
(1 row)
```

有关更多信息，请参阅 [用于计划任务和捕获状态的表](#PostgreSQL_pg_cron.tables)。

### 清除 pg\$1cron 历史记录表
<a name="PostgreSQL_pg_cron.job_run_details"></a>

`cron.job_run_details` 表包含 cron 作业的历史记录，随着时间的推移，这些历史记录可能会变得非常大。我们建议您计划清除此表的作业。例如，保留一周的条目可能足以进行故障排除。

以下示例使用 [cron.schedule](#PostgreSQL_pg_cron.schedule) 函数计划每天午夜运行以清除 `cron.job_run_details` 表的作业。这项工作只保留了过去七天的历史记录。使用您的 `rds_superuser` 账户计划作业，如下所示。

```
SELECT cron.schedule('0 0 * * *', $$DELETE 
    FROM cron.job_run_details 
    WHERE end_time < now() - interval '7 days'$$);
```

有关更多信息，请参阅 [用于计划任务和捕获状态的表](#PostgreSQL_pg_cron.tables)。

### 仅将错误记录到 postgresql.log 文件中
<a name="PostgreSQL_pg_cron.log_run"></a>

要防止向 `cron.job_run_details` 表中进行写入，请修改与 PostgreSQL 数据库实例关联的参数组，然后将 `cron.log_run` 参数设置为 off。`pg_cron` 扩展不再写入表，只会将错误捕获到 `postgresql.log` 文件中。有关更多信息，请参阅 [在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。

使用以下命令检查 `cron.log_run` 参数的值。

```
postgres=> SHOW cron.log_run;
```

有关更多信息，请参阅 [用于管理 pg\$1cron 扩展的参数](#PostgreSQL_pg_cron.parameters)。

### 为原定设置数据库以外的数据库计划 cron 任务
<a name="PostgreSQL_pg_cron.otherDB"></a>

`pg_cron` 的元数据全部保存在名为 `postgres` 的 PostgreSQL 默认数据库中。由于后台工件用于运行维护 cron 作业，因此您可以在 PostgreSQL 数据库实例中的任何数据库中计划作业。

**注意**  
只有具有 `rds_superuser` 角色或 `rds_superuser` 权限的用户才能列出数据库中的所有 cron 作业。其他用户只能在 `cron.job` 表中查看其自己的作业。

1. 在 cron 数据库中，以与平常使用 [cron.schedule](#PostgreSQL_pg_cron.schedule) 相同的方式计划作业。

   ```
   postgres=> SELECT cron.schedule('database1 manual vacuum', '29 03 * * *', 'vacuum freeze test_table');
   ```

1. 作为具有 `rds_superuser` 角色的用户，请更新刚创建的作业的数据库列，使其在 PostgreSQL 数据库实例中的另一个数据库中运行。

   ```
   postgres=> UPDATE cron.job SET database = 'database1' WHERE jobid = 106;
   ```

1.  通过查询 `cron.job` 表进行验证。

   ```
   postgres=> SELECT * FROM cron.job;
   jobid | schedule    | command                        | nodename  | nodeport | database | username  | active | jobname
   ------+-------------+--------------------------------+-----------+----------+----------+-----------+--------+-------------------------
   106   | 29 03 * * * | vacuum freeze test_table       | localhost | 8192     | database1| adminuser | t      | database1 manual vacuum
     1   | 59 23 * * * | vacuum freeze pgbench_accounts | localhost | 8192     | postgres | adminuser | t      | manual vacuum
   (2 rows)
   ```

**注意**  
在某些情况下，您可以添加打算在其他数据库上运行的 cron 作业。在这些情况下，在您更新正确的数据库列之前，该作业可能会尝试在默认数据库 (`postgres`) 中运行。如果用户名具有权限，则作业将在默认数据库中成功运行。

## pg\$1cron 扩展的参考
<a name="PostgreSQL_pg_cron.reference"></a>

您可以将以下参数、函数和表与 `pg_cron` 扩展搭配使用。有关更多信息，请参阅 pg\$1cron 文档中的[什么是 pg\$1cron？](https://github.com/citusdata/pg_cron)。

**Topics**
+ [用于管理 pg\$1cron 扩展的参数](#PostgreSQL_pg_cron.parameters)
+ [函数参考：cron.schedule](#PostgreSQL_pg_cron.schedule)
+ [函数参考：cron.unschedule](#PostgreSQL_pg_cron.unschedule)
+ [用于计划任务和捕获状态的表](#PostgreSQL_pg_cron.tables)

### 用于管理 pg\$1cron 扩展的参数
<a name="PostgreSQL_pg_cron.parameters"></a>

以下是用于控制 `pg_cron` 扩展行为的参数列表。


| 参数 | 说明 | 
| --- | --- | 
| cron.database\$1name |  保存 `pg_cron` 元数据的数据库。  | 
| cron.host |  要连接到 PostgreSQL 的主机名。您无法修改此值。  | 
| cron.log\$1run |  在 `job_run_details` 表中记录运行的每个任务。值为 `on` 或 `off`。有关更多信息，请参阅“[用于计划任务和捕获状态的表](#PostgreSQL_pg_cron.tables)”。  | 
| cron.log\$1statement |  在运行所有 cron 语句之前将其记入日志。值为 `on` 或 `off`。  | 
| cron.max\$1running\$1jobs |  可以同时运行的最大作业数。  | 
| cron.use\$1background\$1workers |  使用后台工作程序而不是客户端会话。您无法修改此值。  | 

使用以下 SQL 命令来显示这些参数及其值。

```
postgres=> SELECT name, setting, short_desc FROM pg_settings WHERE name LIKE 'cron.%' ORDER BY name;
```

### 函数参考：cron.schedule
<a name="PostgreSQL_pg_cron.schedule"></a>

此函数计划 cron 作业。作业最初是在默认 `postgres` 数据库中计划的。该函数返回一个表示作业标识符的 `bigint` 值。要计划作业在 PostgreSQL 数据库实例的其他数据库中运行，请参阅 [为原定设置数据库以外的数据库计划 cron 任务](#PostgreSQL_pg_cron.otherDB) 中的示例。

该函数有两种语法格式。

**语法**  

```
cron.schedule (job_name,
    schedule,
    command
);

cron.schedule (schedule,
    command
);
```

**参数**      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html)

**示例**  

```
postgres=> SELECT cron.schedule ('test','0 10 * * *', 'VACUUM pgbench_history');
 schedule
----------
      145
(1 row)

postgres=> SELECT cron.schedule ('0 15 * * *', 'VACUUM pgbench_accounts');
 schedule
----------
      146
(1 row)
```

### 函数参考：cron.unschedule
<a name="PostgreSQL_pg_cron.unschedule"></a>

此函数删除 cron 作业。您可以指定 `job_name` 或 `job_id`。策略可以确保您是删除作业计划的拥有者。该函数返回一个布尔值，指示成功或失败。

该函数使用以下语法格式。

**语法**  

```
cron.unschedule (job_id);

cron.unschedule (job_name);
```

**参数**      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html)

**示例**  

```
postgres=> SELECT cron.unschedule(108);
 unschedule
------------
 t
(1 row)

postgres=> SELECT cron.unschedule('test');
 unschedule
------------
 t
(1 row)
```

### 用于计划任务和捕获状态的表
<a name="PostgreSQL_pg_cron.tables"></a>

将以下各表用于计划 cron 作业和记录作业完成的方式。


| 表 | 描述 | 
| --- | --- | 
| cron.job |  包含有关每个计划作业的元数据。与此表的大多数交互应使用 `cron.schedule` 和 `cron.unschedule` 函数完成。  我们不建议直接授予对此表的更新或插入权限。这样做将允许用户更新 `username` 列，从而以 `rds-superuser` 身份运行。   | 
| cron.job\$1run\$1details |  包含过去运行的计划作业的历史信息。这对于调查运行的作业的状态、返回消息以及开始和结束时间非常有用。  为了防止此表无限增长，请定期清除此表。有关示例，请参阅[清除 pg\$1cron 历史记录表](#PostgreSQL_pg_cron.job_run_details)。   | 

# 使用 pglogical 跨实例同步数据
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical"></a>

所有当前可用的 RDS for PostgreSQL 版本都支持 `pglogical` 扩展。pglogic 扩展早于 PostgreSQL 在版本 10 中引入的功能类似的逻辑复制特征。有关更多信息，请参阅[为 Amazon RDS for PostgreSQL 执行逻辑复制](PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication.md)。

`pglogical` 扩展支持在两个或更多 RDS for PostgreSQL 数据库实例之间进行逻辑复制。它还支持在不同的 PostgreSQL 版本之间进行复制，以及在 RDS for PostgreSQL 数据库实例和 Aurora PostgreSQL 数据库集群上运行的数据库之间进行复制。`pglogical` 扩展使用发布-订阅模型将对表和其他对象（例如序列）的更改从发布者复制到订阅者。它依赖于复制插槽来确保更改从发布者节点同步到订阅者节点，定义如下。
+ *发布者节点*是作为要复制到其他节点的数据来源的 RDS for PostgreSQL 数据库实例。发布者节点定义要在发布集中复制的表。
+ *订阅者节点*是用于接收来自发布商的 WAL 更新的 RDS for PostgreSQL 数据库实例。订阅者创建订阅以连接到发布者并获取解码后的 WAL 数据。订阅者创建订阅时，将在发布者节点上创建复制插槽。

在下文中，您可以了解有关设置 `pglogical` 扩展的信息。

**Topics**
+ [pglogical 扩展的要求和限制](#Appendix.PostgreSQL.CommonDBATasks.pglogical.requirements-limitations)
+ [设置 pglogical 扩展](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)
+ [为 RDS for PostgreSQL 数据库实例设置逻辑复制](Appendix.PostgreSQL.CommonDBATasks.pglogical.setup-replication.md)
+ [在主要升级后重新建立逻辑复制](Appendix.PostgreSQL.CommonDBATasks.pglogical.recover-replication-after-upgrade.md)
+ [管理 RDS for PostgreSQL 的逻辑复制插槽](Appendix.PostgreSQL.CommonDBATasks.pglogical.handle-slots.md)
+ [pglogical 扩展的参数参考](Appendix.PostgreSQL.CommonDBATasks.pglogical.reference.md)

## pglogical 扩展的要求和限制
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.requirements-limitations"></a>

所有当前可用的 RDS for PostgreSQL 版本都支持 `pglogical` 扩展。

发布者节点和订阅者节点都必须设置为进行逻辑复制。

要从发布者复制到订阅用户的表必须具有相同的名称和相同的架构。这些表还必须包含相同的列，并且这些列必须使用相同的数据类型。发布者表和订阅者表必须具有相同的主键。我们建议您仅使用 PRIMARY KEY 作为唯一约束。

对于 CHECK 约束和 NOT NULL 约束，订阅者节点上的表可能比发布者节点上的表具有更宽松的约束。

`pglogical` 扩展提供了诸如双向复制之类的特征，PostgreSQL（版本 10 及更高版本）中内置的逻辑复制特征不支持这些特征。有关更多信息，请参阅[使用 pglogic 进行 PostgreSQL 双向复制](https://aws.amazon.com/blogs/database/postgresql-bi-directional-replication-using-pglogical/)。

# 设置 pglogical 扩展
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup"></a>

要在 RDS for PostgreSQL 数据库实例上设置 `pglogical` 扩展，首先要将 `pglogical` 添加到 RDS for PostgreSQL 数据库实例的自定义数据库参数组上的共享库中。您还需要将 `rds.logical_replication` 参数的值设置为 `1`，以开启逻辑解码。最后，在数据库中创建此扩展。您可以使用 AWS 管理控制台或 AWS CLI 执行这些任务。

您必须拥有 `rds_superuser` 角色的权限才能执行这些任务。

以下步骤假设您的 RDS for PostgreSQL 数据库实例与自定义数据库参数组相关联。有关创建自定义数据库参数组的信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

## 控制台
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.CON"></a>

**设置 pglogical 扩展**

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

1. 在导航窗格中，选择 RDS for PostgreSQL 数据库实例。

1. 打开 的**配置**选项卡。RDS for PostgreSQL 数据库实例的 Configuration（配置）选项卡。在实例详细信息中，找到 **Parameter group**（参数组）链接。

1. 选择此链接以打开与您的 RDS for PostgreSQL 数据库实例关联的自定义参数。

1. 在 **Parameters**（参数）搜索字段中，键入 `shared_pre` 以查找 `shared_preload_libraries` 参数。

1. 选择 **Edit parameters**（编辑参数）以访问属性值。

1. 将 `pglogical` 添加到 **Values**（值）字段的列表中。使用逗号分隔值列表中的项目。  
![\[添加了 pglogical 的 shared_preload_libraries 参数的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pglogical.png)

1. 找到 `rds.logical_replication` 参数并将其设置为 `1`，以开启逻辑复制。

1. 重启 RDS for PostgreSQL 数据库实例，以使更改生效。

1. 当实例可用时，可以使用 `psql`（或 pgAdmin）连接到 RDS for PostgreSQL 数据库实例。

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

1. 要验证 pglogical 是否初始化，可以运行以下命令。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pglogical
   (1 row)
   ```

1. 验证启用逻辑解码的设置，如下所示。

   ```
   SHOW wal_level;
   wal_level
   -----------
    logical
   (1 row)
   ```

1. 创建扩展，如下所示。

   ```
   CREATE EXTENSION pglogical;
   EXTENSION CREATED
   ```

1. 选择**保存更改**。

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

1. 从数据库列表中选择 RDS for PostgreSQL 数据库实例以将其选中，然后从 Actions（操作）菜单中选择 **Reboot**（重启）。

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.CLI"></a>

**设置 pglogical 扩展**

要使用 AWS CLI 设置 pglogical，您可以调用 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) 操作来修改自定义参数组中的某些参数，如以下过程所示。

1. 使用以下 AWS CLI 命令向 `shared_preload_libraries` 参数中添加 `pglogical`。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=pglogical,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用以下 AWS CLI 命令将 `rds.logical_replication` 设置为 `1`，以针对 RDS for PostgreSQL 数据库实例开启逻辑解码功能。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例，以便初始化 pglogical 库。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 当实例可用时，使用 `psql` 连接到 RDS for PostgreSQL 数据库实例。

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

1. 创建扩展，如下所示。

   ```
   CREATE EXTENSION pglogical;
   EXTENSION CREATED
   ```

1. 使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

# 为 RDS for PostgreSQL 数据库实例设置逻辑复制
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.setup-replication"></a>

以下过程说明如何在两个 RDS for PostgreSQL 数据库实例之间启动逻辑复制。这些步骤假设来源（发布者）和目标（订阅者）都如[设置 pglogical 扩展](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)中所述设置了 `pglogical` 扩展。

**注意**  
订阅用户节点的 `node_name` 不能以 `rds` 开头。

**创建发布者节点并定义要复制的表**

这些步骤假设您的 RDS for PostgreSQL 数据库实例有一个数据库，其中包含一个或多个您要复制到另一个节点的表。您需要在订阅者上根据发布者重新创建表结构，因此，如果需要，首先获取表结构。为此，您可以使用 `psql` 元命令 `\d tablename`，然后在订阅者实例上创建相同的表。以下过程在发布者（来源）上创建示例表以用于演示目的。

1. 使用 `psql` 连接到具有要用作订阅者来源的表的实例。

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

   如果没有现有表要复制，可以按如下方式创建示例表。

   1. 使用以下 SQL 语句创建一个示例表。

      ```
      CREATE TABLE docs_lab_table (a int PRIMARY KEY);
      ```

   1. 使用以下 SQL 语句用生成的数据填充表。

      ```
      INSERT INTO docs_lab_table VALUES (generate_series(1,5000));
      INSERT 0 5000
      ```

   1. 使用以下 SQL 语句验证表中是否存在数据。

      ```
      SELECT count(*) FROM docs_lab_table;
      ```

1. 将这一 RDS for PostgreSQL 数据库实例标识为发布者节点，如下所示。

   ```
   SELECT pglogical.create_node(
       node_name := 'docs_lab_provider',
       dsn := 'host=source-instance.aws-region.rds.amazonaws.com port=5432 dbname=labdb');
    create_node
   -------------
      3410995529
   (1 row)
   ```

1. 将要复制的表添加到默认的复制集。有关复制集的更多信息，请参阅 pglogical 文档中的[复制集](https://github.com/2ndQuadrant/pglogical/tree/REL2_x_STABLE/docs#replication-sets)。

   ```
   SELECT pglogical.replication_set_add_table('default', 'docs_lab_table', 'true', NULL, NULL);
    replication_set_add_table
     ---------------------------
     t
     (1 row)
   ```

发布者节点设置已完成。现在，您可以设置订阅者节点以接收来自发布者的更新。

**设置订阅者节点并创建订阅以接收更新**

这些步骤假设已使用 `pglogical` 扩展设置了 RDS for PostgreSQL 数据库实例。有关更多信息，请参阅 [设置 pglogical 扩展](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)。

1. 使用 `psql` 连接到要从发布者接收更新的实例。

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

1. 在订阅者 RDS for PostgreSQL 数据库实例上，创建与发布者上存在的相同表。在本例中，该表为 `docs_lab_table`。您可以按如下所示创建表。

   ```
   CREATE TABLE docs_lab_table (a int PRIMARY KEY);
   ```

1. 验证此表为空。

   ```
   SELECT count(*) FROM docs_lab_table;
    count
   -------
     0
   (1 row)
   ```

1. 将这一 RDS for PostgreSQL 数据库实例标识为订阅者节点，如下所示。

   ```
   SELECT pglogical.create_node(
       node_name := 'docs_lab_target',
       dsn := 'host=target-instance.aws-region.rds.amazonaws.com port=5432 sslmode=require dbname=labdb user=postgres password=********');
    create_node
   -------------
      2182738256
   (1 row)
   ```

1. 创建订阅。

   ```
   SELECT pglogical.create_subscription(
      subscription_name := 'docs_lab_subscription',
      provider_dsn := 'host=source-instance.aws-region.rds.amazonaws.com port=5432 sslmode=require dbname=labdb user=postgres password=*******',
      replication_sets := ARRAY['default'],
      synchronize_data := true,
      forward_origins := '{}' );  
    create_subscription
   ---------------------
   1038357190
   (1 row)
   ```

   完成此步骤后，将在订阅者上的表中创建发布者上表中的数据。您可以使用以下 SQL 查询来验证是否已发生这种情况。

   ```
   SELECT count(*) FROM docs_lab_table;
    count
   -------
     5000
   (1 row)
   ```

此后，对发布者上的表所做的更改将复制到订阅者上的表中。

# 在主要升级后重新建立逻辑复制
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.recover-replication-after-upgrade"></a>

对于设置为逻辑复制的发布者节点的 RDS for PostgreSQL 数据库实例，在可以对其执行主要版本升级之前，您必须删除所有复制插槽，即使是不活动的复制插槽也是如此。我们建议您暂时从发布者节点转移数据库事务，删除复制插槽，升级 RDS for PostgreSQL 数据库实例，然后重新建立并重新启动复制。

复制插槽仅托管在发布者节点上。逻辑复制场景中的 RDS for PostgreSQL 订阅者节点没有可删除的插槽，但当它被指定为对发布者具有订阅的订阅者节点时，它无法升级到主要版本。在升级 RDS for PostgreSQL 订阅者节点之前，请删除订阅和节点。有关更多信息，请参阅。[管理 RDS for PostgreSQL 的逻辑复制插槽](Appendix.PostgreSQL.CommonDBATasks.pglogical.handle-slots.md)

## 确定逻辑复制已中断
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.recover-replication-after-upgrade.identifying-the-issue"></a>

您可以通过查询发布者节点或订阅者节点来确定复制过程是否已中断，如下所示。

**检查发布者节点**
+ 使用 `psql` 连接到发布者节点，然后查询 `pg_replication_slots` 函数。注意活动列中的值。通常，这将返回 `t`（true），表明复制处于活动状态。如果查询返回 `f`（false），则表明向订阅者的复制已停止。

  ```
  SELECT slot_name,plugin,slot_type,active FROM pg_replication_slots;
                      slot_name              |      plugin      | slot_type | active
  -------------------------------------------+------------------+-----------+--------
   pgl_labdb_docs_labcb4fa94_docs_lab3de412c | pglogical_output | logical   | f
  (1 row)
  ```

**检查订阅者节点**

在订阅者节点上，您可以通过三种不同的方式检查复制的状态。
+ 浏览订阅者节点上的 PostgreSQL 日志，以查找失败消息。该日志使用包含退出代码 1 的消息来标识故障，如下所示。

  ```
  2022-07-06 16:17:03 UTC::@:[7361]:LOG: background worker "pglogical apply 16404:2880255011" (PID 14610) exited with exit code 1
  2022-07-06 16:19:44 UTC::@:[7361]:LOG: background worker "pglogical apply 16404:2880255011" (PID 21783) exited with exit code 1
  ```
+ 查询 `pg_replication_origin` 函数。使用 `psql` 连接到订阅者节点上的数据库并查询 `pg_replication_origin` 函数，如下所示。

  ```
  SELECT * FROM pg_replication_origin;
   roident | roname
  ---------+--------
  (0 rows)
  ```

  结果集为空表示复制已中断。正常情况下，您将看到如下输出。

  ```
     roident |                       roname
    ---------+----------------------------------------------------
           1 | pgl_labdb_docs_labcb4fa94_docs_lab3de412c
    (1 row)
  ```
+ 查询 `pglogical.show_subscription_status` 函数，如以下示例所示。

  ```
  SELECT subscription_name,status,slot_name FROM pglogical.show_subscription_status();
       subscription_name | status |              slot_name
  ---====----------------+--------+-------------------------------------
   docs_lab_subscription | down   | pgl_labdb_docs_labcb4fa94_docs_lab3de412c
  (1 row)
  ```

  此输出显示复制已中断。它的状态为 `down`。通常，输出将状态显示为 `replicating`。

如果您的逻辑复制过程已中断，则可以按照以下步骤重新建立复制。

**在发布者节点和订阅者节点之间重新建立逻辑复制**

要重新建立复制，请先断开订阅者与发布者节点的连接，然后重新建立订阅，如这些步骤所述。

1. 使用 `psql` 连接到订阅者节点，如下所示。

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

1. 通过使用 `pglogical.alter_subscription_disable` 函数停用订阅。

   ```
   SELECT pglogical.alter_subscription_disable('docs_lab_subscription',true);
    alter_subscription_disable
   ----------------------------
    t
   (1 row)
   ```

1. 通过查询 `pg_replication_origin` 获取发布者节点的标识符，如下所示。

   ```
   SELECT * FROM pg_replication_origin;
    roident |               roname
   ---------+-------------------------------------
          1 | pgl_labdb_docs_labcb4fa94_docs_lab3de412c
   (1 row)
   ```

1. 将上一步的响应与 `pg_replication_origin_create` 命令一起使用，以分配重新建立时订阅可以使用的标识符。

   ```
   SELECT pg_replication_origin_create('pgl_labdb_docs_labcb4fa94_docs_lab3de412c');
     pg_replication_origin_create
   ------------------------------
                               1
   (1 row)
   ```

1. 通过传递其状态为 `true` 的名称来打开订阅，如下面的示例所示。

   ```
   SELECT pglogical.alter_subscription_enable('docs_lab_subscription',true);
     alter_subscription_enable
   ---------------------------
    t
   (1 row)
   ```

检查节点的状态。其状态应为 `replicating`，如本例所示。

```
SELECT subscription_name,status,slot_name
  FROM pglogical.show_subscription_status();
             subscription_name |   status    |              slot_name
-------------------------------+-------------+-------------------------------------
 docs_lab_subscription         | replicating | pgl_labdb_docs_lab98f517b_docs_lab3de412c
(1 row)
```

检查发布者节点上订阅者的复制插槽的状态。插槽的 `active` 列应返回 `t`（true），表示已重新建立复制。

```
SELECT slot_name,plugin,slot_type,active
  FROM pg_replication_slots;
                    slot_name              |      plugin      | slot_type | active
-------------------------------------------+------------------+-----------+--------
 pgl_labdb_docs_lab98f517b_docs_lab3de412c | pglogical_output | logical   | t
(1 row)
```

# 管理 RDS for PostgreSQL 的逻辑复制插槽
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.handle-slots"></a>

对于在逻辑复制场景中充当发布者节点的 RDS for PostgreSQL 数据库实例，在对其执行主要版本升级之前，必须删除该实例上的复制插槽。主要版本升级预检查过程会通知您，在插槽被删除之前，升级无法继续。

要从 RDS for PostgreSQL 数据库实例中删除插槽，请先删除订阅，然后删除插槽。

要识别使用 `pglogical` 扩展创建的复制插槽，请登录到每个数据库并获取节点的名称。当您查询订阅者节点时，您会在输出中得到发布者节点和订阅者节点，如本示例所示。

```
SELECT * FROM pglogical.node;
node_id   |     node_name
------------+-------------------
 2182738256 | docs_lab_target
 3410995529 | docs_lab_provider
(2 rows)
```

您可以通过以下查询获取有关订阅的详细信息。

```
SELECT sub_name,sub_slot_name,sub_target
  FROM pglogical.subscription;
 sub_name |         sub_slot_name          | sub_target
----------+--------------------------------+------------
  docs_lab_subscription     | pgl_labdb_docs_labcb4fa94_docs_lab3de412c | 2182738256
(1 row)
```

现在您可以删除订阅，如下所示。

```
SELECT pglogical.drop_subscription(subscription_name := 'docs_lab_subscription');
 drop_subscription
-------------------
                 1
(1 row)
```

删除订阅后，您可以删除该节点。

```
SELECT pglogical.drop_node(node_name := 'docs-lab-subscriber');
 drop_node
-----------
 t
(1 row)
```

您可以验证该节点是否不再存在，如下所示。

```
SELECT * FROM pglogical.node;
 node_id | node_name
---------+-----------
(0 rows)
```

# pglogical 扩展的参数参考
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.reference"></a>

在表中，您可以找到与 `pglogical` 扩展关联的参数。`pglogical.conflict_log_level` 和 `pglogical.conflict_resolution` 等参数用于处理更新冲突。当对订阅来自发布者的更改的相同表进行本地更改时，可能会出现冲突。在不同情况下也可能发生冲突，例如双向复制或当多个订阅者从同一个发布者进行复制时。有关更多信息，请参阅[使用 pglogical 进行 PostgreSQL 双向复制](https://aws.amazon.com/blogs/database/postgresql-bi-directional-replication-using-pglogical/)。


| 参数 | 说明 | 
| --- | --- | 
| pglogical.batch\$1inserts | 在可能时执行批量插入。默认情况下未设置。更改为“1”将打开，更改为“0”将关闭。 | 
| pglogical.conflict\$1log\$1level | 设置用于记录已解决的冲突的日志级别。支持的字符串值为 debug5、debug4、debug3、debug2、debug1、info、notice、warning、error、log、fatal、panic。 | 
| pglogical.conflict\$1resolution | 设置在冲突可以解决时用来解决冲突的方法。支持的字符串值为 error、apply\$1remote、keep\$1local、last\$1update\$1wins、first\$1update\$1wins。 | 
| pglogical.extra\$1connection\$1options | 要添加到所有对等节点连接的连接选项。 | 
| pglogical.synchronous\$1commit | pglogical 专用的同步提交值 | 
| pglogical.use\$1spi | 使用 SPI（服务器编程接口）而非低级 API 来应用更改。设置为“1”将打开，设置为“0”将关闭。有关 SPI 的更多信息，请参阅 PostgreSQL 文档中的[服务器编程接口](https://www.postgresql.org/docs/current/spi.html)。 | 

# 使用 pgactive 支持主动-主动复制
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive"></a>

`pgactive` 扩展使用主动-主动复制来支持和协调多个 RDS for PostgreSQL 数据库上的写入操作。Amazon RDS for PostgreSQL 支持以下版本的 `pgactive` 扩展。
+ RDS for PostgreSQL 17.0 和所有更高版本
+ RDS for PostgreSQL 16.1 及更高的 16 版本
+ RDS for PostgreSQL 15.4-R2 及更高的 15 版本
+ RDS for PostgreSQL 14.10 及更高的 14 版本
+ RDS for PostgreSQL 13.13 及更高的 13 版本
+ RDS for PostgreSQL 12.17 及更高的 12 版本
+ RDS for PostgreSQL 11.22

**注意**  
当复制配置中的多个数据库上有写入操作时，可能会发生冲突。有关更多信息，请参阅 [处理主动-主动复制中的冲突](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-conflicts.md)。

**Topics**
+ [pgactive 扩展的局限性](#Appendix.PostgreSQL.CommonDBATasks.pgactive.requirements-limitations)
+ [初始化 pgactive 扩展功能](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)
+ [为 RDS for PostgreSQL 数据库实例设置主动-主动复制](Appendix.PostgreSQL.CommonDBATasks.pgactive.setup-replication.md)
+ [衡量 pgactive 成员之间的复制延迟](Appendix.PostgreSQL.CommonDBATasks.pgactive.replicationlag.md)
+ [配置 pgactive 扩展的参数设置](Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.md)
+ [了解双活冲突](Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.replication.md)
+ [了解 pgactive 架构](Appendix.PostgreSQL.CommonDBATasks.pgactive.schema.md)
+ [pgactive 函数参考](pgactive-functions-reference.md)
+ [处理主动-主动复制中的冲突](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-conflicts.md)
+ [处理主动-主动复制中的序列](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-sequences.md)

## pgactive 扩展的局限性
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.requirements-limitations"></a>
+ 所有表都需要主键，否则不允许使用更新和删除。不应更新“主键”列中的值。
+ 序列可能存在间隙，有时可能不遵循顺序。不会复制序列。有关更多信息，请参阅 [处理主动-主动复制中的序列](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-sequences.md)。
+ 不会复制 DDL 和大型对象。
+ 辅助唯一索引可能会导致数据差异。
+ 组中所有节点上的排序规则需要相同。
+ 跨节点负载均衡是一种反模式。
+ 大型事务可能会导致复制滞后。

# 初始化 pgactive 扩展功能
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup"></a>

要在 RDS for PostgreSQL 数据库实例上初始化 `pgactive` 扩展功能，请将参数 `rds.enable_pgactive` 的值设置为 `1`，然后在数据库中创建扩展。这样做会自动开启参数 `rds.logical_replication` 和 `track_commit_timestamp` 并将 `wal_level` 的值设置为 `logical`。

您必须拥有 `rds_superuser` 角色的权限才能执行这些任务。

您可以使用 AWS 管理控制台或 AWS CLI 创建所需的 RDS for PostgreSQL 数据库实例。以下步骤假设您的 RDS for PostgreSQL 数据库实例与自定义数据库参数组相关联。有关创建自定义数据库参数组的信息，请参阅[Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

## 控制台
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.CON"></a>

**初始化 pgactive 扩展功能**

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

1. 在导航窗格中，选择 RDS for PostgreSQL 数据库实例。

1. 打开 RDS for PostgreSQL 数据库实例的**配置**选项卡。在实例详细信息中，找到**数据库实例参数组**链接。

1. 选择此链接以打开与 RDS for PostgreSQL 数据库实例关联的自定义参数。

1. 找到 `rds.enable_pgactive` 参数，并将其设置为 `1` 以初始化 `pgactive` 功能。

1. 选择**保存更改**。

1. 在 Amazon RDS 控制台的导航窗格中，选择**数据库**。

1. 选择您的 RDS for PostgreSQL 数据库实例，然后从**操作**菜单中选择**重启**。

1. 确认数据库实例重启，以便您的更改生效。

1. 当数据库实例可用时，您可以使用 `psql` 或任何其它 PostgreSQL 客户端连接到 RDS for PostgreSQL 数据库实例。

   以下示例假设 RDS for PostgreSQL 数据库实例有一个名为 *postgres* 的原定设置数据库。

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

1. 要验证 pgactive 是否初始化，可以运行以下命令。

   ```
   postgres=>SELECT setting ~ 'pgactive' 
   FROM pg_catalog.pg_settings
   WHERE name = 'shared_preload_libraries';
   ```

   如果 `pgactive` 在 `shared_preload_libraries` 中，则前面的命令将返回以下内容：

   ```
   ?column? 
   ----------
    t
   ```

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.CLI"></a>

**初始化 pgactive 扩展功能**

要使用 AWS CLI 设置 `pgactive`，请调用 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) 操作来修改自定义参数组中的某些参数，如以下过程所示。

1. 使用以下 AWS CLI 命令将 `rds.enable_pgactive` 设置为 `1`，以初始化 RDS for PostgreSQL 数据库实例的 `pgactive` 功能。

   ```
   postgres=>aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=rds.enable_pgactive,ParameterValue=1,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例，以便初始化 `pgactive` 库。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 当实例可用时，使用 `psql` 连接到 RDS for PostgreSQL 数据库实例。

   ```
   psql --host=mydb.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master user --password=PASSWORD --dbname=postgres
   ```

1. 要验证 pgactive 是否初始化，可以运行以下命令。

   ```
   postgres=>SELECT setting ~ 'pgactive' 
   FROM pg_catalog.pg_settings
   WHERE name = 'shared_preload_libraries';
   ```

   如果 `pgactive` 在 `shared_preload_libraries` 中，则前面的命令将返回以下内容：

   ```
   ?column? 
   ----------
    t
   ```

# 为 RDS for PostgreSQL 数据库实例设置主动-主动复制
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.setup-replication"></a>

以下过程说明如何在 `pgactive` 可用的两个 RDS for PostgreSQL 数据库实例之间启动主动-主动复制。要运行多区域高可用性示例，您需要在两个不同的区域中部署 Amazon RDS for PostgreSQL 实例，并设置 VPC 对等。有关更多信息，请参阅 [VPC 对等](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html)。

**注意**  
在多个区域之间发送流量可能会产生额外费用。

这些步骤假定已使用 `pgactive` 扩展启用 RDS for PostgreSQL 数据库实例。有关更多信息，请参阅 [初始化 pgactive 扩展功能](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)。

**使用 `pgactive` 扩展配置第一个 RDS for PostgreSQL 数据库实例**

以下示例说明如何创建 `pgactive` 组，以及在 RDS for PostgreSQL 数据库实例上创建 `pgactive` 扩展所需的其它步骤。

1. 使用 `psql` 或其它客户端工具连接第一个 RDS for PostgreSQL 数据库实例。

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

1. 使用以下命令在 RDS for PostgreSQL 实例上创建数据库：

   ```
   postgres=> CREATE DATABASE app;
   ```

1. 使用以下命令将连接切换到新数据库：

   ```
   \c app
   ```

1. 使用以下 SQL 语句创建并填充示例表：

   1. 使用以下 SQL 语句创建一个示例表。

      ```
      app=> CREATE SCHEMA inventory;
      CREATE TABLE inventory.products (
      id int PRIMARY KEY, product_name text NOT NULL,
      created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP);
      ```

   1. 使用以下 SQL 语句用一些示例数据填充表。

      ```
      app=> INSERT INTO inventory.products (id, product_name)
      VALUES (1, 'soap'), (2, 'shampoo'), (3, 'conditioner');
      ```

   1. 使用以下 SQL 语句验证表中是否存在数据。

      ```
       app=>SELECT count(*) FROM inventory.products;
      
       count
      -------
       3
      ```

1. 在现有数据库上创建 `pgactive` 扩展。

   ```
   app=> CREATE EXTENSION pgactive;
   ```

1. 要安全地创建并初始化 pgactive 组，请使用以下命令：

   ```
   app=>
   -- connection info for endpoint1
   CREATE SERVER pgactive_server_endpoint1
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint1>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint1
       OPTIONS (user 'postgres', password '<password>');
         -- connection info for endpoint2
   CREATE SERVER pgactive_server_endpoint2
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint2>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint2
       OPTIONS (user 'postgres', password '<password>');
   ```

   现在，您可以初始化复制组并添加此第一个实例：

   ```
   SELECT pgactive.pgactive_create_group(
       node_name := 'endpoint1-app',
       node_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint1'
   
   );
   ```

   使用以下命令作为替代方案（安全性较低）来创建并初始化 pgactive 组：

   ```
   app=> SELECT pgactive.pgactive_create_group(
       node_name := 'node1-app',
       node_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD');
   ```

   node1-app 是您分配的名称，用于唯一标识 `pgactive` 组中的节点。
**注意**  
要在可公开访问的数据库实例上成功执行此步骤，必须通过将 `rds.custom_dns_resolution` 参数设置为 `1` 将其开启。

1. 要检查数据库实例是否就绪，请使用以下命令：

   ```
   app=> SELECT pgactive.pgactive_wait_for_node_ready();
   ```

   如果命令成功，您可以看到以下输出：

   ```
   pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

**配置第二个 RDS for PostgreSQL 实例并将其加入 `pgactive` 组**

以下示例说明如何将 RDS for PostgreSQL 数据库实例加入 `pgactive` 组，以及在数据库实例上创建 `pgactive` 扩展所需的其它步骤。

这些步骤假设已使用 `pgactive` 扩展设置了其它 RDS for PostgreSQL 数据库实例。有关更多信息，请参阅 [初始化 pgactive 扩展功能](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)。

1. 使用 `psql` 连接到要从发布者接收更新的实例。

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

1. 使用以下命令在第二个 RDS for PostgreSQL 数据库实例上创建数据库：

   ```
   postgres=> CREATE DATABASE app;
   ```

1. 使用以下命令将连接切换到新数据库：

   ```
   \c app
   ```

1. 在现有数据库上创建 `pgactive` 扩展。

   ```
   app=> CREATE EXTENSION pgactive;
   ```

1. 使用以下命令以更安全的方式将 RDS for PostgreSQL 第二个数据库实例加入 `pgactive` 组：

   ```
   -- connection info for endpoint1
   CREATE SERVER pgactive_server_endpoint1
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint1>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint1
       OPTIONS (user 'postgres', password '<password>');
   
   -- connection info for endpoint2
   CREATE SERVER pgactive_server_endpoint2
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint2>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint2
       OPTIONS (user 'postgres', password '<password>');
   ```

   ```
   SELECT pgactive.pgactive_join_group(
       node_name := 'endpoint2-app',
       node_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint2',
       join_using_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint1'
   );
   ```

   使用以下命令作为替代方案（安全性较低）将 RDS for PostgreSQL 第二个数据库实例加入 `pgactive` 组

   ```
   app=> SELECT pgactive.pgactive_join_group(
   node_name := 'node2-app',
   node_dsn := 'dbname=app host=secondinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD',
   join_using_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD');
   ```

   node2-app 是您分配的名称，用于唯一标识 `pgactive` 组中的节点。

1. 要检查数据库实例是否就绪，请使用以下命令：

   ```
   app=> SELECT pgactive.pgactive_wait_for_node_ready(); 
   ```

   如果命令成功，您可以看到以下输出：

   ```
   pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

   如果第一个 RDS for PostgreSQL 数据库相对较大，则可以看到 `pgactive.pgactive_wait_for_node_ready()` 正在发出还原操作的进度报告。输出看上去类似于以下内容：

   ```
   NOTICE:  restoring database 'app', 6% of 7483 MB complete
   NOTICE:  restoring database 'app', 42% of 7483 MB complete
   NOTICE:  restoring database 'app', 77% of 7483 MB complete
   NOTICE:  restoring database 'app', 98% of 7483 MB complete
   NOTICE:  successfully restored database 'app' from node node1-app in 00:04:12.274956
    pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

   此后，`pgactive` 将在两个数据库实例之间同步数据。

1. 您可以使用以下命令来验证第二个数据库实例的数据库是否具有数据：

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   如果数据成功同步，您将看到以下输出：

   ```
    count
   -------
    3
   ```

1. 运行以下命令插入新值：

   ```
   app=> INSERT INTO inventory.products (id, product_name) VALUES (4, 'lotion');
   ```

1. 连接到第一个数据库实例的数据库并运行以下查询：

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   如果已初始化主动-主动复制，则输出类似于以下内容：

   ```
   count
   -------
    4
   ```

**从 `pgactive` 组中分离和移除数据库实例**

您可以使用以下步骤从 `pgactive` 组中分离和移除数据库实例：

1. 您可以使用以下命令将第二个数据库实例与第一个数据库实例分离：

   ```
   app=> SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app']);
   ```

1. 使用以下命令从第二个数据库实例中移除 `pgactive` 扩展：

   ```
   app=> SELECT * FROM pgactive.pgactive_remove();
   ```

   要强制移除此扩展，请执行以下操作：

   ```
   app=> SELECT * FROM pgactive.pgactive_remove(true);
   ```

1. 使用以下命令删除扩展：

   ```
   app=> DROP EXTENSION pgactive;
   ```

# 衡量 pgactive 成员之间的复制延迟
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.replicationlag"></a>

您可以使用以下查询来查看 `pgactive` 成员之间的复制延迟。在每个 `pgactive` 节点上运行此查询以了解全部信息。

```
    
app=> SELECT * FROM pgactive.pgactive_get_replication_lag_info();
│-[ RECORD 1 ]--------+---------------------------------------------
│node_name            | node2-app
│node_sysid           | 7481018224801653637
│application_name     | pgactive:7481018224801653637:send
│slot_name            | pgactive_16385_7481018224801653637_0_16385__
│active               | t
│active_pid           | 783486
│pending_wal_decoding | 0
│pending_wal_to_apply | 0
│restart_lsn          | 0/2108150
│confirmed_flush_lsn  | 0/2154690
│sent_lsn             | 0/2154690
│write_lsn            | 0/2154690
│flush_lsn            | 0/2154690
│replay_lsn           | 0/2154690
│-[ RECORD 2 ]--------+---------------------------------------------
│node_name            | node1-app
│node_sysid           | 7481018033434600853
│application_name     | pgactive:7481018033434600853:send
│slot_name            | pgactive_16385_7481018033434600853_0_16385__
│active               | t
│active_pid           | 783488
│pending_wal_decoding | 0
│pending_wal_to_apply | 0
│restart_lsn          | 0/20F5AD0
│confirmed_flush_lsn  | 0/214EF68
│sent_lsn             | 0/214EF68
│write_lsn            | 0/214EF68
│flush_lsn            | 0/214EF68
│replay_lsn           | 0/214EF68
```

至少需要监控以下诊断信息：

active  
在 active 为 false 时设置警报，这表示该插槽当前未被使用（订阅用户实例已断开与发布者的连接）。

pending\$1wal\$1decoding  
在 PostgreSQL 的逻辑复制中，WAL 文件以二进制格式存储。发布者必须解码这些 WAL 更改并将其转换为逻辑更改（例如插入、更新或删除操作）。  
指标 pending\$1wal\$1decoding 显示发布者端等待解码的 WAL 文件的数量。  
该数量可能因以下因素增大：  
+ 当未连接订阅用户时，active 状态将为 false，并且 pending\$1wal\$1decoding 将增大
+ 该插槽处于 active 状态，但发布者无法跟上 WAL 更改的量

pending\$1wal\$1to\$1apply  
指标 pending\$1wal\$1apply 表示订阅用户端等待应用的 WAL 文件的数量。  
有以下几个因素可能会阻止订阅用户应用更改，并且可能导致出现磁盘已满的情况：  
+ 架构差异 – 例如，当您在名为 sample 的表的 WAL 流中做出了更改，但订阅用户端却不存在该表时
+ 主键列中的值已更新
+ 辅助唯一索引可能会导致数据差异

# 配置 pgactive 扩展的参数设置
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters"></a>

您可以使用以下查询来查看与 `pgactive` 扩展关联的所有参数。

```
app=> SELECT * FROM pg_settings WHERE name LIKE 'pgactive.%';
```

您可以使用各种参数配置 `pgactive` 扩展。可通过 AWS 管理控制台或 AWS CLI 界面设置这些参数。

## pgactive 扩展的主要参数
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.mainparams"></a>

下表提供了 `pgactive` 扩展的主要参数的参考：


| 参数 | 单位 | 默认值 | 说明 | 
| --- | --- | --- | --- | 
| pgactive.conflict\$1logging\$1include\$1tuples | `boolean` | –  | 记录 `pgactive` 扩展的完整元组信息。  要使更改生效，必须先重启服务器。  | 
| pgactive.log\$1conflicts\$1to\$1table | `boolean` | –  | 确定 `pgactive` 扩展是否已将检测到的冲突记录到 `pgactive.pgactive_conflict_history` 表中。有关更多信息，请参阅冲突日志记录。  要使更改生效，必须先重启服务器。  | 
| pgactive.log\$1conflicts\$1to\$1logfile | `boolean` | –  | 确定 `pgactive` 扩展是否已将检测到的冲突记录到 PostgreSQL 日志文件中。有关更多信息，请参阅冲突日志记录。  要使更改生效，必须先重启服务器。  | 
| pgactive.synchronous\$1commit | `boolean` | off | 确定 pgactive 应用工作线程的提交行为。在此设置处于禁用（off）状态时，应用工作线程会执行异步提交，这将提高 PostgreSQL 在应用操作期间的吞吐量，但会延迟向上游发送的重播确认。将此设置设为 `off` 始终是安全的，不会导致事务丢失或跳过。此设置仅影响下游节点上的磁盘刷新时间以及向上游发送确认的时间。系统会延迟发送重播刷新确认，直到通过检查点或定期工作等不相关的操作将提交刷新到磁盘。但是，如果上游具有 `synchronous_standby_names` 中列出的下游，则将此设置设定为 `off` 会导致上游的同步提交需要更长的时间才能向客户端返回成功响应。在此情况下，可将该参数设置为 `on`。  即使将该参数设置为 `on` 并在 `synchronous_standby_names` 中列出了节点，主动-主动配置中也仍然可能发生复制冲突。这是因为系统缺少节点间锁定和全局快照管理，可能导致不同节点上的并发事务修改同一元组。此外，事务仅在上游节点上提交后才开始复制。启用同步提交并不会将 pgactive 扩展转换为始终一致的系统。  | 
| pgactive.temp\$1dump\$1directory | `string` | – | 定义数据库克隆操作在初始设置期间所需的临时存储路径。此目录必须可由 postgres 用户写入，并且拥有足够的存储空间来容纳完整的数据库转储。系统仅在通过逻辑复制操作进行初始数据库设置期间使用此位置。`pgactive_init_copy command` 不使用该参数。 | 
| pgactive.max\$1ddl\$1lock\$1delay | `milliseconds` | `-1` | 指定在强制中止并发写入事务之前，DDL 锁的最长等待时间。默认值为 `-1`，这将使用 `max_standby_streaming_delay` 中设置的值。该参数接受时间单位。例如，可以将它设置为 10s 来表示 10 秒。在此等待期间，系统会尝试获取 DDL 锁，同时等待正在进行的写入事务完成提交或回滚。有关更多信息，请参阅“DDL 锁定”。 | 
| pgactive.ddl\$1lock\$1timeout | `milliseconds` | `-1` | 指定 DDL 锁为获取锁而尝试等待的时长。默认值为 `-1`，这将使用 lock\$1timeout 中指定的值。您可以使用时间单位来设置此参数，例如 10s 表示 10 秒。此计时器仅控制为获取 DDL 锁而等待的时长。在系统获取锁并开始 DDL 操作后，计时器将停止。此参数不会限制可将 DDL 锁保持的总持续时间或总 DDL 操作时间。要控制操作的总持续时间，请改用 `statement_timeout`。有关更多信息，请参阅“DDL 锁定”。 | 
| pgactive.debug\$1trace\$1ddl\$1locks\$1level | `boolean` | –  | 覆盖 `pgactive` 扩展中 DDL 锁定操作的默认调试日志级别。配置此设置后，会导致系统在 LOG 调试级别而非默认级别发出与 DDL 锁相关的消息。使用此参数可监控 DDL 锁定活动，而无需在整个服务器上启用详细 `DEBUG1` 或 `DEBUG2` 日志级别。 可用日志级别（按详细程度升序排列）： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 有关监控选项的更多信息，请参阅“监控全局 DDL 锁”。  对此设置所做的更改会在重新加载配置后生效。您无需重新启动服务器。   | 

## pgactive 扩展的其他参数
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.addparams"></a>

下表列出了 `pgactive` 扩展中不常用的配置选项和可用的内部配置选项。


| 参数 | 单位 | 默认值 | 说明 | 
| --- | --- | --- | --- | 
| pgactive.debug\$1apply\$1delay | `integer` | – |  为 `pgactive.pgactive_connections` 条目中未明确设定应用延迟的已配置连接设置应用延迟（以毫秒为单位）。此延迟是在节点创建或加入时设置的，pgactive 不会在对等节点上重播事务，直到提交后至少经过指定的毫秒数。 主要用于在测试环境中模拟高延迟网络，以便更轻松地制造冲突。例如，如果在节点 A 和 B 上设置了 500 毫秒的延迟，则在节点 A 上插入一个值后，至少为您提供了 500 毫秒的时间在节点 B 上执行冲突插入。  需要重新加载服务器或重新启动应用工作线程，设置才能生效。  | 
| pgactive.connectability\$1check\$1duration | `integer` | –  | 指定数据库工作线程在尝试连接失败后，继续尝试建立连接的持续时间（以秒为单位）。工作线程每秒尝试连接一次，直到连接成功或达到此超时值。当数据库引擎在工作线程准备好建立连接之前启动时，此设置很有用。 | 
| pgactive.skip\$1ddl\$1replication | `boolean` | `on` | 控制如何在启用 `pgactive` 时，在 Amazon RDS 中复制或处理 DDL 更改。在设置为 `on` 时，该节点会像非 pgactive 节点一样处理 DDL 更改。在使用此参数时，需符合以下要求： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 您可以使用超级用户权限以全局和本地（会话级别）这两种方式修改此参数。  错误地更改此参数可能会中断您的复制设置。  | 
| pgactive.do\$1not\$1replicate | `boolean` | – | 此参数仅供内部使用。在事务中设置此参数时，所做的更改不会复制到数据库集群内的其他节点。  错误地更改此参数可能会中断您的复制设置。  | 
| pgactive.discard\$1mismatched\$1row\$1attributes | `boolean` | –  | 此参数仅供专业人员使用。建议仅在解决特定的复制问题时使用此参数。在以下情况下可使用此参数： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 此设置会覆盖以下错误消息，并允许产生数据差异，以便让复制进程持续进行：`cannot right-pad mismatched attributes; attno %u is missing in local table and remote row has non-null, non-dropped value for this attribute`  错误地更改此参数可能会中断您的复制设置。   | 
| pgactive.debug\$1trace\$1replay | `boolean` | – | 在设置为 `on` 时，它会为下游应用工作线程处理的每个远程操作发出一条日志消息。日志包括： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 日志还会捕获已排队的 DDL 命令和表删除事件。para> 默认情况下，日志不包括行字段内容。要在日志中包含行值，您必须在启用以下标志的情况下重新编译： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html)  启用此日志记录设置可能会影响性能。建议仅在需要此设置来进行问题排查时启用它。对此设置所做的更改会在重新加载配置后生效。您无需重新启动服务器。   | 
| pgactive.extra\$1apply\$1connection\$1options |  | – | 您可以为所有与 pgactive 节点的对等节点连接配置连接参数。这些参数可控制 keepalives 和 SSL 模式等设置。默认情况下，pgactive 使用以下连接参数： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 要覆盖默认参数，请使用以下类似命令： pgactive.extra\$1apply\$1connection\$1options = 'keepalives=0' 单个节点连接字符串优先于这些设置和 pgactive 的内置连接选项。有关连接字符串格式的更多信息，请参阅 [libpq connection strings](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING)。 我们建议将默认的 keepalive 设置保持启用状态。仅在您通过不可靠的网络完成大量事务时遇到问题的情况下，才禁用 keepalives。  我们建议将默认的 keepalive 设置保持启用状态。仅在您通过不可靠的网络完成大量事务时遇到问题的情况下，才禁用 keepalives。对此设置所做的更改会在重新加载配置后生效。您无需重新启动服务器。  | 
| pgactive.init\$1node\$1parallel\$1jobs (int) |  | – | 指定在逻辑节点与 `pgactive.pgactive_join_group` 函数联接期间，`pg_dump` 和 `pg_restore` 可使用的并行作业数。 对此设置所做的更改会在重新加载配置后生效。您无需重新启动服务器。 | 
| pgactive.max\$1nodes | `int` | 4 |  指定 pgactive 扩展组中可包含的节点的最大数目。默认值为 4 个节点。在设置此参数的值时，必须注意以下几点： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 可通过两种方式设置此参数，即在配置文件中进行设置或者使用 `ALTER SYSTEM SET` 命令进行设置 此参数的默认值为 `4`，这意味着，`pgactive` 扩展组始终最多只能包含 4 个节点。  重新启动服务器后，此更改将生效。  | 
| pgactive.permit\$1node\$1identifier\$1getter\$1function\$1creation | `boolean` | – | 此参数仅供内部使用。启用后，`pgactive` 扩展将允许创建 pgactive 节点标识符 getter 函数。 | 

# 了解双活冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.replication"></a>

如果您在双活模式下使用 pgactive，在从多个节点写入同一个表时可能会造成数据冲突。一些集群化系统会使用分布式锁来防止并发访问，不过 pgactive 采用的是乐观方法，更适合分布在不同地理位置的应用程序。

一些数据库集群系统使用分布式锁来防止并发数据访问。但是，此方法只适合距离非常近的服务器，不支持分布在不同地理位置的应用程序，因为此方法需要极低的延迟才能实现良好的性能。pgactive 扩展没有使用分布式锁（这是一种悲观方法），而是使用乐观方法。这意味着：
+ 可帮助您尽可能避免冲突。
+ 允许出现某些类型的冲突。
+ 发生冲突时会提供冲突解决方案。

通过这种方法，您在构建分布式应用程序时具有更好的灵活性。

## 发生冲突的原因
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.howconflicts"></a>

节点间冲突是由事件序列引起的，如果涉及的所有事务同时发生在同一个节点上，则不会出现节点间冲突。由于节点仅在事务提交后交换更改，因此每个事务在其提交的节点上都是分别有效的，但如果事务在另一个同时完成其他工作的节点上运行，就会无效。由于 pgactive 的应用操作本质上是在其他节点上重播事务，因此，如果正在应用的事务与在接收节点上提交的事务之间存在冲突，则重播操作会失败。

 当所有事务都运行在单个节点上时，大多数冲突不会发生的原因是 PostgreSQL 采用了事务间通信机制来防止冲突，包括：
+ UNIQUE 索引
+ SEQUENCE
+ 行和关系锁定
+ SERIALIZABLE 依赖关系跟踪

所有这些机制都是在事务之间进行通信的方法，用于防止出现意外并发问题

pgactive 不使用分布式事务管理器或锁管理器，因此可以实现低延迟并很好地处理网络分区。但是，这意味着不同节点上事务的运行是彼此完全隔离的。虽然隔离通常可以提高数据库的一致性，但在这种情况下，您需要减少隔离以防止冲突。

## 冲突类型
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflicttypes"></a>

可能发生的冲突包括：

**Topics**
+ [PRIMARY KEY 或 UNIQUE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict1)
+ [INSERT/INSERT 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict2)
+ [违反多个 UNIQUE 约束的 INSERT](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict3)
+ [UPDATE/UPDATE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict4)
+ [PRIMARY KEY 上的 UPDATE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict5)
+ [违反多个 UNIQUE 约束的 UPDATE](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict6)
+ [UPDATE/DELETE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict7)
+ [INSERT/UPDATE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict8)
+ [DELETE/DELETE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict9)
+ [外键约束冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict10)
+ [排除约束冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict11)
+ [全局数据冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict12)
+ [锁冲突和死锁中止](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict13)
+ [分歧冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14)

### PRIMARY KEY 或 UNIQUE 冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict1"></a>

当多个操作试图以单个节点上不可能出现的方式修改同一个行键时，就会发生行冲突。这些冲突体现了最常见的数据冲突类型。

pgactive 采用上次更新获胜处理方法或者您的自定义冲突处理程序，来解决检测到的冲突。

行冲突包括：
+ INSERT 与 INSERT
+ INSERT 与 UPDATE
+ UPDATE 与 DELETE
+ INSERT 与 DELETE
+ DELETE 与 DELETE
+ INSERT 与 DELETE

### INSERT/INSERT 冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict2"></a>

这是最常见的冲突，当两个不同节点上的 INSERT 操作创建具有相同 PRIMARY KEY 值的元组（或在没有 PRIMARY KEY 时，使用相同的 UNIQUE 约束值），就会发生这种冲突。

pgactivelink 使用来自原始主机的时间戳来保留最新的元组，以此解决 INSERT 冲突。您可以使用自定义冲突处理程序覆盖此默认行为。虽然此过程不需要管理员专门采取操作，但请注意，pgactivelink 会丢弃所有节点上的其中一个 INSERT 操作。除非您的自定义处理程序实施自动数据合并，否则不会自动进行数据合并。

pgactivelink 只能解决涉及单个约束违规的冲突。如果某个 INSERT 违反了多个 UNIQUE 约束，您必须实施其他冲突解决策略。

### 违反多个 UNIQUE 约束的 INSERT
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict3"></a>

INSERT/INSERT 冲突可能违反多个 UNIQUE 约束，包括 PRIMARY KEY。pgactivelink 只能处理涉及单个 UNIQUE 约束的冲突。当冲突违反多个 UNIQUE 约束时，应用工作线程会失败并返回以下错误：

`multiple unique constraints violated by remotely INSERTed tuple.`

在较早的版本中，这种情况生成的是“分歧唯一性冲突”错误。

要解决这些冲突，您必须手动采取操作。您可以对发生冲突的本地元组执行 DELETE，或者对元组执行 UPDATE 以使用新的远程元组来消除冲突。请注意，您可能需要解决多个相互冲突的元组。目前，pgactivelink 没有提供内置功能用于忽略、丢弃或合并违反多个唯一约束的元组。

**注意**  
有关更多信息，请参阅“违反多个 UNIQUE 约束的 UPDATE”。

### UPDATE/UPDATE 冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict4"></a>

当两个节点并发修改同一个元组而没有更改其 PRIMARY KEY 时，就会发生此冲突。pgactivelink 使用上次更新获胜逻辑或您的自定义冲突处理程序（如果已定义）来解决这些冲突。PRIMARY KEY 对于元组匹配和冲突解决至关重要。对于没有 PRIMARY KEY 的表，pgactivelink 拒绝 UPDATE 操作，并显示以下错误：

`Cannot run UPDATE or DELETE on table (tablename) because it does not have a primary key.`

### PRIMARY KEY 上的 UPDATE 冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict5"></a>

pgactive 在处理 PRIMARY KEY 更新时存在限制。虽然您可以对 PRIMARY KEY 执行 UPDATE 操作，但对于这些操作，pgactive 无法使用最后更新获胜逻辑自动解决冲突。您必须确保 PRIMARY KEY 更新不会与现有值冲突。如果在 PRIMARY KEY 更新期间发生冲突，这些冲突就会成为分歧冲突，需要您手动干预。有关处理这些情况的更多信息，请参阅[分歧冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14)。

### 违反多个 UNIQUE 约束的 UPDATE
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict6"></a>

当传入的 UPDATE 违反多个 UNIQUE 约束或 PRIMARY KEY 值时，pgactivelink 无法应用上次更新获胜冲突解决方案。此行为类似于出现多个约束冲突的 INSERT 操作。这些情况会造成分歧冲突，需要您手动干预。有关更多信息，请参阅[分歧冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14)。

### UPDATE/DELETE 冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict7"></a>

当一个节点对一行执行 UPDATE 而另一个节点同时对该行执行 DELETE 时，就会出现此冲突。在这种情况下，重播时会发生 UPDATE/DELETE 冲突。除非您的自定义冲突处理程序另行规定，否则解决方案是丢弃在 DELETE 之后到达的所有 UPDATE。

pgactivelink 需要一个 PRIMARY KEY 来匹配元组并解决冲突。对于没有 PRIMARY KEY 的表，表会拒绝 DELETE 操作，并显示以下错误：

`Cannot run UPDATE or DELETE on table (tablename) because it does not have a primary key.`

**注意**  
pgactivelink 无法区分 UPDATE/DELETE 和 INSERT/UPDATE 冲突。在这两种情况下，UPDATE 均会影响不存在的行。由于异步复制以及节点之间缺乏重播排序，pgactivelink 无法确定是在对新行（尚未收到 INSERT）还是对已删除行执行 UPDATE 操作。在这两种情况下，pgactivelink 都会丢弃 UPDATE。

### INSERT/UPDATE 冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict8"></a>

这种冲突可能发生在多节点环境中。当一个节点 INSERT 一行数据，第二个节点对该行执行 UPDATE，而第三个节点在收到原始 INSERT 之前就接收到 UPDATE 时，就会发生这种情况。默认情况下，除非您的自定义冲突触发器另行规定，否则 pgactivelink 会通过放弃 UPDATE 来解决这些冲突。请注意，这种解决方法可能会导致节点间的数据不一致。有关类似场景及其处理方法的更多信息，请参阅 [UPDATE/DELETE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict7)。

### DELETE/DELETE 冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict9"></a>

当两个不同的节点并发删除同一个元组时，就会发生这种冲突。pgactivelink 认为这些冲突无害，因为两个 DELETE 操作会产生相同的最终结果。在此场景中，pgactivelink 可以安全地忽略其中一个 DELETE 操作，而不会影响数据一致性。

### 外键约束冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict10"></a>

对现有本地数据应用远程事务时，FOREIGN KEY 约束可能会导致冲突。发生这些冲突的情况通常是应用事务的顺序，不同于事务在发起节点上的逻辑顺序。

默认情况下，pgactive 会将 session\$1replication\$1role 作为 `replica` 来应用更改，这会在复制过程中绕过外键检查。在双活配置中，这可能会导致外键违规。大多数违规行为都是暂时性的，当复制进度跟上时就会解决。但是，由于 pgactive 不支持跨节点行锁定，因此可能会出现悬挂外键。

这种行为是具备分区容错性的异步双活系统所固有的。例如，节点 A 可能会插入新的子行，而节点 B 同时在删除其父行。系统无法阻止节点之间这种类型的并发修改。

为尽可能减少外键冲突，我们给出了以下建议：
+ 将外键关系限制为密切相关的实体。
+ 尽可能从单个节点修改相关实体。
+ 选择极少需要进行修改的实体。
+ 针对修改实施应用程序级的并发控制。

### 排除约束冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict11"></a>

 pgactivelink 不支持排除约束，并会限制创建这种约束。

**注意**  
在将现有的独立数据库转换为 pgactivelink 数据库时，请手动删除所有排除约束。

在分布式异步系统中，不可能保证所有行集都没有违反约束。这是因为不同节点上的所有事务都是完全隔离的。排除约束可能导致重播死锁，在这种情况下，由于排除约束违规，重播无法从任何节点进展到另一个节点。

如果您强制 pgactivelink 创建排除约束，或者在将独立数据库转换到 pgactivelink 时不删除现有排除约束，则复制很可能会中断。要恢复复制进度，请删除或更改与传入的远程元组冲突的本地元组，这样便可以应用远程事务。

### 全局数据冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict12"></a>

使用 pgactivelink 时，当节点具有不同的全局 PostgreSQL 系统级数据（例如角色）时，就可能会发生冲突。这些冲突的结果是操作（主要是 DDL）会成功并在一个节点上提交，但无法应用于其他节点。

如果一个节点上有某个用户但另一个节点上没有，就会出现复制问题：
+ Node1 有名为 `fred` 的用户，但是 Node2 上没有该用户
+ 当 `fred` 在 Node1 上创建表时，表在复制时的所有者是 `fred`
+ 将此 DDL 命令应用于 Node2 时，命令会失败，因为用户 `fred` 不存在
+ 在失败后，会在 Node2 上的 PostgreSQL 日志中生成 ERROR 条目并递增 `pgactive.pgactive_stats.nr_rollbacks` 计数器

**解决方案：**在 Node2 上创建用户 `fred`。该用户不必具备相同的权限，但必须存在于两个节点上。

如果一个节点上有某个表但另一个节点上没有，则数据修改操作会失败：
+ Node1 上有名为 `foo` 的表，但 Node2 上没有
+ Node1 上对 `foo` 表执行的任何 DML 操作，在复制到 Node2 时会失败

**解决方案：**在 Node2 上创建具有相同结构的表 `foo`。

**注意**  
pgactivelink 目前不复制 CREATE USER 命令或 DDL 操作。DDL 复制功能计划在未来版本中发布。

### 锁冲突和死锁中止
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict13"></a>

由于 pgactive 应用进程的运行方式类似于普通用户会话，因此这些进程遵循标准的行和表锁定规则。这可能会导致 pgactivelink 应用进程需要等待用户事务或其他应用进程持有的锁被释放。

以下类型的锁会影响应用进程：
+ 用户会话施加的显式表级锁（LOCK TABLE...）
+ 用户会话施加的显式行级锁（SELECT ... FOR UPDATE/FOR SHARE）
+ 来自外键的锁定
+ 由于行 UPDATE、INSERT 或 DELETE 而导致的隐式锁定，这可能源自本地活动，也可能是从其他服务器应用的

在下列操作之间可能会出现死锁：
+ pgactivelink 应用进程和用户事务
+ 两个应用进程

发生死锁时，PostgreSQL 的死锁检测器会终止其中一个出现问题的事务。如果 pgactivelink 应用工作线程的进程终止，则会自动重试而且通常会成功。

**注意**  
这些问题是暂时性的，通常无需管理员干预。如果由于空闲用户会话锁定导致某个应用进程被长时间阻止，您可以终止该用户会话来恢复复制。这种情况类似于某个用户持有的长时间锁定影响到了其他用户会话。
要识别与锁定相关的重播延迟，请在 PostgreSQL 中启用 `log_lock_waits` 功能。

### 分歧冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14"></a>

当各节点之间本应相同的数据意外地变得不同时，就会发生分歧冲突。虽然这些冲突不应该发生，但在当前的实施中，无法可靠地预防所有冲突。

**注意**  
 在一行上，如果有某个节点在所有节点处理更改之前更改该行的主键，则修改行的 PRIMARY KEY 会导致分歧冲突。请避免更改主键，或将更改限制在某个指定节点上。有关更多信息，请参阅 [PRIMARY KEY 上的 UPDATE 冲突](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict5)。

涉及行数据的分歧冲突通常需要管理员干预。要解决这些冲突，您必须手动调整一个节点上的数据来与其他节点相匹配，同时使用 `pgactive.pgactive_do_not_replicate` 暂时禁用复制。如果您按照文档说明使用 pgactive 并避免使用标记为不安全的设置或函数，则不应出现这些冲突。

 作为管理员，您必须手动解决这些冲突。根据冲突类型，您需要使用诸如 `pgactive.pgactive_do_not_replicate` 之类的高级选项。请谨慎使用这些选项，因为使用不当会导致情况恶化。由于可能出现的冲突各种各样，我们无法提供通用的解决方案说明。

当不同节点之间本应相同的数据意外地变得不同时，就会发生分歧冲突。虽然这些冲突不应该发生，但在当前的实施中，无法可靠地预防所有此类冲突。

## 避免或容忍冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.avoidconflicts"></a>

 在大多数情况下，您可以使用合适的应用程序设计，从而避免冲突或使应用程序具备容忍冲突的能力。

 只有在多个节点上同时进行多个操作时才会发生冲突。为避免冲突，请采取以下方法：
+ 仅向一个节点写入
+ 写入各个节点上的独立数据库子集（例如，向每个节点分配一个单独的架构）

对于 INSERT 与 INSERT 冲突，请使用全局序列来彻底防止冲突。

 如果您的应用场景不能接受冲突，请考虑在应用程序级别实施分布式锁定。通常，最好的方法是对应用程序进行设计，使其与 pgactive 的冲突解决机制配合使用，而不是尝试预防所有冲突。有关更多信息，请参阅 [冲突类型](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflicttypes)。

## 冲突日志记录
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflictlogging"></a>

pgactivelink 会将冲突事件记录到 `pgactive.pgactive_conflict_history` 表中，供您诊断和处理双活冲突。仅当 `pgactive.log_conflicts_to_table` 设置为 true 时，才会将冲突记录到此表。无论 `pgactive.log_conflicts_to_table` 的设置如何，当 log\$1min\$1messages 设置为 `LOG` 或 `lower` 时，pgactive 扩展还会将冲突记录到 PostgreSQL 日志文件中。

 使用冲突历史记录表可以：
+ 衡量您的应用程序造成冲突的频率
+ 确定在什么位置发生冲突
+ 改进应用程序以降低冲突率
+ 检测冲突解决方案无法达成所需结果的情况
+ 确定哪些地方需要用户定义的冲突触发器或更改应用程序设计

 对于行冲突，您可以选择记录行值。这由 `pgactive.log_conflicts_to_table` 设置控制。请注意：
+ 这是一个全局数据库级选项
+ 无法按各个表来控制对行值的记录
+ 字段数量、数组元素或字段长度没有限制
+ 如果您在处理数 MB 的行而这些行可能会触发冲突，则不建议启用此功能

 由于冲突历史记录表包含来自数据库中各个表的数据（每个表都可能采用不同架构），因此记录的行值存储为 JSON 字段。JSON 使用 `row_to_json` 创建，类似于直接从 SQL 中调用。PostgreSQL 不提供 `json_to_row` 函数，因此您需要特定于表的代码（采用 PL/pgSQL、PL/Python、PL/Perl 等）才能从记录的 JSON 中重新构造复合类型的元组。

**注意**  
对用户定义冲突的支持计划作为未来的扩展功能推出。

# 了解 pgactive 架构
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.schema"></a>

pgactive 架构管理 RDS for PostgreSQL 中的主动-主动复制。此架构包含用于存储复制配置和状态信息的表。

**注意**  
pgactive 架构正在演进中，可能会发生变更。不要直接修改这些表中的数据。

pgactive 架构中的键表包括：
+ `pgactive_nodes` – 存储有关主动-主动复制组中的节点的信息。
+ `pgactive_connections` – 存储每个节点的连接详细信息。

## pgactive\$1nodes
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.schema.nodes"></a>

pgactive\$1nodes 存储有关参与主动-主动复制组的节点的信息。


| 列 | 类型 | 排序规则 | 是否可为 null | 默认值 | 
| --- | --- | --- | --- | --- | 
| node\$1sysid | 文本 | – | 不为 null | – | 
| node\$1timeline | oid | – | 不为 null | – | 
| node\$1dboid | oid | – | 不为 null | – | 
| node\$1status | char | – | 不为 null | – | 
| node\$1name | 文本 | – | 不为 null | – | 
| node\$1dsn | 文本 | – | 不为 null | – | 
| node\$1init\$1from\$1dsn | 文本 | – | 不为 null | – | 
| node\$1read\$1only | 布尔值 | – | – | false | 
| node\$1seq\$1id | smallint | – | 不为 null | – | 

**node\$1sysid**  
在 `pgactive_create_group` 或 `pgactive_join_group` 期间生成的节点的唯一 ID

**node\$1status**  
节点的准备情况：  
+ **b** – 开始设置
+ **i** – 正在初始化
+ **c** – 追赶
+ **o** – 创建出站插槽
+ **r** – 已就绪
+ **k** – 已终止
此列不指明节点已连接还是已断开连接。

**node\$1name**  
用户提供的唯一节点名称。

**node\$1dsn**  
连接字符串或用户映射名称。

**node\$1init\$1from\$1dsn**  
从中创建了此节点的 DSN。

## pgactive\$1connection
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.schema.connection"></a>

pgactive\$1connections 存储每个节点的连接详细信息。


| 列 | 类型 | 排序规则 | 是否可为 null | 默认值 | 
| --- | --- | --- | --- | --- | 
| conn\$1sysid | 文本 | none | 不为 null | none | 
| conn\$1timeline | oid | none | 不为 null | none | 
| conn\$1dboid | oid | none | 不为 null | none | 
| conn\$1dsn | 文本 | none | 不为 null | none | 
| conn\$1apply\$1delay | 整数 | none | none | none | 
| conn\$1replication\$1sets | 文本 | none | none | none | 

conn\$1sysid  
此条目所指的节点的节点标识符。

conn\$1dsn  
与 pgactive.pgactive\$1nodes `node_dsn` 相同。

conn\$1apply\$1delay  
如果设置此参数，则将设定从远程节点应用每个事务前的等待时间（以毫秒为单位）。主要用于调试。如果为 null，则全局默认值将适用。

## 使用复制集
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.replication"></a>

复制集决定要在复制操作中包含或排除的表。默认情况下，除非您使用以下函数另行指定，否则将复制所有表：
+ `pgactive_exclude_table_replication_set()` – 从复制中排除指定的表
+ `pgactive_include_table_replication_set()` – 在复制中包含指定的表

**注意**  
在配置复制集之前，请注意以下几点：  
仅在运行 `pgactive_create_group()` 后且在运行 `pgactive_join_group()` 之前，才能配置表包含或排除。
使用 `pgactive_exclude_table_replication_set()` 后，您将无法使用 `pgactive_include_table_replication_set()`。
使用 `pgactive_include_table_replication_set()` 后，您将无法使用 `pgactive_exclude_table_replication_set()`。

系统会根据您的初始配置通过不同的方式处理新创建的表：
+ 如果排除表：在 `pgactive_join_group()` 之后创建的任何新表都将自动包含在复制中。
+ 如果包含表：在 `pgactive_join_group()` 之后创建的任何新表都将自动从复制中排除。

要查看特定表的复制集配置，请使用 `pgactive.pgactive_get_table_replication_sets()` 函数。

# pgactive 函数参考
<a name="pgactive-functions-reference"></a>

在下文中，您可以找到 pgactive 函数及其参数、返回值和实际使用说明，以助您高效使用它们：

## get\$1last\$1applied\$1xact\$1info
<a name="get-last-applied-xact-info"></a>

检索指定节点的上次应用的事务信息。

**Arguments (参数)**  
+ sysid (text) - timeline OID
+ dboid (OID)

**返回类型**  
它将记录以下内容：  
+ last\$1applied\$1xact\$1id（OID）
+ last\$1applied\$1xact\$1committs（带时区的时间戳）
+ last\$1applied\$1xact\$1at（带时区的时间戳）

**使用说明**  
使用此函数可检索指定节点的上次应用的事务信息。

## pgactive\$1apply\$1pause
<a name="pgactive-apply-pause"></a>

暂停复制应用进程。

**Arguments (参数)**  
无

**返回类型**  
布尔值

**使用说明**  
调用此函数可暂停复制应用进程。

## pgactive\$1apply\$1resume
<a name="pgactive-apply-resume"></a>

恢复复制应用进程。

**Arguments (参数)**  
无

**返回类型**  
void

**使用说明**  
调用此函数可恢复复制应用进程。

## pgactive\$1is\$1apply\$1paused
<a name="pgactive-is-apply-paused"></a>

检查复制应用当前是否已暂停。

**Arguments (参数)**  
无

**返回类型**  
布尔值

**使用说明**  
使用此函数可检查复制应用当前是否已暂停。

## pgactive\$1create\$1group
<a name="pgactive-create-group"></a>

通过将独立数据库转换为初始节点来创建 pgactive 组。



**Arguments (参数)**  
+ node\$1name (text)
+ node\$1dsn (text)
+ apply\$1delay integer DEFAULT NULL::integer - replication\$1sets text[] DEFAULT ARRAY[‘default’::text]

**返回类型**  
void

**使用说明**  
通过将独立数据库转换为初始节点来创建 pgactive 组。此函数在将节点转换为 pgactive 节点之前执行完整性检查。在使用此函数之前，请确保您的 PostgreSQL 集群有足够的可用 `max_worker_processes` 来支持 pgactive 后台工作线程。

## pgactive\$1detach\$1nodes
<a name="pgactive-detach-nodes"></a>

从 pgactive 组中移除指定节点。

**Arguments (参数)**  
+ p\$1nodes (text[])

**返回类型**  
void

**使用说明**  
使用此函数可从 pgactive 组中移除指定节点。

## pgactive\$1exclude\$1table\$1replication\$1set
<a name="pgactive-exclude-table-replication-set"></a>

将特定表排除在复制之外。

**Arguments (参数)**  
+ p\$1relation（regclass）

**返回类型**  
void

**使用说明**  
使用此函数可将特定表排除在复制之外。

## pgactive\$1get\$1replication\$1lag\$1info
<a name="pgactive-get-replication-lag-info"></a>

检索详细的复制滞后信息，包括节点详细信息、WAL 状态和 LSN 值。

**Arguments (参数)**  
无

**返回类型**  
SETOF 记录 - node\$1name text - node\$1sysid text - application\$1name text - slot\$1name text - active boolean - active\$1pid integer - pending\$1wal\$1decoding bigint - 发送者节点上待解码的 WAL 的近似大小（以字节为单位）- pending\$1wal\$1to\$1apply bigint - 要在接收节点上应用的 WAL 的近似大小（以字节为单位）- restart\$1lsn pg\$1lsn - confirmed\$1flush\$1lsn pg\$1lsn - sent\$1lsn pg\$1lsn - write\$1lsn pg\$1lsn - flush\$1lsn pg\$1lsn - replay\$1lsn pg\$1lsn

**使用说明**  
调用此函数可检索复制滞后信息，包括节点详细信息、WAL 状态和 LSN 值。

## pgactive\$1get\$1stats
<a name="pgactive-get-stats"></a>

检索 pgactive 复制统计信息。

**Arguments (参数)**  
无

**返回类型**  
SETOF 记录 - rep\$1node\$1id oid - rilocalid oid - riremoteid text - nr\$1commit bigint - nr\$1rollback bigint - nr\$1insert bigint - nr\$1insert\$1conflict bigint - nr\$1update bigint - nr\$1update\$1conflict bigint - nr\$1delete bigint - nr\$1delete\$1conflict bigint - nr\$1disconnect bigint

**使用说明**  
使用此函数可检索 pgactive 复制统计信息。

## pgactive\$1get\$1table\$1replication\$1sets
<a name="pgactive-get-table-replication-sets"></a>

获取特定关系的复制集配置。

**Arguments (参数)**  
+ relation (regclass)

**返回类型**  
SETOF 记录

**使用说明**  
调用此函数可获取特定关系的复制集配置。

## pgactive\$1include\$1table\$1replication\$1set
<a name="pgactive-include-table-replication-set"></a>

将特定表包含在复制中。

**Arguments (参数)**  
+ p\$1relation（regclass）

**返回类型**  
void

**使用说明**  
使用此函数可将特定表包含在复制中。

## pgactive\$1join\$1group
<a name="pgactive-join-group"></a>

向现有 pgactive 组添加节点。

**Arguments (参数)**  
+ node\$1name (text)
+ node\$1dsn (text)
+ join\$1using\$1dsn (text)
+ apply\$1delay (integer，可选)
+ replication\$1sets (text[]，默认值：['default'])
+ bypass\$1collation\$1check (boolean，默认值：false)
+ bypass\$1node\$1identifier\$1creation (boolean，默认值：false)
+ bypass\$1user\$1tables\$1check (boolean，默认值：false)

**返回类型**  
void

**使用说明**  
调用此函数可将节点添加到现有 pgactive 组中。确保您的 PostgreSQL 集群有足够的 max\$1worker\$1processes 以供 pgactive 后台工作线程使用。

## pgactive\$1remove
<a name="pgactive-remove"></a>

从本地节点中移除所有 pgactive 组件。

**Arguments (参数)**  
+ force (boolean，默认值：false)

**返回类型**  
void

**使用说明**  
调用此函数可从本地节点中移除所有 pgactive 组件。

## pgactive\$1snowflake\$1id\$1nextval
<a name="pgactive-snowflake-id-nextval"></a>

生成特定于节点的唯一序列值。

**Arguments (参数)**  
+ regclass

**返回类型**  
bigint

**使用说明**  
使用此函数可生成特定于节点的唯一序列值。

## pgactive\$1update\$1node\$1conninfo
<a name="pgactive-update-node-conninfo"></a>

更新 pgactive 节点的连接信息。

**Arguments (参数)**  
+ node\$1name\$1to\$1update (text)
+ node\$1dsn\$1to\$1update (text)

**返回类型**  
void

**使用说明**  
使用此函数可更新 pgactive 节点的连接信息。

## pgactive\$1wait\$1for\$1node\$1ready
<a name="pgactive-wait-for-node-ready"></a>

监控组创建或加入操作的进度。

**Arguments (参数)**  
+ timeout (integer，默认值：0)
+ progress\$1interval (integer，默认值：60)

**返回类型**  
void

**使用说明**  
调用此函数可监控组创建或加入操作的进度。

# 处理主动-主动复制中的冲突
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-conflicts"></a>

`pgactive` 扩展适用于每个数据库，而不是每个集群。使用 `pgactive` 的每个数据库实例都是一个独立的实例，可以接受来自任何来源的数据更改。将更改发送到数据库实例时，PostgreSQL 会在本地提交更改，然后使用 `pgactive` 将更改异步复制到其它数据库实例。当两个 PostgreSQL 数据库实例几乎同时更新同一记录时，可能会发生冲突。

`pgactive` 扩展提供了冲突检测和自动解决机制。它跟踪在这两个数据库实例上提交事务的时间戳，并自动应用带有最新时间戳的更改。`pgactive` 扩展还会记录 `pgactive.pgactive_conflict_history` 表中发生冲突的时间。

`pgactive.pgactive_conflict_history` 会继续增加。您可能需要定义清除策略。可以通过定期删除一些记录或为此关系定义分区方案（然后分离、删除、截断感兴趣的分区）来完成此操作。要定期实施清除策略，一种选择是使用 `pg_cron` 扩展。请参阅 `pg_cron` 历史记录表示例的以下信息：[使用 PostgreSQL pg\$1cron 扩展安排维护计划](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html)。

# 处理主动-主动复制中的序列
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-sequences"></a>

带有 `pgactive` 扩展的 RDS for PostgreSQL 数据库实例使用两种不同的序列机制来生成唯一值。

**全局序列**  
要使用全局序列，请使用 `CREATE SEQUENCE` 语句创建一个本地序列。使用 `pgactive.pgactive_snowflake_id_nextval(seqname)` 而非 `usingnextval(seqname)` 来获取序列的下一个唯一值。

以下示例创建全局序列：

```
app=> CREATE TABLE gstest (
      id bigint primary key,
      parrot text
    );
```

```
app=>CREATE SEQUENCE gstest_id_seq OWNED BY gstest.id;
```

```
app=> ALTER TABLE gstest \
      ALTER COLUMN id SET DEFAULT \
      pgactive.pgactive_snowflake_id_nextval('gstest_id_seq');
```

**分区序列**  
在分步或分区序列中，每个节点上都使用普通的 PostgreSQL 序列。每个序列的增量相同，从不同的偏移量开始。例如，在步骤 100 中，节点 1 生成序列为 101、201、301，依此类推，而节点 2 生成序列为 102、202、302，依此类推。即使节点长时间无法通信，该方案也能正常工作，但要求设计人员在建立模式时指定最大节点数，并且需要按节点进行配置。错误很容易导致序列重叠。

通过在节点上创建所需的序列，使用 `pgactive` 配置这种方法相对简单，如下所示：

```
CREATE TABLE some_table (generated_value bigint primary key);
```

```
app=> CREATE SEQUENCE some_seq INCREMENT 100 OWNED BY some_table.generated_value;
```

```
app=> ALTER TABLE some_table ALTER COLUMN generated_value SET DEFAULT nextval('some_seq');
```

然后，对每个节点调用 `setval` 以给出不同的偏移起始值，如下所示。

```
app=>
-- On node 1
SELECT setval('some_seq', 1);

-- On node 2
SELECT setval('some_seq', 2);
```

# 使用 pg\$1repack 扩展减少表和索引的膨胀
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack"></a>

您可以使用 `pg_repack` 扩展从表和索引中移除多余内容，作为 `VACUUM FULL` 的备选方法。RDS for PostgreSQL 版本 9.6.3 及更高版本支持该扩展。有关 `pg_repack` 扩展和完整表重新打包的更多信息，请参阅 [GitHub 项目文档](https://reorg.github.io/pg_repack/)。

与 `VACUUM FULL` 不同，在以下情况下，`pg_repack` 扩展只需在表重建操作期间短时间使用独占锁（AccessExclusiveLock）：
+ 初始创建日志表 - 创建日志表以记录在数据初始复制期间发生的更改，如以下示例所示：

  ```
  postgres=>\dt+ repack.log_*
  List of relations
  -[ RECORD 1 ]-+----------
  Schema        | repack
  Name          | log_16490
  Type          | table
  Owner         | postgres
  Persistence   | permanent
  Access method | heap
  Size          | 65 MB
  Description   |
  ```
+ 最后的交换和删除阶段。

在重建操作的其余部分中，它只需对原始表使用 `ACCESS SHARE` 锁，即可将行从该表复制到新表。这有助于 INSERT、UPDATE 和 DELETE 操作照常进行。

## 建议
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack.Recommen"></a>

当您使用 `pg_repack` 扩展从表和索引中移除膨胀内容时，以下建议适用：
+ 在非工作时间或在维护时段内执行重新打包，以最大限度地减少它对其它数据库活动性能的影响。
+ 在重建活动期间，密切监视阻止会话，并确保原始表上不存在可能阻止 `pg_repack` 的活动，特别是在最后的交换和删除阶段，此时它需要对原始表进行独占锁定。有关更多信息，请参阅[识别阻止查询的内容](https://repost.aws/knowledge-center/rds-aurora-postgresql-query-blocked)。

  当您看到阻止会话时，经慎重考虑后，可以使用以下命令将其终止。这有助于继续执行 `pg_repack` 以完成重建：

  ```
  SELECT pg_terminate_backend(pid);
  ```
+ 在事务速率非常高的系统上应用 `pg_repack's` 日志表中的应计更改时，应用过程可能无法跟上更改速率。在这种情况下，`pg_repack` 将无法完成应用过程。有关更多信息，请参阅 [在重新打包期间监控新表](#Appendix.PostgreSQL.CommonDBATasks.pg_repack.Monitoring)。如果索引严重膨胀，另一种解决方案是执行仅限索引的重新打包。这还有助于 VACUUM 的索引清理周期更快地完成。

  您可以使用 PostgreSQL 版本 12 中的手动 VACUUM 跳过索引清理阶段，在 PostgreSQL 版本 14 中的紧急 autovacuum 期间会自动跳过索引清理阶段。这有助于在不消除索引膨胀的情况下更快地完成 VACUUM，并且仅适用于紧急情况，例如防止重叠 VACUUM。有关更多信息，请参阅《Amazon Aurora 用户指南》中的[避免索引膨胀](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.diag-table-ind-bloat.html#AuroraPostgreSQL.diag-table-ind-bloat.AvoidinginIndexes)。

## 先决条件
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack.Prereq"></a>
+ 该表必须具有 PRIMARY KEY 或非 null UNIQUE 约束。
+ 客户端和服务器的扩展版本必须相同。
+ 确保 RDS 实例的 `FreeStorageSpace` 超过表的总大小，而不会出现膨胀。例如，假设表（包括 TOAST 和索引）的总大小为 2TB，表中的总膨胀为 1TB。所需 `FreeStorageSpace` 必须大于以下计算返回的值：

   `2TB (Table size)` - `1TB (Table bloat)` = `1TB`

  您可以使用以下查询来检查表的总大小，并使用 `pgstattuple` 来派生膨胀。有关更多信息，请参阅《Amazon Aurora 用户指南》中的[诊断表和索引膨胀](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.diag-table-ind-bloat.html) 

  ```
  SELECT pg_size_pretty(pg_total_relation_size('table_name')) AS total_table_size;
  ```

  活动完成后，将回收此空间。
+ 确保 RDS 实例有足够的计算和 IO 容量来处理重新打包操作。您可以考虑纵向扩展实例类以实现性能的最佳平衡。

**使用 `pg_repack` 扩展**

1. 通过运行以下命令在 RDS for PostgreSQL 数据库实例上安装 `pg_repack` 扩展。

   ```
   CREATE EXTENSION pg_repack;
   ```

1. 运行以下命令以授予对由 `pg_repack` 创建的临时日志表的写入访问权限。

   ```
   ALTER DEFAULT PRIVILEGES IN SCHEMA repack GRANT INSERT ON TABLES TO PUBLIC;
   ALTER DEFAULT PRIVILEGES IN SCHEMA repack GRANT USAGE, SELECT ON SEQUENCES TO PUBLIC;
   ```

1. 使用 `pg_repack` 客户端实用程序连接到数据库。使用具有 `rds_superuser` 特权的账户。例如，假设 `rds_test` 角色有 `rds_superuser` 特权。以下语法对完整表执行 `pg_repack`，包括 `postgres` 数据库中的所有表索引。

   ```
   pg_repack -h db-instance-name.111122223333.aws-region.rds.amazonaws.com -U rds_test -k postgres
   ```
**注意**  
必须使用 -k 选项进行连接。不支持 -a 选项。

   来自 `pg_repack` 客户端的响应提供有关重新打包的数据库实例上的表的信息。

   ```
   INFO: repacking table "pgbench_tellers"
   INFO: repacking table "pgbench_accounts"
   INFO: repacking table "pgbench_branches"
   ```

1. 以下语法对 `postgres` 数据库中包含索引的单个表 `orders` 进行重新打包。

   ```
   pg_repack -h db-instance-name.111122223333.aws-region.rds.amazonaws.com -U rds_test --table orders -k postgres
   ```

   以下语法仅重新打包 `postgres` 数据库中 `orders` 表的索引。

   ```
   pg_repack -h db-instance-name.111122223333.aws-region.rds.amazonaws.com -U rds_test --table orders --only-indexes -k postgres
   ```

## 在重新打包期间监控新表
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack.Monitoring"></a>
+ 在重新打包的交换和删除阶段之前，数据库的大小增加量为表的总大小减去膨胀。您可以监控数据库大小的增长率，计算重新打包的速度，并粗略估计完成初始数据传输所需的时间。

  例如，假设表的总大小为 2TB，数据库的大小为 4TB，表中的总膨胀为 1TB。重新打包操作结束时计算返回的数据库总大小值如下：

   `2TB (Table size)` \$1 `4 TB (Database size)` - `1TB (Table bloat)` = `5TB`

  您可以通过对两个时间点之间的增长率（以字节为单位）进行采样来粗略估计重新打包操作的速度。如果增长率为每分钟 1GB，则可能需要 1000 分钟或大约 16.6 小时才能完成初始表构建操作。除了初始表构建外，`pg_repack` 还需要应用应计更改。所需时间取决于应用持续更改以及应计更改的速率。
**注意**  
您可以使用 `pgstattuple` 扩展来计算表中的膨胀。有关更多信息，请参阅 [pgstattuple](https://www.postgresql.org/docs/current/pgstattuple.html)。
+ 重新打包架构下 `pg_repack's` 日志表中的行数表示在初始加载后待应用于新表的更改量。

  您可以检查 `pg_stat_all_tables` 中的 `pg_repack's` 日志表以监控应用于新表的更改。`pg_stat_all_tables.n_live_tup` 表示待应用于新表的记录数。有关更多信息，请参阅 [pg\$1stat\$1all\$1tables](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW)。

  ```
  postgres=>SELECT relname,n_live_tup FROM pg_stat_all_tables WHERE schemaname = 'repack' AND relname ILIKE '%log%';
          
  -[ RECORD 1 ]---------
  relname    | log_16490
  n_live_tup | 2000000
  ```
+ 您可以使用 `pg_stat_statements` 扩展来找出重新打包操作中每个步骤所花费的时间。这有助于准备在生产环境中应用相同的重新打包操作。您可以调整 `LIMIT` 子句以进一步扩展输出。

  ```
  postgres=>SELECT
       SUBSTR(query, 1, 100) query,
       round((round(total_exec_time::numeric, 6) / 1000 / 60),4) total_exec_time_in_minutes
   FROM
       pg_stat_statements
   WHERE
       query ILIKE '%repack%'
   ORDER BY
       total_exec_time DESC LIMIT 5;
          
   query                                                                 | total_exec_time_in_minutes
  -----------------------------------------------------------------------+----------------------------
   CREATE UNIQUE INDEX index_16493 ON repack.table_16490 USING btree (a) |                     6.8627
   INSERT INTO repack.table_16490 SELECT a FROM ONLY public.t1           |                     6.4150
   SELECT repack.repack_apply($1, $2, $3, $4, $5, $6)                    |                     0.5395
   SELECT repack.repack_drop($1, $2)                                     |                     0.0004
   SELECT repack.repack_swap($1)                                         |                     0.0004
  (5 rows)
  ```

重新打包完全是一项不合时宜的操作，因此原始表不会受到影响，我们预计不会出现任何需要恢复原始表的意外挑战。如果重新打包意外失败，则必须检查错误的原因并加以解决。

问题解决后，在表所在的数据库中删除并重新创建 `pg_repack` 扩展，然后重试 `pg_repack` 步骤。此外，计算资源的可用性和表的并行可访问性在及时完成重新打包操作方面起着至关重要的作用。

# 升级和使用 PLV8 扩展
<a name="PostgreSQL.Concepts.General.UpgradingPLv8"></a>

PLV8 是适用于 PostgreSQL 的可信 Javascript 语言扩展。您可以将其用于存储过程、触发条件和其他可从 SQL 调用的过程代码。PostgreSQL 的所有当前版本都支持此语言扩展。

如果使用 [PLV8](https://plv8.github.io/) 并将 PostgreSQL 升级到新的 PLV8 版本，您可以立即利用新扩展。按下列步骤将目录元数据与新版本的 PLV8 进行同步。这些步骤是可选的，但我们强烈建议您完成这些步骤以避免元数据错配警告。

升级过程会丢弃所有现有的 PLV8 功能。因此，建议您在升级之前创建 RDS for PostgreSQL 数据库实例的快照。有关更多信息，请参阅 [为 Amazon RDS 的单可用区数据库实例创建数据库快照](USER_CreateSnapshot.md)。

**重要**  
从 PostgreSQL 版本 18 开始，Amazon RDS for PostgreSQL 将弃用 `plcoffee` 和 `plls` PostgreSQL 扩展。建议您停止在应用程序中使用 CoffeeScript 和 LiveScript，以确保为未来的引擎版本升级提供升级途径。

**将目录元数据与新版本的 PLV8 同步**

1. 确认您需要更新。为此，请在连接到实例的情况下运行以下命令。

   ```
   SELECT * FROM pg_available_extensions WHERE name IN ('plv8','plls','plcoffee');
   ```

   如果您的结果包含的已安装版本的值低于默认版本，请继续该过程以更新扩展。例如，以下结果集指示您应更新。

   ```
   name    | default_version | installed_version |                     comment
   --------+-----------------+-------------------+--------------------------------------------------
   plls    | 2.1.0           | 1.5.3             | PL/LiveScript (v8) trusted procedural language
   plcoffee| 2.1.0           | 1.5.3             | PL/CoffeeScript (v8) trusted procedural language
   plv8    | 2.1.0           | 1.5.3             | PL/JavaScript (v8) trusted procedural language
   (3 rows)
   ```

1. 如果尚未创建 RDS for PostgreSQL 数据库实例的快照，请先创建一个。创建快照时，您可以继续下列步骤。

1. 获取数据库实例中 PLV8 函数的数量，以便在升级后验证是否遗漏函数。例如，以下 SQL 查询会返回用 plv8、plcoffee 和 plls 编写的函数数量。

   ```
   SELECT proname, nspname, lanname 
   FROM pg_proc p, pg_language l, pg_namespace n
   WHERE p.prolang = l.oid
   AND n.oid = p.pronamespace
   AND lanname IN ('plv8','plcoffee','plls');
   ```

1. 使用 pg\$1dump 创建仅架构转储文件。例如，在客户端计算机上的 `/tmp` 目录中创建文件。

   ```
   ./pg_dump -Fc --schema-only -U master postgres >/tmp/test.dmp
   ```

   该示例使用以下选项：
   + `-Fc` - 自定义格式
   + --仅架构 - 仅转储创建架构所需的命令（在本例中为功能）
   + `-U` - RDS 主用户名
   + `database` - 数据库实例的数据库名称

   有关 pg\$1dump 的更多信息，请参阅 PostgreSQL 文档中的 [pg\$1dump](https://www.postgresql.org/docs/current/static/app-pgdump.html )。

1. 提取位于转储文件中的“CREATE FUNCTION”DDL 语句。以下示例使用 `grep` 命令提取创建函数的 DDL 语句并将函数保存到文件中。将在后续步骤中使用该语句重新创建函数。

   ```
   ./pg_restore -l /tmp/test.dmp | grep FUNCTION > /tmp/function_list
   ```

   有关 pg\$1restore 的更多信息，请参阅 PostgreSQL 文档中的 [pg\$1restore](https://www.postgresql.org/docs/current/static/app-pgrestore.html)。

1. 删掉函数和扩展。以下示例将删除基于 PLV8 的任何对象。级联选项确保删除任何依赖项。

   ```
   DROP EXTENSION plv8 CASCADE;
   ```

   如果您的 PostgreSQL 实例包含基于 plcoffee 或 plls 的对象，请对这些扩展重复此步骤。

1. 创建扩展。以下示例将创建 plv8、plcoffee 和 plls 扩展。

   ```
   CREATE EXTENSION plv8;
   CREATE EXTENSION plcoffee;
   CREATE EXTENSION plls;
   ```

1. 使用转储文件和“驱动程序”文件创建函数。

   以下示例将重新创建之前提取的函数。

   ```
   ./pg_restore -U master -d postgres -Fc -L /tmp/function_list /tmp/test.dmp
   ```

1. 使用以下查询验证是否已重新创建所有函数。

   ```
   SELECT * FROM pg_available_extensions WHERE name IN ('plv8','plls','plcoffee'); 
   ```

   PLV8 版本 2 在结果集中添加以下额外行：

   ```
       proname    |  nspname   | lanname
   ---------------+------------+----------
    plv8_version  | pg_catalog | plv8
   ```

# 使用 PL/Rust 通过 Rust 语言编写 PostgreSQL 函数
<a name="PostgreSQL.Concepts.General.Using.PL_Rust"></a>

PL/Rust 是 PostgreSQL 的可信 Rust 语言扩展。您可以将其用于存储过程、函数和其他可从 SQL 调用的过程代码。PL/Rust 语言扩展有以下版本可用：
+ RDS for PostgreSQL 17.1 及更高的 17 版本
+ RDS for PostgreSQL 16.1 及更高的 16 版本
+ RDS for PostgreSQL 15.2-R2 和更高的 15 版本
+ RDS for PostgreSQL 14.9 和更高的 14 版本
+ RDS for PostgreSQL 13.12 和更高的 13 版本

有关更多信息，请参阅 GitHub 上的 [PL/Rust](https://github.com/tcdi/plrust#readme)。

**Topics**
+ [设置 PL/Rust](#PL_Rust-setting-up)
+ [使用 PL/Rust 创建函数](#PL_Rust-create-function)
+ [将 crate 与 PL/Rust 结合使用](#PL_Rust-crates)
+ [PL/Rust 限制](#PL_Rust-limitations)

## 设置 PL/Rust
<a name="PL_Rust-setting-up"></a>

要在数据库实例上安装 plrust 扩展，请将 plrust 添加到与数据库实例相关联的数据库参数组中的 `shared_preload_libraries` 参数。安装了 plrust 扩展后，您可以创建函数。

要修改 `shared_preload_libraries` 参数，数据库实例必须与自定义参数组相关联。有关创建自定义数据库参数组的信息，请参阅[Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。

您可以使用 AWS 管理控制台或 AWS CLI 安装 plrust 扩展程序。

以下步骤假设您的数据库实例与自定义数据库参数组相关联。

### 控制台
<a name="PL_Rust-setting-up.CON"></a>

**在 `shared_preload_libraries` 参数中安装 plrust 扩展**

使用作为 `rds_superuser` 组（角色）成员的账户完成以下步骤。

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

1. 在导航窗格中，选择 **Databases (数据库)**。

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

1. 打开数据库实例的**配置**选项卡，并找到数据库实例参数组链接。

1. 选择此链接以打开与您的数据库实例关联的自定义参数。

1. 在**参数**搜索字段中，键入 `shared_pre` 以查找 **`shared_preload_libraries`** 参数。

1. 选择 **Edit parameters**（编辑参数）以访问属性值。

1. 将 plrust 添加到**值**字段的列表中。使用逗号分隔值列表中的项目。

1. 重启数据库实例以使对 `shared_preload_libraries` 参数的更改生效。初次重启可能需要额外的时间才能完成。

1. 当实例可用时，验证 plrust 是否已初始化。使用 `psql` 连接到数据库实例，然后并运行以下命令。

   ```
   SHOW shared_preload_libraries;
   ```

   您的输出应类似于以下内容：

   ```
   shared_preload_libraries 
   --------------------------
   rdsutils,plrust
   (1 row)
   ```

### AWS CLI
<a name="PL_Rust-setting-up-CLI"></a>

**在 shared\$1preload\$1libraries 参数中安装 plrust 扩展**

使用作为 `rds_superuser` 组（角色）成员的账户完成以下步骤。

1. 使用 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) AWS CLI 命令将 plrust 添加到 `shared_preload_libraries` 参数。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=plrust,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用 [reboot-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/reboot-db-instance) AWS CLI 命令重启数据库实例并初始化 plrust 库。初次重启可能需要额外的时间才能完成。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 当实例可用时，您可以验证 plrust 已初始化。使用 `psql` 连接到数据库实例，然后并运行以下命令。

   ```
   SHOW shared_preload_libraries;
   ```

   您的输出应类似于以下内容：

   ```
   shared_preload_libraries
   --------------------------
   rdsutils,plrust
   (1 row)
   ```

## 使用 PL/Rust 创建函数
<a name="PL_Rust-create-function"></a>

PL/Rust 会将函数编译为动态库、加载动态库并执行该库。

以下 Rust 函数从数组中筛选出倍数。

```
postgres=> CREATE LANGUAGE plrust;
CREATE EXTENSION
```

```
CREATE OR REPLACE FUNCTION filter_multiples(a BIGINT[], multiple BIGINT) RETURNS BIGINT[]
    IMMUTABLE STRICT
    LANGUAGE PLRUST AS
$$
    Ok(Some(a.into_iter().filter(|x| x.unwrap() % multiple != 0).collect()))
$$;
        
WITH gen_values AS (
SELECT ARRAY(SELECT * FROM generate_series(1,100)) as arr)
SELECT filter_multiples(arr, 3)
from gen_values;
```

## 将 crate 与 PL/Rust 结合使用
<a name="PL_Rust-crates"></a>

在 RDS for PostgreSQL 版本 16.3-R2 及更高版本、15.7-R2 及更高的 15 版本、14.12-R2 及更高的 14 版本、13.15-R2 及更高的 13 版本中，PL/Rust 支持额外的 crate：
+ `url` 
+ `regex` 
+ `serde` 
+ `serde_json` 

在 RDS for PostgreSQL 版本 15.5-R2 及更高版本、14.10-R2 及更高的 14 版本、13.13-R2 及更高的 13 版本中，PL/Rust 支持另外两个 crate：
+ `croaring-rs` 
+ `num-bigint` 

从 Amazon RDS for PostgreSQL 版本 15.4、14.9 和 13.12 开始，PL/Rust 支持以下 crate：
+ `aes` 
+ `ctr` 
+ `rand` 

这些 crate 仅支持默认特征。新的 RDS for PostgreSQL 版本可能包含更新版本的 crate，并且可能不再支持旧版本的 crate。

按照执行主要版本升级的最佳实践来测试您的 PL/Rust 函数是否与新的主要版本兼容。有关更多信息，请参阅博客[将 Amazon RDS 升级到 PostgreSQL 主要和次要版本的最佳实践](https://aws.amazon.com/blogs/database/best-practices-for-upgrading-amazon-rds-to-major-and-minor-versions-of-postgresql/)，以及《Amazon RDS 用户指南》中的[为 Amazon RDS 升级 PostgreSQL 数据库引擎](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.PostgreSQL.html)。

有关在创建 PL/Rust 函数时使用依赖关系的示例，请访问[使用依赖关系](https://tcdi.github.io/plrust/use-plrust.html#use-dependencies)。

## PL/Rust 限制
<a name="PL_Rust-limitations"></a>

默认情况下，数据库用户无法使用 PL/Rust。要提供对 PL/Rust 的访问权限，请以具有 rds\$1superuser 权限的用户身份进行连接，然后运行以下命令：

```
postgres=> GRANT USAGE ON LANGUAGE PLRUST TO user;
```

# 使用 PostGIS 扩展管理空间数据
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS"></a>

PostGIS 是一个 PostgreSQL 扩展，用于存储和管理空间信息。要了解有关 PostGIS 的更多信息，请参阅 [PostGIS.net](https://postgis.net/)。

从版本 10.5 开始，PostgreSQL 支持 PostGIS 用于处理地图框矢量平铺数据的 libprotobuf 1.3.0 库。

设置 PostGIS 扩展需要 `rds_superuser` 权限。我们建议您创建一个用户（角色），以管理 PostGIS 和您的空间数据。PostGIS 扩展及其相关组件为 PostgreSQL 添加了数千个函数。如果这对您的使用案例有意义，请考虑在自己的架构中创建 PostGIS 扩展。以下示例说明了如何在其各自的数据库中安装扩展，但这并不是必需的。

**Topics**
+ [步骤 1：创建用户（角色）来管理 PostGIS 扩展](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Connect)
+ [步骤 2：加载 PostGIS 扩展](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.LoadExtensions)
+ [步骤 3：移交扩展架构的所有权](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferOwnership)
+ [步骤 4：移交 PostGIS 表的所有权](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferObjects)
+ [步骤 5：测试扩展](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Test)
+ [步骤 6：升级 PostGIS 扩展](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Update)
+ [PostGIS 扩展版本](#CHAP_PostgreSQL.Extensions.PostGIS)
+ [将 PostGIS 2 升级到 PostGIS 3](#PostgreSQL.Extensions.PostGIS.versions.upgrading.2-to-3)

## 步骤 1：创建用户（角色）来管理 PostGIS 扩展
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.Connect"></a>

首先，以具有 `rds_superuser` 权限的用户身份连接到 RDS for PostgreSQL 数据库实例。如果您在设置实例时保留原定设置名称，则以 `postgres` 进行连接。

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

创建单独的角色（用户）来管理 PostGIS 扩展。

```
postgres=>  CREATE ROLE gis_admin LOGIN PASSWORD 'change_me';
CREATE ROLE
```

向此角色授予 `rds_superuser` 权限，以允许角色安装扩展。

```
postgres=> GRANT rds_superuser TO gis_admin;
GRANT
```

创建一个要用于 PostGIS 构件的数据库。此为可选步骤。或者，您可以在用户数据库中为 PostGIS 扩展创建架构，但这也不是必需的。

```
postgres=> CREATE DATABASE lab_gis;
CREATE DATABASE
```

为 `gis_admin` 提供 `lab_gis` 数据库的所有权限。

```
postgres=> GRANT ALL PRIVILEGES ON DATABASE lab_gis TO gis_admin;
GRANT
```

退出会话并以 `gis_admin` 身份重新连接 RDS for PostgreSQL 数据库实例。

```
postgres=> psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=gis_admin --password --dbname=lab_gis
Password for user gis_admin:...
lab_gis=>
```

按照后续步骤中的详细说明，继续设置扩展。

## 步骤 2：加载 PostGIS 扩展
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.LoadExtensions"></a>

PostGIS 扩展模块包括多个相关的扩展，它们协同工作以提供地理空间功能。您可能不需要在此步骤中创建的所有扩展，具体取决于您的使用案例。

使用 `CREATE EXTENSION` 语句加载 PostGIS 扩展。

```
CREATE EXTENSION postgis;
CREATE EXTENSION
CREATE EXTENSION postgis_raster;
CREATE EXTENSION
CREATE EXTENSION fuzzystrmatch;
CREATE EXTENSION
CREATE EXTENSION postgis_tiger_geocoder;
CREATE EXTENSION
CREATE EXTENSION postgis_topology;
CREATE EXTENSION
CREATE EXTENSION address_standardizer_data_us;
CREATE EXTENSION
```

您可以通过运行以下示例中显示的 SQL 查询来验证结果，该查询列出了扩展及其所有者。

```
SELECT n.nspname AS "Name",
  pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner"
  FROM pg_catalog.pg_namespace n
  WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'
  ORDER BY 1;
List of schemas
     Name     |   Owner
--------------+-----------
 public       | postgres
 tiger        | rdsadmin
 tiger_data   | rdsadmin
 topology     | rdsadmin
(4 rows)
```

## 步骤 3：移交扩展架构的所有权
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferOwnership"></a>

使用 ALTER SCHEMA 语句将架构的所有权移交给 `gis_admin` 角色。

```
ALTER SCHEMA tiger OWNER TO gis_admin;
ALTER SCHEMA
ALTER SCHEMA tiger_data OWNER TO gis_admin; 
ALTER SCHEMA
ALTER SCHEMA topology OWNER TO gis_admin;
ALTER SCHEMA
```

您可以通过运行以下 SQL 查询来确认所有权变更。或者，您也可以从 psql 命令行使用 `\dn` 元命令。

```
SELECT n.nspname AS "Name",
  pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner"
  FROM pg_catalog.pg_namespace n
  WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'
  ORDER BY 1;

       List of schemas
     Name     |     Owner
--------------+---------------
 public       | postgres
 tiger        | gis_admin
 tiger_data   | gis_admin
 topology     | gis_admin
(4 rows)
```

## 步骤 4：移交 PostGIS 表的所有权
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferObjects"></a>

**注意**  
请勿更改 PostGIS 函数的所有权。PostGIS 的正常运行和未来升级要求这些函数保留原始所有权。有关 PostGIS 权限的更多信息，请参阅 [PostgreSQL Security](https://postgis.net/workshops/postgis-intro/security.html)。

使用以下函数将 PostGIS 表的所有权移交给 `gis_admin` 角色。从 psql 提示符处运行以下语句以创建此函数。

```
CREATE FUNCTION exec(text) returns text language plpgsql volatile AS $f$ BEGIN EXECUTE $1; RETURN $1; END; $f$;
CREATE FUNCTION
```

接下来，运行以下查询以运行 `exec` 函数，该函数进而将运行语句并更改权限。

```
SELECT exec('ALTER TABLE ' || quote_ident(s.nspname) || '.' || quote_ident(s.relname) || ' OWNER TO gis_admin;')
  FROM (
    SELECT nspname, relname
    FROM pg_class c JOIN pg_namespace n ON (c.relnamespace = n.oid) 
    WHERE nspname in ('tiger','topology') AND
    relkind IN ('r','S','v') ORDER BY relkind = 'S')
s;
```

## 步骤 5：测试扩展
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.Test"></a>

为避免需要指定架构名称，请使用以下命令将 `tiger` 架构添加到搜索路径中。

```
SET search_path=public,tiger;
SET
```

使用以下 SELECT 语句测试 `tiger` 架构。

```
SELECT address, streetname, streettypeabbrev, zip
 FROM normalize_address('1 Devonshire Place, Boston, MA 02109') AS na;
address | streetname | streettypeabbrev |  zip
---------+------------+------------------+-------
       1 | Devonshire | Pl               | 02109
(1 row)
```

要了解有关此扩展的更多信息，请参阅 PostGIS 文档中的 [Tiger 地理编码器](https://postgis.net/docs/Extras.html#Tiger_Geocoder)。

使用以下 `SELECT` 语句测试对 `topology` 架构的访问。这将调用 `createtopology` 函数，以使用指定的空间参考标识符（26986）和原定设置容差（0.5）注册新的拓扑对象（my\$1new\$1topo）。要了解更多信息，请参阅 PostGIS 文档中的 [CreateTopology](https://postgis.net/docs/CreateTopology.html)。

```
SELECT topology.createtopology('my_new_topo',26986,0.5);
 createtopology
----------------
              1
(1 row)
```

## 步骤 6：升级 PostGIS 扩展
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.Update"></a>

PostgreSQL 的每个新发行版都支持与该发行版兼容的一个或多个 PostGIS 扩展版本。将 PostgreSQL 引擎升级到新版本不会自动升级 PostGIS 扩展。在升级 PostgreSQL 引擎之前，通常需要将 PostGIS 升级到当前 PostgreSQL 版本的最新可用版本。有关更多信息，请参阅 [PostGIS 扩展版本](#CHAP_PostgreSQL.Extensions.PostGIS)。

PostgreSQL 引擎升级后，您可以再次将 PostGIS 扩展升级到新升级的 PostgreSQL 引擎版本所支持的版本。有关升级 PostgreSQL 引擎的更多信息，请参阅。[如何执行 RDS for PostgreSQL 的主要版本升级](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process.md)

您可以随时检查 RDS for PostgreSQL 数据库实例上可用的 PostGIS 扩展版本更新。为此，请运行以下命令。PostGIS 2.5.0 及更高版本可以使用此功能。

```
SELECT postGIS_extensions_upgrade();
```

如果您的应用程序不支持最新的 PostGIS 版本，您可以安装主要版本中提供的旧版本 PostGIS，如下所示。

```
CREATE EXTENSION postgis VERSION "2.5.5";
```

如果要从旧版本升级到特定 PostGIS 版本，还可以使用以下命令。

```
ALTER EXTENSION postgis UPDATE TO "2.5.5";
```

根据要从中进行升级的版本，您可能需要再次使用此函数。第一次运行该函数的结果决定是否需要额外的升级功能。例如，从 PostGIS 2 升级到 PostGIS 3 就是这种情况。有关更多信息，请参阅 [将 PostGIS 2 升级到 PostGIS 3](#PostgreSQL.Extensions.PostGIS.versions.upgrading.2-to-3)。

如果您升级此扩展是为了准备进行 PostgreSQL 引擎的主要版本升级，则可以继续执行其他初步任务。有关更多信息，请参阅。[如何执行 RDS for PostgreSQL 的主要版本升级](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process.md)

## PostGIS 扩展版本
<a name="CHAP_PostgreSQL.Extensions.PostGIS"></a>

我们建议您安装 《Amazon RDS for PostgreSQL 发布说明》**的 [Amazon RDS for PostgreSQL 的扩展版本](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)中列出的所有扩展版本，如 PostGIS。要获取发行版中可用的版本列表，请使用以下命令。

```
SELECT * FROM pg_available_extension_versions WHERE name='postgis';
```

您可以在《Amazon RDS for PostgreSQL 发布说明》**的以下部分中找到版本信息：
+ [Amazon RDS 上支持的 PostgreSQL 16 版本扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-16x)
+ [Amazon RDS 上支持的 PostgreSQL 版本 15 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-15x)
+ [Amazon RDS 上支持的 PostgreSQL 版本 14 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-14x)
+ [Amazon RDS 上支持的 PostgreSQL 版本 13 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-13x)
+ [Amazon RDS 上支持的 PostgreSQL 版本 12 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-12x)
+ [Amazon RDS 上支持的 PostgreSQL 版本 11 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-11x)
+ [Amazon RDS 上支持的 PostgreSQL 版本 10 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-101x)
+ [Amazon RDS 上支持的 PostgreSQL 版本 9.6.x 扩展](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-96x)

## 将 PostGIS 2 升级到 PostGIS 3
<a name="PostgreSQL.Extensions.PostGIS.versions.upgrading.2-to-3"></a>

从版本 3.0 开始，PostGIS 光栅功能现在是一个单独的扩展，即 `postgis_raster`。此扩展有自己的安装和升级路径。这将从核心 `postgis` 扩展中删除光栅图像处理所需的数十个函数、数据类型和其他构件。这意味着，如果您的使用案例不需要光栅处理，则不需要安装 `postgis_raster` 扩展。

在以下升级示例中，第一个升级命令将光栅功能提取到 `postgis_raster` 扩展。然后，需要使用第二个升级命令将 `postgis_raster` 升级到新版本。

**从 PostGIS 2 升级到 PostGIS 3**

1. 确定 RDS for PostgreSQL 数据库实例上 PostgreSQL 版本可用的 PostGIS 的默认版本。为此，请运行以下查询。

   ```
   SELECT * FROM pg_available_extensions
       WHERE default_version > installed_version;
     name   | default_version | installed_version |                          comment
   ---------+-----------------+-------------------+------------------------------------------------------------
    postgis | 3.1.4           | 2.3.7             | PostGIS geometry and geography spatial types and functions
   (1 row)
   ```

1. 确定 RDS for PostgreSQL 数据库实例上每个数据库中安装的 PostGIS 版本。换句话说，按如下方式查询每个用户数据库。

   ```
   SELECT
       e.extname AS "Name",
       e.extversion AS "Version",
       n.nspname AS "Schema",
       c.description AS "Description"
   FROM
       pg_catalog.pg_extension e
       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
       LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid
       AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass
   WHERE
       e.extname LIKE '%postgis%'
   ORDER BY
       1;
     Name   | Version | Schema |                             Description
   ---------+---------+--------+---------------------------------------------------------------------
    postgis | 2.3.7   | public | PostGIS geometry, geography, and raster spatial types and functions
   (1 row)
   ```

   原定设置版本（PostGIS 3.1.4）和已安装版本（PostGIS 2.3.7）之间的不匹配意味着您需要升级 PostGIS 扩展。

   ```
   ALTER EXTENSION postgis UPDATE;
   ALTER EXTENSION
   WARNING: unpackaging raster
   WARNING: PostGIS Raster functionality has been unpackaged
   ```

1. 运行以下查询，以验证光栅功能现在是否已包含在自己的程序包中。

   ```
   SELECT
       probin,
       count(*)
   FROM
       pg_proc
   WHERE
       probin LIKE '%postgis%'
   GROUP BY
       probin;
             probin          | count
   --------------------------+-------
    $libdir/rtpostgis-2.3    | 107
    $libdir/postgis-3        | 487
   (2 rows)
   ```

   输出将显示版本之间仍然存在差异。PostGIS 函数为版本 3（postgis-3），而光栅函数（rtpostgis）为第 2 版（rtpostgis-2.3）。要完成升级，请再次运行升级命令，如下所示。

   ```
   postgres=> SELECT postgis_extensions_upgrade();
   ```

   您可以放心地忽略警告消息。再次运行以下查询，以验证升级已完成。当 PostGIS 和所有相关扩展未标记为需要升级时，升级即告完成。

   ```
   SELECT postgis_full_version();
   ```

1. 使用以下查询查看已完成的升级过程和单独打包的扩展，并验证其版本是否匹配。

   ```
   SELECT
       e.extname AS "Name",
       e.extversion AS "Version",
       n.nspname AS "Schema",
       c.description AS "Description"
   FROM
       pg_catalog.pg_extension e
       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
       LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid
           AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass
   WHERE
       e.extname LIKE '%postgis%'
   ORDER BY
       1;
         Name      | Version | Schema |                             Description
   ----------------+---------+--------+---------------------------------------------------------------------
    postgis        | 3.1.5   | public | PostGIS geometry, geography, and raster spatial types and functions
    postgis_raster | 3.1.5   | public | PostGIS raster types and functions
   (2 rows)
   ```

   输出显示，PostGIS 2 扩展已升级到 PostGIS 3，并且 `postgis` 和现在独立的 `postgis_raster` 扩展都为版本 3.1.5。

升级完成后，如果您不打算使用光栅功能，则可以按如下方式删除此扩展。

```
DROP EXTENSION postgis_raster;
```

# 使用 Amazon RDS for PostgreSQL 支持的外部数据包装器
<a name="Appendix.PostgreSQL.CommonDBATasks.Extensions.foreign-data-wrappers"></a>

外部数据包装器 (FDW) 是一种特定类型的扩展，提供对外部数据的访问。例如，`oracle_fdw` 扩展允许您的 RDS for PostgreSQL 数据库集群使用 Oracle 数据库。再例如，通过使用 PostgreSQL 本机 `postgres_fdw` 扩展，您可以访问存储在 RDS for PostgreSQL 数据库实例外部的 PostgreSQL 数据库实例中的数据。

在下文中，您可以了解有关几种支持的 PostgreSQL 外部数据包装器的信息。

**Topics**
+ [使用 log\$1fdw 扩展通过 SQL 访问数据库日志](CHAP_PostgreSQL.Extensions.log_fdw.md)
+ [使用 postgres\$1fdw 扩展访问外部数据](postgresql-commondbatasks-fdw.md)
+ [使用 mysql\$1fdw 扩展处理 MySQL 数据库](postgresql-mysql-fdw.md)
+ [通过使用 oracle\$1fdw 扩展来使用 Oracle 数据库](postgresql-oracle-fdw.md)
+ [通过使用 tds\$1fdw 扩展来使用 SQL Server 数据库](postgresql-tds-fdw.md)

# 使用 log\$1fdw 扩展通过 SQL 访问数据库日志
<a name="CHAP_PostgreSQL.Extensions.log_fdw"></a>

RDS for PostgreSQL 数据库实例支持 `log_fdw` 扩展，您可以使用该扩展通过 SQL 界面访问数据库引擎日志。此 `log_fdw` 扩展提供了两个新函数，便于创建数据库日志的外部表：
+ `list_postgres_log_files` – 列出数据库日志目录中的文件，以及文件大小 (以字节为单位)。
+ `create_foreign_table_for_log_file(table_name text, server_name text, log_file_name text)` – 针对当前数据库中的指定文件构建外部表。

`log_fdw` 创建的所有函数均归 `rds_superuser` 所有。`rds_superuser` 角色的成员可以将这些函数的访问权限授予其他数据库用户。

默认情况下，日志文件由 Amazon RDS 以 `stderr`（标准错误）格式生成，如 `log_destination` 参数中指定。此参数只有两个选项，即，`stderr` 和 `csvlog`（逗号分隔值，CSV）。如果您向参数添加 `csvlog` 选项，Amazon RDS 会同时生成 `stderr` 和 `csvlog` 日志。这可能会影响数据库集群的存储容量，因此您需要了解影响日志处理的其它参数。有关更多信息，请参阅 [设置日志目标（`stderr`、`csvlog`）](USER_LogAccess.Concepts.PostgreSQL.overview.parameter-groups.md#USER_LogAccess.Concepts.PostgreSQL.Log_Format)。

生成 `csvlog` 日志的一个优势是 `log_fdw` 扩展允许您构建将数据整齐地拆分为多个列的外部表。为此，您的实例需要与自定义数据库参数组关联，以便您可以更改 `log_destination` 的设置。有关如何执行此操作的更多信息，请参阅。[在 RDS for PostgreSQL 数据库实例上使用参数](Appendix.PostgreSQL.CommonDBATasks.Parameters.md)

以下示例假设 `log_destination` 参数包含 `cvslog`。

**使用 log\$1fdw 扩展**

1. 安装 `log_fdw` 扩展。

   ```
   postgres=> CREATE EXTENSION log_fdw;
   CREATE EXTENSION
   ```

1. 创建日志服务器，作为外部数据包装器。

   ```
   postgres=> CREATE SERVER log_server FOREIGN DATA WRAPPER log_fdw;
   CREATE SERVER
   ```

1. 选择日志文件列表中的所有文件。

   ```
   postgres=> SELECT * FROM list_postgres_log_files() ORDER BY 1;
   ```

   示例响应如下所示。

   ```
             file_name           | file_size_bytes
   ------------------------------+-----------------
    postgresql.log.2023-08-09-22.csv |            1111
    postgresql.log.2023-08-09-23.csv |            1172
    postgresql.log.2023-08-10-00.csv |            1744
    postgresql.log.2023-08-10-01.csv |            1102
   (4 rows)
   ```

1. 为所选文件创建包含单个“log\$1entry”列的表。

   ```
   postgres=> SELECT create_foreign_table_for_log_file('my_postgres_error_log',
        'log_server', 'postgresql.log.2023-08-09-22.csv');
   ```

   除了告知现在存在表格外，响应不提供详细信息。

   ```
   -----------------------------------
   (1 row)
   ```

1. 选择日志文件的示例。以下代码检索日志时间和错误消息描述。

   ```
   postgres=> SELECT log_time, message FROM my_postgres_error_log ORDER BY 1;
   ```

   示例响应如下所示。

   ```
                log_time             |                                  message
   ----------------------------------+---------------------------------------------------------------------------
   Tue Aug 09 15:45:18.172 2023 PDT | ending log output to stderr
   Tue Aug 09 15:45:18.175 2023 PDT | database system was interrupted; last known up at 2023-08-09 22:43:34 UTC
   Tue Aug 09 15:45:18.223 2023 PDT | checkpoint record is at 0/90002E0
   Tue Aug 09 15:45:18.223 2023 PDT | redo record is at 0/90002A8; shutdown FALSE
   Tue Aug 09 15:45:18.223 2023 PDT | next transaction ID: 0/1879; next OID: 24578
   Tue Aug 09 15:45:18.223 2023 PDT | next MultiXactId: 1; next MultiXactOffset: 0
   Tue Aug 09 15:45:18.223 2023 PDT | oldest unfrozen transaction ID: 1822, in database 1
   (7 rows)
   ```

# 使用 postgres\$1fdw 扩展访问外部数据
<a name="postgresql-commondbatasks-fdw"></a>

您可以使用 [postgres\$1fdw](https://www.postgresql.org/docs/current/static/postgres-fdw.html) 扩展访问远程数据库服务器上表中的数据。如果您从 PostgreSQL 数据库实例设置远程连接，则访问还可用于您的只读副本。

**使用 postgres\$1fdw 访问远程数据库服务器**

1. 安装 postgres\$1fdw 扩展。

   ```
   CREATE EXTENSION postgres_fdw;
   ```

1. 使用 CREATE SERVER 创建外部数据服务器。

   ```
   CREATE SERVER foreign_server
   FOREIGN DATA WRAPPER postgres_fdw
   OPTIONS (host 'xxx.xx.xxx.xx', port '5432', dbname 'foreign_db');
   ```

1. 创建用户映射，用于标识将在远程服务器上使用的角色。
**重要**  
要掩蔽密码以使其不出现在日志中，请在会话级别设置 `log_statement=none`。在参数级别进行设置不会掩蔽密码。

   ```
   CREATE USER MAPPING FOR local_user
   SERVER foreign_server
   OPTIONS (user 'foreign_user', password 'password');
   ```

1. 创建一个表，该表映射到远程服务器上的表。

   ```
   CREATE FOREIGN TABLE foreign_table (
           id integer NOT NULL,
           data text)
   SERVER foreign_server
   OPTIONS (schema_name 'some_schema', table_name 'some_table');
   ```

# 使用 mysql\$1fdw 扩展处理 MySQL 数据库
<a name="postgresql-mysql-fdw"></a>

要从 RDS for PostgreSQL 数据库实例访问 MySQL 兼容数据库，您可以安装并使用 `mysql_fdw` 扩展。这款外部数据包装器允许您使用 RDS for MySQL、Aurora MySQL、MariaDB 和其他 MySQL 兼容数据库。从 RDS for PostgreSQL 数据库实例到 MySQL 数据库的连接会尽可能加密，具体取决于客户端和服务器配置。但是，如果您愿意，可以强制加密。有关更多信息，请参阅 [将传输中加密与扩展配合使用](#postgresql-mysql-fdw.encryption-in-transit)。

`mysql_fdw` 扩展在 Amazon RDS for PostgreSQL 版本 14.2、13.6 以及更高版本中受支持。它支持从 RDS for PostgreSQL 数据库到 MySQL 兼容数据库实例上的表的选择、插入、更新和删除。

**Topics**
+ [将 RDS for PostgreSQL 数据库设置为使用 mysql\$1fdw 扩展](#postgresql-mysql-fdw.setting-up)
+ [示例：从 RDS for PostgreSQL 使用 RDS for MySQL 数据库](#postgresql-mysql-fdw.using-mysql_fdw)
+ [将传输中加密与扩展配合使用](#postgresql-mysql-fdw.encryption-in-transit)

## 将 RDS for PostgreSQL 数据库设置为使用 mysql\$1fdw 扩展
<a name="postgresql-mysql-fdw.setting-up"></a>

在您的 RDS for PostgreSQL 数据库实例上设置 `mysql_fdw` 扩展涉及到在数据库实例中加载扩展，然后创建到 MySQL 数据库实例的连接点。对于该任务，您需要了解有关 MySQL 数据库实例的以下详细信息：
+ 主机名或终端节点。对于RDS for MySQL 数据库实例，您可以使用控制台查找终端节点。选择 Connectivity & security（连接和安全）选项卡，然后查看 Endpoint and port（终端节点和端口）部分。
+ 端口号。MySQL 的默认端口是 3306。
+ 数据库的名称。数据库标识符。

您还需要为 MySQL 端口 3306 提供对安全组或访问控制列表 (ACL) 的访问权限。RDS for PostgreSQL 数据库实例和 RDS for MySQL 数据库实例均需要访问端口 3306。如果访问权限配置不正确，当尝试连接到 MySQL 兼容表时，您会看到一条与以下内容类似的错误消息：

```
ERROR: failed to connect to MySQL: Can't connect to MySQL server on 'hostname.aws-region.rds.amazonaws.com:3306' (110)
```

在以下过程中，您（作为 `rds_superuser` 账户）创建外部服务器。然后，您将访问外部服务器的权限授予特定用户。然后，这些用户创建其自身到相应 MySQL 用户账户的映射以使用 MySQL 数据库实例。

**使用 mysql\$1fdw 访问 MySQL 数据库服务器**

1. 使用具有 `rds_superuser` 角色的账户连接到您的 PostgreSQL 数据库实例。如果在创建 RDS for PostgreSQL 数据库实例时接受默认值，则用户名为 `postgres`，您可以使用 `psql` 命令行工具进行连接，如下所示：

   ```
   psql --host=your-DB-instance.aws-region.rds.amazonaws.com --port=5432 --username=postgres –-password
   ```

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

   ```
   postgres=> CREATE EXTENSION mysql_fdw;
   CREATE EXTENSION
   ```

在 RDS for PostgreSQL 数据库实例上安装扩展后，您可以设置提供与 MySQL 数据库连接的外部服务器。

**创建外部服务器**

在 RDS for PostgreSQL 数据库实例上执行这些任务。这些步骤假定您以具有 `rds_superuser` 特权的用户身份连接，例如 `postgres`。

1. 在 RDS for PostgreSQL 数据库实例中创建外部服务器：

   ```
   postgres=> CREATE SERVER mysql-db FOREIGN DATA WRAPPER mysql_fdw OPTIONS (host 'db-name.111122223333.aws-region.rds.amazonaws.com', port '3306');
   CREATE SERVER
   ```

1. 向适当的用户授予访问外部服务器的权限。这些用户应该是非管理员用户，即，没有 `rds_superuser` 角色的用户。

   ```
   postgres=> GRANT USAGE ON FOREIGN SERVER mysql-db to user1;
   GRANT
   ```

PostgreSQL 用户通过外部服务器创建和管理其自身与 MySQL 数据库的连接。

## 示例：从 RDS for PostgreSQL 使用 RDS for MySQL 数据库
<a name="postgresql-mysql-fdw.using-mysql_fdw"></a>

假设您在 RDS for PostgreSQL 数据库实例上有一个简单的表。您的 RDS for PostgreSQL 用户想要在该表中查询（`SELECT`）、`INSERT`、`UPDATE` 和 `DELETE` 项目。假设 `mysql_fdw` 扩展是在您的 RDS for PostgreSQL 数据库实例上创建的，如前面的过程中所述。以具有 `rds_superuser` 权限的用户身份连接到 RDS for PostgreSQL 数据库实例后，您可以继续执行以下步骤。

1. 在 RDS for PostgreSQL 数据库实例上，创建一个外部服务器：

   ```
   test=> CREATE SERVER mysqldb FOREIGN DATA WRAPPER mysql_fdw OPTIONS (host 'your-DB.aws-region.rds.amazonaws.com', port '3306');
   CREATE SERVER
   ```

1. 将使用权授予没有 `rds_superuser` 权限的用户，例如 `user1`：

   ```
   test=> GRANT USAGE ON FOREIGN SERVER mysqldb TO user1;
   GRANT
   ```

1. 作为 *user1* 连接，然后创建一个到 MySQL 用户的映射：

   ```
   test=> CREATE USER MAPPING FOR user1 SERVER mysqldb OPTIONS (username 'myuser', password 'mypassword');
   CREATE USER MAPPING
   ```

1. 创建链接到 MySQL 表的外部表：

   ```
   test=> CREATE FOREIGN TABLE mytab (a int, b text) SERVER mysqldb OPTIONS (dbname 'test', table_name '');
   CREATE FOREIGN TABLE
   ```

1. 针对外表运行简单查询：

   ```
   test=> SELECT * FROM mytab;
   a |   b
   ---+-------
   1 | apple
   (1 row)
   ```

1. 您可以从 MySQL 表中添加、更改和删除数据。例如：

   ```
   test=> INSERT INTO mytab values (2, 'mango');
   INSERT 0 1
   ```

   再次运行 `SELECT` 查询以查看结果：

   ```
   test=> SELECT * FROM mytab ORDER BY 1;
    a |   b
   ---+-------
   1 | apple
   2 | mango
   (2 rows)
   ```

## 将传输中加密与扩展配合使用
<a name="postgresql-mysql-fdw.encryption-in-transit"></a>

默认情况下，从 RDS for PostgreSQL 到 MySQL 的连接使用传输中加密（TLS/SSL）。但是，当客户端和服务器配置不同时，连接会回退为非加密状态。您可以通过在 RDS for MySQL 用户账户上指定 `REQUIRE SSL` 选项来对所有传出连接强制加密。这种方法也适用于 MariaDB 和 Aurora MySQL 用户账户。

对于配置为 `REQUIRE SSL` 的 MySQL 用户帐户，如果无法建立安全连接，则连接尝试将失败。

要对现有 MySQL 数据库用户帐户强制加密，可以使用 `ALTER USER` 命令。根据 MySQL 版本的不同，语法有所不同，如下表所示。有关更多信息，请参阅《MySQL 参考手册》**中的 [ALTER USER](https://dev.mysql.com/doc/refman/8.0/en/alter-user.html)。


| MySQL 5.7、MySQL 8.0 | MySQL 5.6 | 
| --- | --- | 
|  `ALTER USER 'user'@'%' REQUIRE SSL;`  |  `GRANT USAGE ON *.* to 'user'@'%' REQUIRE SSL;`  | 

有关 `mysql_fdw` 扩展的更多信息，请参阅 [mysql\$1fdw](https://github.com/EnterpriseDB/mysql_fdw) 文档。

# 通过使用 oracle\$1fdw 扩展来使用 Oracle 数据库
<a name="postgresql-oracle-fdw"></a>

要从 RDS for PostgreSQL 数据库实例访问 Oracle 数据库，您可以安装并使用 `oracle_fdw` 扩展。此扩展是 Oracle 数据库的外部数据包装器。要了解有关此扩展的更多信息，请参阅 [oracle\$1fdw](https://github.com/laurenz/oracle_fdw) 文档。

RDS for PostgreSQL 12.7、13.3 及更高版本支持 `oracle_fdw` 扩展。

**Topics**
+ [启用 oracle\$1fdw 扩展](#postgresql-oracle-fdw.enabling)
+ [示例：使用链接到 Amazon RDS for Oracle Database 的外部服务器](#postgresql-oracle-fdw.example)
+ [在传输过程中使用加密](#postgresql-oracle-fdw.encryption)
+ [了解 pg\$1user\$1mappings 视图和权限](#postgresql-oracle-fdw.permissions)

## 启用 oracle\$1fdw 扩展
<a name="postgresql-oracle-fdw.enabling"></a>

要使用 oracle\$1fdw 扩展，请执行以下步骤。

**启用 oracle\$1fdw 扩展**
+ 使用具有 `rds_superuser` 权限的账户运行以下命令。

  ```
  CREATE EXTENSION oracle_fdw;
  ```

## 示例：使用链接到 Amazon RDS for Oracle Database 的外部服务器
<a name="postgresql-oracle-fdw.example"></a>

以下示例展示如何使用链接到 Amazon RDS for Oracle Database 的外部服务器。

**创建链接到 RDS for Oracle 数据库的外部服务器**

1. 请注意 RDS for Oracle 数据库实例上的以下内容：
   + Endpoint
   + 端口
   + 数据库名称

1. 创建外部服务器。

   ```
   test=> CREATE SERVER oradb FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver '//endpoint:port/DB_name');
   CREATE SERVER
   ```

1. 将使用权授予没有 `rds_superuser` 权限的用户，例如 `user1`。

   ```
   test=> GRANT USAGE ON FOREIGN SERVER oradb TO user1;
   GRANT
   ```

1. 作为 `user1` 连接并创建到 Oracle 用户的映射。

   ```
   test=> CREATE USER MAPPING FOR user1 SERVER oradb OPTIONS (user 'oracleuser', password 'mypassword');
   CREATE USER MAPPING
   ```

1. 创建链接到 Oracle 表的外部表。

   ```
   test=> CREATE FOREIGN TABLE mytab (a int) SERVER oradb OPTIONS (table 'MYTABLE');
   CREATE FOREIGN TABLE
   ```

1. 查询外部表。

   ```
   test=>  SELECT * FROM mytab;
   a
   ---
   1
   (1 row)
   ```

如果查询报告以下错误，请检查您的安全组和访问控制列表（ACL）以确保两个实例可以通信。

```
ERROR: connection for foreign table "mytab" cannot be established
DETAIL: ORA-12170: TNS:Connect timeout occurred
```

## 在传输过程中使用加密
<a name="postgresql-oracle-fdw.encryption"></a>

PostgreSQL-to-Oracle 传输中加密基于客户端和服务器配置参数的组合。有关使用 Oracle 21c 的示例，请参阅 Oracle 文档中的[关于协商加密和完整性的值](https://docs.oracle.com/en/database/oracle/oracle-database/21/dbseg/configuring-network-data-encryption-and-integrity.html#GUID-3A2AF4AA-AE3E-446B-8F64-31C48F27A2B5)。用于 Amazon RDS 上 oracle\$1fdw 的客户端配置有 `ACCEPTED`，这意味着加密取决于 Oracle 数据库服务器配置，并且使用 Oracle 安全库（libnnz）进行加密。

如果您的数据库位于 RDS for Oracle 上，请参阅 [Oracle 本机网络加密](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.Oracle.Options.NetworkEncryption.html)来配置加密。

## 了解 pg\$1user\$1mappings 视图和权限
<a name="postgresql-oracle-fdw.permissions"></a>

PostgreSQL 目录 `pg_user_mapping` 存储 RDS for PostgreSQL 用户到外部数据（远程）服务器上用户的映射。虽然对目录的访问受到限制，但是您可以使用 `pg_user_mappings` 视图来查看映射。在下面，您可以找到一个示例，该示例演示如何将权限应用于示例 Oracle 数据库，但此信息更普遍地适用于任何外部数据包装器。

在以下输出中，您可以找到映射到三个不同示例用户的角色和权限。用户 `rdssu1` 和 `rdssu2` 是 `rds_superuser` 角色的成员，而 `user1` 不是。此示例使用 `psql` 元命令 `\du` 列出现有角色。

```
test=>  \du
                                                               List of roles
    Role name    |                         Attributes                         |                          Member of
-----------------+------------------------------------------------------------+-------------------------------------------------------------
 rdssu1          |                                                            | {rds_superuser}
 rdssu2          |                                                            | {rds_superuser}
 user1           |                                                            | {}
```

所有用户，包括具有 `rds_superuser` 权限的用户，都可以查看 `pg_user_mappings` 表中他们自己的用户映射 (`umoptions`)。如以下示例所示，当 `rdssu1` 尝试获取所有用户映射时，即使存在 `rdssu1``rds_superuser` 权限，也会出现错误：

```
test=> SELECT * FROM pg_user_mapping;
ERROR: permission denied for table pg_user_mapping
```

下面是一些示例。

```
test=> SET SESSION AUTHORIZATION rdssu1;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |            umoptions
-------+-------+---------+--------+------------+----------------------------------
 16414 | 16411 | oradb   |  16412 | user1      |
 16423 | 16411 | oradb   |  16421 | rdssu1     | {user=oracleuser,password=mypwd}
 16424 | 16411 | oradb   |  16422 | rdssu2     |
 (3 rows)

test=> SET SESSION AUTHORIZATION rdssu2;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |            umoptions
-------+-------+---------+--------+------------+----------------------------------
 16414 | 16411 | oradb   |  16412 | user1      |
 16423 | 16411 | oradb   |  16421 | rdssu1     |
 16424 | 16411 | oradb   |  16422 | rdssu2     | {user=oracleuser,password=mypwd}
 (3 rows)

test=> SET SESSION AUTHORIZATION user1;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |           umoptions
-------+-------+---------+--------+------------+--------------------------------
 16414 | 16411 | oradb   |  16412 | user1      | {user=oracleuser,password=mypwd}
 16423 | 16411 | oradb   |  16421 | rdssu1     |
 16424 | 16411 | oradb   |  16422 | rdssu2     |
 (3 rows)
```

由于 `information_schema._pg_user_mappings` 和 `pg_catalog.pg_user_mappings` 的实施差异，手动创建的 `rds_superuser` 需要额外的权限才能在 `pg_catalog.pg_user_mappings` 中查看密码。

`rds_superuser` 无需额外权限即可在 `information_schema._pg_user_mappings` 中查看密码。

没有 `rds_superuser` 角色的用户只能在以下条件下在 `pg_user_mappings` 中查看密码：
+ 当前用户是被映射的用户，拥有服务器或对其具有 `USAGE` 权限。
+ 当前用户是服务器所有者，此映射用于 `PUBLIC`。

# 通过使用 tds\$1fdw 扩展来使用 SQL Server 数据库
<a name="postgresql-tds-fdw"></a>

您可以使用 PostgreSQL `tds_fdw` 扩展来访问支持表格数据流 (TDS) 协议的数据库，例如 Sybase 和 Microsoft SQL Server 数据库。此外部数据包装器可让您从 RDS for PostgreSQL 数据库实例 连接到使用 TDS 协议的数据库，包括 Amazon RDS for Microsoft SQL Server。有关更多信息，请参阅 GitHub 上的 [tds-fdw/tds\$1fdw](https://github.com/tds-fdw/tds_fdw) 文档。

Amazon RDS for PostgreSQL 版本 14.2、13.6 及更高版本支持该 `tds_fdw` 扩展。

## 将 Aurora PostgreSQL 数据库设置为使用 tds\$1fdw 扩展
<a name="postgresql-tds-fdw-setting-up"></a>

在以下过程中，您可以找到设置 `tds_fdw` 并将其与 RDS for PostgreSQL 数据库实例结合使用的示例。在可以使用 `tds_fdw` 连接到 SQL Server 数据库之前，您需要获取实例的以下详细信息：
+ 主机名或终端节点。对于 RDS for SQL Server 数据库实例，您可以使用控制台查找终端节点。选择 Connectivity & security（连接和安全）选项卡，然后查看 Endpoint and port（终端节点和端口）部分。
+ 端口号。Microsoft SQL Server 的默认端口是 1433。
+ 数据库的名称。数据库标识符。

您还需要为 SQL Server 端口 1433 提供对安全组或访问控制列表 (ACL) 的访问权限。RDS for PostgreSQL 数据库实例和 RDS for SQL Server 数据库实例都需要访问端口 1433。如果访问权限配置不正确，当您尝试查询 Microsoft SQL Server 时，会看到以下错误消息：

```
ERROR: DB-Library error: DB #: 20009, DB Msg: Unable to connect:
Adaptive Server is unavailable or does not exist (mssql2019.aws-region.rds.amazonaws.com), OS #: 0, OS Msg: Success, Level: 9
```

**使用 tds\$1fdw 连接到 SQL Server 数据库**

1. 使用具有 `rds_superuser` 角色的账户连接到您的 PostgreSQL 数据库实例：

   ```
   psql --host=your-DB-instance.aws-region.rds.amazonaws.com --port=5432 --username=test –-password
   ```

1. 安装 `tds_fdw` 扩展：

   ```
   test=> CREATE EXTENSION tds_fdw;
   CREATE EXTENSION
   ```

在 RDS for PostgreSQL 数据库实例上安装扩展后，应设置外部服务器。

**创建外部服务器**

使用具有 `rds_superuser` 权限的账户在 RDS for PostgreSQL 数据库实例上执行这些任务。

1. 在 RDS for PostgreSQL 数据库实例中创建外部服务器：

   ```
   test=> CREATE SERVER sqlserverdb FOREIGN DATA WRAPPER tds_fdw OPTIONS (servername 'mssql2019.aws-region.rds.amazonaws.com', port '1433', database 'tds_fdw_testing');
   CREATE SERVER
   ```

   要访问 SQLServer 端的非 ASCII 数据，请在 RDS for PostgreSQL 数据库实例中使用 character\$1set 选项创建服务器链接：

   ```
   test=> CREATE SERVER sqlserverdb FOREIGN DATA WRAPPER tds_fdw OPTIONS (servername 'mssql2019.aws-region.rds.amazonaws.com', port '1433', database 'tds_fdw_testing', character_set 'UTF-8');
   CREATE SERVER
   ```

1. 向没有 `rds_superuser` 角色权限的用户授予权限，例如 `user1`：

   ```
   test=> GRANT USAGE ON FOREIGN SERVER sqlserverdb TO user1;
   ```

1. 以 user1 身份进行连接，然后创建到 SQL Server 用户的映射：

   ```
   test=> CREATE USER MAPPING FOR user1 SERVER sqlserverdb OPTIONS (username 'sqlserveruser', password 'password');
   CREATE USER MAPPING
   ```

1. 创建链接到 SQL Server 表的外部表：

   ```
   test=> CREATE FOREIGN TABLE mytab (a int) SERVER sqlserverdb OPTIONS (table 'MYTABLE');
   CREATE FOREIGN TABLE
   ```

1. 查询外部表：

   ```
   test=> SELECT * FROM mytab;
    a
   ---
    1
   (1 row)
   ```

### 使用传输中的加密进行连接
<a name="postgresql-tds-fdw-ssl-tls-encryption"></a>

RDS for PostgreSQL 到 SQL Server 的连接使用传输中加密 (TLS/SSL)，具体取决于 SQL Server 数据库配置。如果 SQL Server 未配置为加密，则向 SQL Server 数据库发出请求的 RDS for PostgreSQL 客户端将回退到未加密状态。

您可以通过设置 `rds.force_ssl` 参数对与 RDS for SQL Server 数据库实例的连接进行加密。要了解操作方法，请参阅[强制与数据库实例的连接使用 SSL](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/SQLServer.Concepts.General.SSL.Using.html#SQLServer.Concepts.General.SSL.Forcing)。有关 RDS for SQL Server 的 SSL/TLS 配置的更多信息，请参阅[将 SSL 与 Microsoft SQL Server 数据库实例结合使用](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/SQLServer.Concepts.General.SSL.Using.html)。

# 使用适用于 PostgreSQL 的可信语言扩展
<a name="PostgreSQL_trusted_language_extension"></a>

适用于 PostgreSQL 的可信语言扩展是一个用于构建 PostgreSQL 扩展的开源开发套件。它允许您构建高性能 PostgreSQL 扩展，并在您的 RDS for PostgreSQL 数据库实例上安全地运行它们。通过使用适用于 PostgreSQL 的可信语言扩展（TLE），您可以创建 PostgreSQL 扩展，这些扩展遵循已记载的用于扩展 PostgreSQL 功能的方法。有关更多信息，请参阅 PostgreSQL 文档中的[将相关对象打包为扩展](https://www.postgresql.org/docs/current/extend-extensions.html)。

TLE 的一个关键好处是，您可以在不提供对 PostgreSQL 实例底层文件系统的访问权限的环境中使用它。以前，安装新扩展需要访问文件系统。TLE 消除了这一约束。它提供了一个开发环境，用于为任何 PostgreSQL 数据库创建新扩展，包括在 RDS for PostgreSQL 数据库实例上运行的扩展。

TLE 旨在防止访问您使用 TLE 创建的扩展的不安全资源。它的运行时环境限制了任何扩展缺陷对单个数据库连接的影响。TLE 还让数据库管理员可以细粒度控制谁可以安装扩展，并为运行扩展提供了权限模型。

以下 RDS for PostgreSQL 版本支持 TLE：
+  版本 18.1 及更高的 18 版本 
+  版本 17.1 及更高的 17 版本 
+  版本 16.1 及更高的 16 版本 
+  版本 15.2 及更高的 15 版本 
+  版本 14.5 及更高的 14 版本 
+  版本 13.12 及更高的 13 版本 

可信语言扩展开发环境和运行时打包为 `pg_tle` PostgreSQL 扩展，版本 1.0.1。它支持在 JavaScript、Perl、Tcl、PL/pgSQL 和 SQL 中创建扩展。您可以在 RDS for PostgreSQL 数据库实例中安装 `pg_tle` 扩展，方式与安装其他 PostgreSQL 扩展一样。设置 `pg_tle` 后，开发人员可以使用它来创建新的 PostgreSQL 扩展，称为 *TLE 扩展*。

 

在以下主题中，您可以了解有关如何设置可信语言扩展以及如何开始创建自己的 TLE 扩展的信息。

**Topics**
+ [术语](PostgreSQL_trusted_language_extension-terminology.md)
+ [使用适用于 PostgreSQL 的可信语言扩展的要求](PostgreSQL_trusted_language_extension-requirements.md)
+ [在 RDS for PostgreSQL 数据库实例中设置可信语言扩展](PostgreSQL_trusted_language_extension-setting-up.md)
+ [适用于 PostgreSQL 的可信语言扩展概述](PostgreSQL_trusted_language_extension.overview.md)
+ [为 RDS for PostgreSQL 创建 TLE 扩展](PostgreSQL_trusted_language_extension-creating-TLE-extensions.md)
+ [从数据库中删除 TLE 扩展](PostgreSQL_trusted_language_extension-creating-TLE-extensions.dropping-TLEs.md)
+ [卸载适用于 PostgreSQL 的可信语言扩展](PostgreSQL_trusted_language_extension-uninstalling-pg_tle-devkit.md)
+ [在您的 TLE 扩展中使用 PostgreSQL 挂钩](PostgreSQL_trusted_language_extension.overview.tles-and-hooks.md)
+ [在 TLE 中使用自定义数据类型](PostgreSQL_trusted_language_extension-custom-data-type.md)
+ [适用于 PostgreSQL 的可信语言扩展的函数参考](PostgreSQL_trusted_language_extension-functions-reference.md)
+ [适用于 PostgreSQL 的可信语言扩展的挂钩参考](PostgreSQL_trusted_language_extension-hooks-reference.md)

# 术语
<a name="PostgreSQL_trusted_language_extension-terminology"></a>

为了帮助您更好地了解可信语言扩展，请查看以下词汇表，了解本主题中使用的术语。

**适用于 PostgreSQL 的可信语言扩展**  
*适用于 PostgreSQL 的可信语言扩展*是打包为 `pg_tle` 扩展的开源开发套件的正式名称。它可以在任何 PostgreSQL 系统上使用。有关更多信息，请参阅 GitHub 上的 [aws/pg\$1tle](https://github.com/aws/pg_tle)。

**可信语言扩展**  
*可信语言扩展*是适用于 PostgreSQL 的可信语言扩展的简称。本文档中也使用了这个缩写名称及其缩写（TLE）。

**可信语言**  
*可信语言*是一种具有特定安全属性的编程或脚本语言。例如，可信语言通常限制对文件系统的访问，并限制对指定网络属性的使用。TLE 开发套件旨在支持可信语言。PostgreSQL 支持几种不同的用于创建可信扩展或不可信扩展的语言。有关示例，请参阅 PostgreSQL 文档中的[可信和不可信 PL/Perl](https://www.postgresql.org/docs/current/plperl-trusted.html)。当您使用可信语言扩展创建扩展时，该扩展本质上使用可信语言机制。

**TLE 扩展**  
*TLE 扩展*是使用可信语言扩展（TLE）开发套件创建的 PostgreSQL 扩展。

# 使用适用于 PostgreSQL 的可信语言扩展的要求
<a name="PostgreSQL_trusted_language_extension-requirements"></a>

以下是设置和使用 TLE 开发套件的要求。
+ ** RDS for PostgreSQL 版本** – 仅在 RDS for PostgreSQL 版本 13.12 及更高的 13 版本、14.5 及更高的 14 版本，以及 15.2 及更高的版本上支持可信语言扩展。
  + 如果您需要升级 RDS for PostgreSQL 实例，请参阅[升级 RDS for PostgreSQL 数据库引擎](USER_UpgradeDBInstance.PostgreSQL.md)。
  + 如果您还没有运行 PostgreSQL 的 Amazon RDS 数据库实例，则可以创建一个。有关更多信息，请参阅 RDS for PostgreSQL 数据库实例，请参阅 [创建 PostgreSQL 数据库实例并连接到该实例](CHAP_GettingStarted.CreatingConnecting.PostgreSQL.md)。
+ **需要 `rds_superuser` 权限** - 要设置和配置 `pg_tle` 扩展，您的数据库用户角色必须具有 `rds_superuser` 角色的权限。默认情况下，此角色被授予 `postgres` 用户，此用户创建 RDS for PostgreSQL 数据库实例。
+ **需要自定义数据库参数组** – 您的 RDS for PostgreSQL 数据库实例必须使用自定义数据库参数组进行配置。
  + 如果未使用自定义数据库参数组配置您的 RDS for PostgreSQL 数据库实例，则应创建一个参数组并将其与 RDS for PostgreSQL 数据库实例相关联。有关步骤的简短摘要，请参阅 [创建和应用自定义数据库参数组](#PostgreSQL_trusted_language_extension-requirements-create-custom-params)。
  + 如果已经使用自定义数据库参数组配置了 RDS for PostgreSQL 数据库实例，则可以设置可信语言扩展。有关更多信息，请参阅 [在 RDS for PostgreSQL 数据库实例中设置可信语言扩展](PostgreSQL_trusted_language_extension-setting-up.md)。

## 创建和应用自定义数据库参数组
<a name="PostgreSQL_trusted_language_extension-requirements-create-custom-params"></a>

使用以下步骤创建自定义数据库参数组，并将 RDS for PostgreSQL 数据库实例配置为使用该参数组。

### 控制台
<a name="PostgreSQL_trusted_language_extension-requirements-custom-parameters.CON"></a>

**创建自定义数据库参数组并将其与您的 RDS for PostgreSQL 数据库实例一起使用**

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

1. 从 Amazon RDS 菜单中选择 Parameter groups（参数组）。

1. 选择**创建参数组**。

1. 在 **Parameter group details**（参数组详细信息）页面中，输入以下信息。
   + 对于**Parameter group family**（参数组系列），选择 postgres14。
   + 对于 **Type**（类型），请选择 DB Parameter Group（数据库参数组）。
   + 对于 **Group name**（组名称），在操作上下文中为参数组指定一个有意义的名称。
   + 对于 **Description**（描述），输入有用的描述，以便团队中的其他人可以轻松找到它。

1. 选择**创建**。您的自定义数据库参数组是在您的 AWS 区域中创建的。现在，您可以按照以下步骤修改 RDS for PostgreSQL 数据库实例以使用它。

1. 从 Amazon RDS 菜单中选择 **Databases**（数据库）。

1. 从列出的列表中选择要与 TLE 结合使用的 RDS for PostgreSQL 数据库实例，然后选择 **Modify**（修改）。

1. 在 Modify DB instance settings（修改数据库实例设置）页面中，在 Additional configuration（其他配置）部分中找到 **Database options**（数据库选项），并从选择器中选择您的自定义数据库参数组。

1. 选择 **Continue**（继续）以保存更改。

1. 选择 **Apply immediately**（立即应用），这样您就可以继续将 RDS for PostgreSQL 数据库实例设置为使用 TLE。

要继续为系统设置可信语言扩展，请参阅 [在 RDS for PostgreSQL 数据库实例中设置可信语言扩展](PostgreSQL_trusted_language_extension-setting-up.md)。

有关使用数据库参数组的更多信息，请参阅 [Amazon RDS 数据库实例的数据库参数组](USER_WorkingWithDBInstanceParamGroups.md)。

### AWS CLI
<a name="PostgreSQL_trusted_language_extension-requirements-custom-parameters-CLI"></a>

在使用 CLI 命令时，您可以通过将您的 AWS CLI 配置为使用默认 AWS 区域来避免指定 `--region` 参数。有关更多信息，请参阅《AWS Command Line Interface 用户指南》**中的[配置基础知识](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。

**创建自定义数据库参数组并将其与您的 RDS for PostgreSQL 数据库实例一起使用**

1. 使用 [create-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-parameter-group.html) AWS CLI 命令为您的 AWS 区域创建一个基于 postgres14 的自定义数据库参数组。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds create-db-parameter-group \
     --region aws-region \
     --db-parameter-group-name custom-params-for-pg-tle \
     --db-parameter-group-family postgres14 \
     --description "My custom DB parameter group for Trusted Language Extensions"
   ```

   对于：Windows

   ```
   aws rds create-db-parameter-group ^
     --region aws-region ^
     --db-parameter-group-name custom-params-for-pg-tle ^
     --db-parameter-group-family postgres14 ^
     --description "My custom DB parameter group for Trusted Language Extensions"
   ```

   您的自定义数据库参数组在 AWS 区域中可用，因此您可以修改 RDS for PostgreSQL 数据库实例以使用它。

1. 使用 [modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) AWS CLI 命令将自定义数据库参数组应用于 RDS for PostgreSQL 数据库实例。此命令立即重启活动实例。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds modify-db-instance \
     --region aws-region \
     --db-instance-identifier your-instance-name \
     --db-parameter-group-name custom-params-for-pg-tle \
     --apply-immediately
   ```

   对于：Windows

   ```
   aws rds modify-db-instance ^
     --region aws-region ^
     --db-instance-identifier your-instance-name ^
     --db-parameter-group-name custom-params-for-pg-tle ^
     --apply-immediately
   ```

要继续为系统设置可信语言扩展，请参阅 [在 RDS for PostgreSQL 数据库实例中设置可信语言扩展](PostgreSQL_trusted_language_extension-setting-up.md)。

有关更多信息，请参阅 。[Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)

# 在 RDS for PostgreSQL 数据库实例中设置可信语言扩展
<a name="PostgreSQL_trusted_language_extension-setting-up"></a>

以下步骤假设您的 RDS for PostgreSQL 数据库实例与自定义数据库参数组相关联。您可以使用 AWS 管理控制台或 AWS CLI 来执行这些步骤。

当您在 RDS for PostgreSQL 数据库实例中设置可信语言扩展时，您可以将其安装在特定的数据库中，供对该数据库拥有权限的数据库用户使用。

## 控制台
<a name="PostgreSQL_trusted_language_extension-setting-up.CON"></a>

**设置可信语言扩展**

使用作为 `rds_superuser` 组（角色）成员的账户执行以下步骤。

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

1. 在导航窗格中，选择 RDS for PostgreSQL 数据库实例。

1. 打开 的**配置**选项卡。RDS for PostgreSQL 数据库实例的 Configuration（配置）选项卡。在实例详细信息中，找到 **Parameter group**（参数组）链接。

1. 选择此链接以打开与您的 RDS for PostgreSQL 数据库实例关联的自定义参数。

1. 在 **Parameters**（参数）搜索字段中，键入 `shared_pre` 以查找 `shared_preload_libraries` 参数。

1. 选择 **Edit parameters**（编辑参数）以访问属性值。

1. 将 `pg_tle` 添加到 **Values**（值）字段的列表中。使用逗号分隔值列表中的项目。  
![\[添加了 pg_tle 的 shared_preload_libraries 参数的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pg_tle.png)

1. 重启 RDS for PostgreSQL 数据库实例，以使对 `shared_preload_libraries` 参数的更改生效。

1. 当实例可用时，验证 `pg_tle` 是否已初始化。使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，然后运行以下命令。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pg_tle
   (1 row)
   ```

1. 初始化 `pg_tle` 扩展后，您现在可以创建此扩展了。

   ```
   CREATE EXTENSION pg_tle;
   ```

   可以使用以下 `psql` 元命令验证扩展是否已安装。

   ```
   labdb=> \dx
                            List of installed extensions
     Name   | Version |   Schema   |                Description
   ---------+---------+------------+--------------------------------------------
    pg_tle  | 1.0.1   | pgtle      | Trusted-Language Extensions for PostgreSQL
    plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
   ```

1. 在设置 RDS for PostgreSQL 数据库实例时，将 `pgtle_admin` 角色授予为其创建的主用户名。如果您接受了默认值，则它就是 `postgres`。

   ```
   labdb=> GRANT pgtle_admin TO postgres;
   GRANT ROLE
   ```

   您可以使用 `psql` 元命令来验证授权是否已完成，如以下示例中所示。输出中仅显示 `pgtle_admin` 和 `postgres` 角色。有关更多信息，请参阅[了解 rds\$1superuser 角色](Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser.md)。

   ```
   labdb=> \du
                             List of roles
       Role name    |           Attributes            |               Member of
   -----------------+---------------------------------+-----------------------------------
   pgtle_admin     | Cannot login                     | {}
   postgres        | Create role, Create DB          +| {rds_superuser,pgtle_admin}
                   | Password valid until infinity    |...
   ```

1. 使用 `\q` 元命令关闭 `psql` 会话。

   ```
   \q
   ```

要开始创建 TLE 扩展，请参阅 [示例：使用 SQL 创建可信语言扩展](PostgreSQL_trusted_language_extension-creating-TLE-extensions.md#PostgreSQL_trusted_language_extension-simple-example)。

## AWS CLI
<a name="PostgreSQL_trusted_language_extension-setting-up-CLI"></a>

在使用 CLI 命令时，您可以通过将您的 AWS CLI 配置为使用默认 AWS 区域来避免指定 `--region` 参数。有关更多信息，请参阅《AWS Command Line Interface 用户指南》**中的[配置基础知识](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。

**设置可信语言扩展**

1. 使用 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) AWS CLI 命令将 `pg_tle` 添加到 `shared_preload_libraries` 参数。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=pg_tle,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用 [reboot-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/reboot-db-instance) AWS CLI 命令重启 RDS for PostgreSQL 数据库实例并初始化 `pg_tle` 库。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 当实例可用时，您可以验证 `pg_tle` 是否已初始化。使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，然后运行以下命令。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pg_tle
   (1 row)
   ```

   初始化 `pg_tle` 后，您现在可以创建扩展了。

   ```
   CREATE EXTENSION pg_tle;
   ```

1. 在设置 RDS for PostgreSQL 数据库实例时，将 `pgtle_admin` 角色授予为其创建的主用户名。如果您接受了默认值，则它就是 `postgres`。

   ```
   GRANT pgtle_admin TO postgres;
   GRANT ROLE
   ```

1. 按如下方式关闭 `psql` 会话。

   ```
   labdb=> \q
   ```

要开始创建 TLE 扩展，请参阅 [示例：使用 SQL 创建可信语言扩展](PostgreSQL_trusted_language_extension-creating-TLE-extensions.md#PostgreSQL_trusted_language_extension-simple-example)。

# 适用于 PostgreSQL 的可信语言扩展概述
<a name="PostgreSQL_trusted_language_extension.overview"></a>

适用于 PostgreSQL 的可信语言扩展是一个 PostgreSQL 扩展，您可以像设置其他 PostgreSQL 扩展一样，将其安装在 RDS for PostgreSQL 数据库实例中。在下图的 pgAdmin 客户端工具的示例数据库中，您可以查看构成 `pg_tle` 扩展的部分组件。

![\[该图显示了构成 TLE 开发套件的部分组件。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/apg-pg_tle-installed-view-in-pgAdmin.png)


您可以查看以下详细信息。

1. 适用于 PostgreSQL 的可信语言扩展（TLE）开发套件打包为 `pg_tle` 扩展。因此，`pg_tle` 添加到安装它的数据库的可用扩展中。

1. TLE 有它自己的模式，即 `pgtle`。此模式包含辅助函数（3 个），用于安装和管理您创建的扩展。

1. TLE 提供了十多个辅助函数，用于安装、注册和管理您的扩展。要了解有关这些函数的更多信息，请参阅 [适用于 PostgreSQL 的可信语言扩展的函数参考](PostgreSQL_trusted_language_extension-functions-reference.md)。

`pg_tle` 扩展的其他组件包含以下各项：
+ **`pgtle_admin` 角色** – `pgtle_admin` 角色是在安装 `pg_tle` 扩展时创建的。此角色获得了相关权限，应视为具有此类权限。我们强烈建议您在向数据库用户授予 `pgtle_admin` 角色时遵循*最低权限*原则。换句话说，仅向允许创建、安装和管理新 TLE 扩展（例如 `postgres`）的数据库用户授予 `pgtle_admin` 角色。
+ **`pgtle.feature_info` 表** – `pgtle.feature_info` 表是一个受保护的表，其中包含有关您的 TLE、挂钩及其使用的自定义存储过程和函数的信息。如果您有 `pgtle_admin` 权限，则可以使用以下可信语言扩展函数在表中添加和更新该信息。
  + [pgtle.register\$1feature](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.register_feature)
  + [pgtle.register\$1feature\$1if\$1not\$1exists](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.register_feature_if_not_exists)
  + [pgtle.unregister\$1feature](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.unregister_feature)
  + [pgtle.unregister\$1feature\$1if\$1exists](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.unregister_feature_if_exists)

# 为 RDS for PostgreSQL 创建 TLE 扩展
<a name="PostgreSQL_trusted_language_extension-creating-TLE-extensions"></a>

您可以将使用 TLE 创建的任何扩展安装在安装了 `pg_tle` 扩展的任何 RDS for PostgreSQL 数据库实例中。`pg_tle` 扩展的范围限于安装该扩展的 PostgreSQL 数据库。使用 TLE 创建的扩展的范围限于同一个数据库。

使用各种 `pgtle` 函数安装构成 TLE 扩展的代码。以下可信语言扩展函数全部需要 `pgtle_admin` 角色。
+ [pgtle.install\$1extension](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.install_extension)
+ [pgtle.install\$1update\$1path](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.install_update_path)
+ [pgtle.register\$1feature](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.register_feature)
+ [pgtle.register\$1feature\$1if\$1not\$1exists](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.register_feature_if_not_exists)
+ [pgtle.set\$1default\$1version](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.set_default_version)
+ [pgtle.uninstall\$1extension(name)](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.uninstall_extension-name)
+ [pgtle.uninstall\$1extension(name, version)](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.uninstall_extension-name-version)
+ [pgtle.uninstall\$1extension\$1if\$1exists](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.uninstall_extension_if_exists)
+ [pgtle.uninstall\$1update\$1path](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.uninstall_update_path)
+ [pgtle.uninstall\$1update\$1path\$1if\$1exists](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.uninstall_update_path_if_exists)
+ [pgtle.unregister\$1feature](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.unregister_feature)
+ [pgtle.unregister\$1feature\$1if\$1exists](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.unregister_feature_if_exists)

## 示例：使用 SQL 创建可信语言扩展
<a name="PostgreSQL_trusted_language_extension-simple-example"></a>

以下示例说明如何创建名为 `pg_distance` 的 TLE 扩展，该扩展包含一些 SQL 函数，用于使用不同的公式计算距离。在列表中，您可以找到用于计算曼哈顿距离的函数和用于计算欧几里得距离的函数。有关这些公式之间差异的更多信息，请参阅维基百科中的 [Taxicab 几何](https://en.wikipedia.org/wiki/Taxicab_geometry)和[欧几里得几何](https://en.wikipedia.org/wiki/Euclidean_geometry)。

如果您按照[在 RDS for PostgreSQL 数据库实例中设置可信语言扩展](PostgreSQL_trusted_language_extension-setting-up.md)中详述设置了 `pg_tle` 扩展，则可以在自己的 RDS for PostgreSQL 数据库实例中使用此示例。

**注意**  
您需要拥有 `pgtle_admin` 角色的权限才能执行此过程。

**创建示例 TLE 扩展**

以下步骤使用名为 `labdb` 的示例数据库。该数据库归 `postgres` 主用户所有。`postgres` 角色还具有 `pgtle_admin` 角色的权限。

1. 使用 `psql` 连接到 RDS for PostgreSQL 数据库实例。

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

1. 通过复制以下代码并将其粘贴到 `psql` 会话控制台中来创建名为 `pg_distance` 的 TLE 扩展。

   ```
   SELECT pgtle.install_extension
   (
    'pg_distance',
    '0.1',
     'Distance functions for two points',
   $_pg_tle_$
       CREATE FUNCTION dist(x1 float8, y1 float8, x2 float8, y2 float8, norm int)
       RETURNS float8
       AS $$
         SELECT (abs(x2 - x1) ^ norm + abs(y2 - y1) ^ norm) ^ (1::float8 / norm);
       $$ LANGUAGE SQL;
   
       CREATE FUNCTION manhattan_dist(x1 float8, y1 float8, x2 float8, y2 float8)
       RETURNS float8
       AS $$
         SELECT dist(x1, y1, x2, y2, 1);
       $$ LANGUAGE SQL;
   
       CREATE FUNCTION euclidean_dist(x1 float8, y1 float8, x2 float8, y2 float8)
       RETURNS float8
       AS $$
         SELECT dist(x1, y1, x2, y2, 2);
       $$ LANGUAGE SQL;
   $_pg_tle_$
   );
   ```

   您将看到如下输出。

   ```
   install_extension
   ---------------
    t
   (1 row)
   ```

   构成 `pg_distance` 扩展的构件现在已安装在您的数据库中。这些构件包括扩展的控制文件和代码，这些项目需要存在，这样才能使用 `CREATE EXTENSION` 命令创建扩展。换句话说，您仍然需要创建扩展以使其函数可供数据库用户使用。

1. 要创建扩展，请像使用任何其他扩展一样使用 `CREATE EXTENSION` 命令。与其他扩展一样，数据库用户需要在数据库中拥有 `CREATE` 权限。

   ```
   CREATE EXTENSION pg_distance;
   ```

1. 要测试 `pg_distance` TLE 扩展，可以使用它来计算四个点之间的[曼哈顿距离](https://en.wikipedia.org/wiki/Taxicab_geometry)。

   ```
   labdb=> SELECT manhattan_dist(1, 1, 5, 5);
   8
   ```

   要计算同一组点之间的[欧几里得距离](https://en.wikipedia.org/wiki/Euclidean_geometry)，可以使用以下方法。

   ```
   labdb=> SELECT euclidean_dist(1, 1, 5, 5);
   5.656854249492381
   ```

`pg_distance` 扩展将函数加载到数据库中，并使对数据库具有权限的任何用户都可以使用它们。

## 修改您的 TLE 扩展
<a name="PostgreSQL_trusted_language_extension-simple-example.modify"></a>

要提高此 TLE 扩展中打包的函数的查询性能，请在其规范中添加以下两个 PostgreSQL 属性。
+ `IMMUTABLE` – `IMMUTABLE` 属性可确保查询优化程序可以使用优化措施来缩短查询响应时间。有关更多信息，请参阅 PostgreSQL 文档中的[函数波动性类别](https://www.postgresql.org/docs/current/xfunc-volatility.html)。
+ `PARALLEL SAFE` – `PARALLEL SAFE` 属性是允许 PostgreSQL 在并行模式下运行该函数的另一个属性。有关更多信息，请参阅 PostgreSQL 文档中的 [CREATE FUNCTION](https://www.postgresql.org/docs/current/sql-createfunction.html)。

在以下示例中，您可以看到如何使用 `pgtle.install_update_path` 函数向每个函数添加这些属性，以创建 `pg_distance` TLE 扩展的版本 `0.2`。有关此函数的更多信息，请参阅 [pgtle.install\$1update\$1path](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.install_update_path)。您需要拥有 `pgtle_admin` 角色才能执行此任务。

**更新现有 TLE 扩展并指定默认版本**

1. 使用 `psql` 或其他客户端工具（例如 pgAdmin）连接到 RDS for PostgreSQL 数据库实例。

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

1. 通过复制以下代码并将其粘贴到 `psql` 会话控制台中来修改现有 TLE 扩展。

   ```
   SELECT pgtle.install_update_path
   (
    'pg_distance',
    '0.1',
    '0.2',
   $_pg_tle_$
       CREATE OR REPLACE FUNCTION dist(x1 float8, y1 float8, x2 float8, y2 float8, norm int)
       RETURNS float8
       AS $$
         SELECT (abs(x2 - x1) ^ norm + abs(y2 - y1) ^ norm) ^ (1::float8 / norm);
       $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
   
       CREATE OR REPLACE FUNCTION manhattan_dist(x1 float8, y1 float8, x2 float8, y2 float8)
       RETURNS float8
       AS $$
         SELECT dist(x1, y1, x2, y2, 1);
       $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
   
       CREATE OR REPLACE FUNCTION euclidean_dist(x1 float8, y1 float8, x2 float8, y2 float8)
       RETURNS float8
       AS $$
         SELECT dist(x1, y1, x2, y2, 2);
       $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
   $_pg_tle_$
   );
   ```

   您看到的响应与以下内容类似。

   ```
   install_update_path
   ---------------------
    t
   (1 row)
   ```

   您可以将此版本的扩展设置为默认版本，这样，数据库用户在其数据库中创建或更新扩展时就不必指定版本。

1. 要将 TLE 扩展的修改版本（版本 0.2）指定为默认版本，请使用以下示例所示的 `pgtle.set_default_version` 函数。

   ```
   SELECT pgtle.set_default_version('pg_distance', '0.2');
   ```

   有关此函数的更多信息，请参阅 [pgtle.set\$1default\$1version](PostgreSQL_trusted_language_extension-functions-reference.md#pgtle.set_default_version)。

1. 代码准备就绪后，您可以使用 `ALTER EXTENSION ... UPDATE` 命令以常规方式更新已安装的 TLE 扩展，如此处所示：

   ```
   ALTER EXTENSION pg_distance UPDATE;
   ```

# 从数据库中删除 TLE 扩展
<a name="PostgreSQL_trusted_language_extension-creating-TLE-extensions.dropping-TLEs"></a>

您可以使用 `DROP EXTENSION` 命令删除 TLE 扩展，方法与处理其他 PostgreSQL 扩展的方法相同。删除扩展并不会删除构成扩展的安装文件，这允许用户重新创建扩展。要删除扩展及其安装文件，请执行以下两步过程。

**删除 TLE 扩展并删除其安装文件**

1. 使用 `psql` 或其他客户端工具连接到 RDS for PostgreSQL 数据库实例。

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

1. 像删除任何 PostgreSQL 扩展一样删除此扩展。

   ```
   DROP EXTENSION your-TLE-extension
   ```

   例如，如果您按照[示例：使用 SQL 创建可信语言扩展](PostgreSQL_trusted_language_extension-creating-TLE-extensions.md#PostgreSQL_trusted_language_extension-simple-example)中的详细说明创建 `pg_distance` 扩展，则可以按如下方式删除此扩展。

   ```
   DROP EXTENSION pg_distance;
   ```

   您将看到确认扩展已删除的输出，如下所示。

   ```
   DROP EXTENSION
   ```

   此时，该扩展在数据库中不再处于活动状态。但是，它的安装文件和控制文件在数据库中仍然可用，因此数据库用户可以根据需要再次创建扩展。
   + 如果您想让扩展文件保持完好，以便数据库用户可以创建您的 TLE 扩展，则可以在此处停止。
   + 如果要删除构成扩展的所有文件，请继续执行下一步。

1. 要删除扩展的所有安装文件，请使用 `pgtle.uninstall_extension` 函数。此函数删除扩展的所有代码和控制文件。

   ```
   SELECT pgtle.uninstall_extension('your-tle-extension-name');
   ```

   例如，要删除所有 `pg_distance` 安装文件，请使用以下命令。

   ```
   SELECT pgtle.uninstall_extension('pg_distance');
    uninstall_extension
   ---------------------
    t
   (1 row)
   ```

# 卸载适用于 PostgreSQL 的可信语言扩展
<a name="PostgreSQL_trusted_language_extension-uninstalling-pg_tle-devkit"></a>

如果您不想再使用 TLE 创建自己的 TLE 扩展，则可以删除 `pg_tle` 扩展并删除所有构件。此操作包括删除数据库中的所有 TLE 扩展和删除 `pgtle` 模式。

**从数据库中删除 `pg_tle` 扩展及其模式**

1. 使用 `psql` 或其他客户端工具连接到 RDS for PostgreSQL 数据库实例。

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

1. 从数据库中删除 `pg_tle` 扩展。如果数据库中仍在运行您自己的 TLE 扩展，则还需要删除这些扩展。为此，您可以使用 `CASCADE` 关键字，如以下所示。

   ```
   DROP EXTENSION pg_tle CASCADE;
   ```

   如果 `pg_tle` 扩展在数据库中仍未处于活动状态，则无需使用 `CASCADE` 关键字。

1. 删除 `pgtle` 模式。此操作将从数据库中删除所有管理函数。

   ```
   DROP SCHEMA pgtle CASCADE;
   ```

   该过程完成后，该命令将返回以下内容。

   ```
   DROP SCHEMA
   ```

   `pg_tle` 扩展、其模式和函数以及所有构件均已删除。要使用 TLE 创建新扩展，请再次完成设置过程。有关更多信息，请参阅 [在 RDS for PostgreSQL 数据库实例中设置可信语言扩展](PostgreSQL_trusted_language_extension-setting-up.md)。

# 在您的 TLE 扩展中使用 PostgreSQL 挂钩
<a name="PostgreSQL_trusted_language_extension.overview.tles-and-hooks"></a>

*挂钩*是 PostgreSQL 中可用的一种回调机制，它允许开发人员在常规数据库操作期间调用自定义函数或其他例程。TLE 开发套件支持 PostgreSQL 挂钩，因此您可以在运行时将自定义函数与 PostgreSQL 行为集成在一起。例如，您可以使用挂钩将身份验证过程与您自己的自定义代码关联起来，或者根据您的特定需求修改查询规划和执行流程。

您的 TLE 扩展可以使用挂钩。如果挂钩在作用域方面是全局的，则它适用于所有数据库。因此，如果您的 TLE 扩展使用全局挂钩，则需要在用户可以访问的所有数据库中创建 TLE 扩展。

当您使用 `pg_tle` 扩展构建自己的可信语言扩展时，您可以使用 SQL API 中的可用挂钩来构建扩展的功能。您应该向 `pg_tle` 注册任何挂钩。对于某些挂钩，您可能还需要设置各种配置参数。例如，可以将 `passcode` 检查挂钩设置为 on、off 或 require。有关可用 `pg_tle` 挂钩的特定要求的更多信息，请参阅 [适用于 PostgreSQL 的可信语言扩展的挂钩参考](PostgreSQL_trusted_language_extension-hooks-reference.md)。

## 示例：创建使用 PostgreSQL 挂钩的扩展
<a name="PostgreSQL_trusted_language_extension-example-hook"></a>

本节讨论的示例使用 PostgreSQL 挂钩检查在特定 SQL 操作期间提供的密码，并防止数据库用户将其密码设置为 `password_check.bad_passwords` 表中包含的任何密码。该表包含十大最常用但易于破解的密码选择。

要在 RDS for PostgreSQL 数据库实例中设置此示例，您必须已经安装了可信语言扩展。有关更多信息，请参阅 [在 RDS for PostgreSQL 数据库实例中设置可信语言扩展](PostgreSQL_trusted_language_extension-setting-up.md)。

**设置密码检查挂钩示例**

1. 使用 `psql` 连接到 RDS for PostgreSQL 数据库实例。

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

1. 从[密码检查挂钩代码列表](#PostgreSQL_trusted_language_extension-example-hook_code_listing)中复制代码并将其粘贴到数据库中。

   ```
   SELECT pgtle.install_extension (
     'my_password_check_rules',
     '1.0',
     'Do not let users use the 10 most commonly used passwords',
   $_pgtle_$
     CREATE SCHEMA password_check;
     REVOKE ALL ON SCHEMA password_check FROM PUBLIC;
     GRANT USAGE ON SCHEMA password_check TO PUBLIC;
   
     CREATE TABLE password_check.bad_passwords (plaintext) AS
     VALUES
       ('123456'),
       ('password'),
       ('12345678'),
       ('qwerty'),
       ('123456789'),
       ('12345'),
       ('1234'),
       ('111111'),
       ('1234567'),
       ('dragon');
     CREATE UNIQUE INDEX ON password_check.bad_passwords (plaintext);
   
     CREATE FUNCTION password_check.passcheck_hook(username text, password text, password_type pgtle.password_types, valid_until timestamptz, valid_null boolean)
     RETURNS void AS $$
       DECLARE
         invalid bool := false;
       BEGIN
         IF password_type = 'PASSWORD_TYPE_MD5' THEN
           SELECT EXISTS(
             SELECT 1
             FROM password_check.bad_passwords bp
             WHERE ('md5' || md5(bp.plaintext || username)) = password
           ) INTO invalid;
           IF invalid THEN
             RAISE EXCEPTION 'Cannot use passwords from the common password dictionary';
           END IF;
         ELSIF password_type = 'PASSWORD_TYPE_PLAINTEXT' THEN
           SELECT EXISTS(
             SELECT 1
             FROM password_check.bad_passwords bp
             WHERE bp.plaintext = password
           ) INTO invalid;
           IF invalid THEN
             RAISE EXCEPTION 'Cannot use passwords from the common password dictionary';
           END IF;
         END IF;
       END
     $$ LANGUAGE plpgsql SECURITY DEFINER;
   
     GRANT EXECUTE ON FUNCTION password_check.passcheck_hook TO PUBLIC;
   
     SELECT pgtle.register_feature('password_check.passcheck_hook', 'passcheck');
   $_pgtle_$
   );
   ```

   将扩展加载到数据库后，您会看到如下输出。

   ```
    install_extension
   -------------------
    t
   (1 row)
   ```

1. 当仍然连接到数据库时，现在可以创建扩展了。

   ```
   CREATE EXTENSION my_password_check_rules;
   ```

1. 您可以使用以下 `psql` 元命令确认已在数据库中创建扩展。

   ```
   \dx
                           List of installed extensions
             Name           | Version |   Schema   |                         Description
   -------------------------+---------+------------+-------------------------------------------------------------
    my_password_check_rules | 1.0     | public     | Prevent use of any of the top-ten most common bad passwords
    pg_tle                  | 1.0.1   | pgtle      | Trusted-Language Extensions for PostgreSQL
    plpgsql                 | 1.0     | pg_catalog | PL/pgSQL procedural language
   (3 rows)
   ```

1. 打开另一个终端会话来使用 AWS CLI。您需要修改您的自定义数据库参数组才能开启密码检查挂钩。为此，请使用 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) CLI 命令，如以下示例中所示。

   ```
   aws rds modify-db-parameter-group \
       --region aws-region \
       --db-parameter-group-name your-custom-parameter-group \
       --parameters "ParameterName=pgtle.enable_password_check,ParameterValue=on,ApplyMethod=immediate"
   ```

   成功开启此参数后，您将看到如下输出。

   ```
   (
       "DBParameterGroupName": "docs-lab-parameters-for-tle"
   }
   ```

   对参数组设置进行的更改可能需要几分钟才能生效。但是，此参数是动态的，因此您无需重新启动 RDS for PostgreSQL 数据库实例，即可使该设置生效。

1. 打开 `psql` 会话并查询数据库，以验证密码检查挂钩已开启。

   ```
   labdb=> SHOW pgtle.enable_password_check;
   pgtle.enable_password_check
   -----------------------------
   on
   (1 row)
   ```

密码检查挂钩现处于活动状态。您可以通过创建新角色并使用其中一个错误密码来对其进行测试，如以下示例中所示。

```
CREATE ROLE test_role PASSWORD 'password';
ERROR:  Cannot use passwords from the common password dictionary
CONTEXT:  PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 21 at RAISE
SQL statement "SELECT password_check.passcheck_hook(
    $1::pg_catalog.text, 
    $2::pg_catalog.text, 
    $3::pgtle.password_types, 
    $4::pg_catalog.timestamptz, 
    $5::pg_catalog.bool)"
```

对输出设置了格式以便于阅读。

以下示例显示，`pgsql` 交互式元命令 `\password` 行为也受到密码检查挂钩的影响。

```
postgres=> SET password_encryption TO 'md5';
SET
postgres=> \password
Enter new password for user "postgres":*****
Enter it again:*****
ERROR:  Cannot use passwords from the common password dictionary
CONTEXT:  PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 12 at RAISE
SQL statement "SELECT password_check.passcheck_hook($1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"
```

如果需要，可以删除此 TLE 扩展并卸载其源文件。有关更多信息，请参阅 [从数据库中删除 TLE 扩展从数据库中删除 TLE 扩展](PostgreSQL_trusted_language_extension-creating-TLE-extensions.dropping-TLEs.md)。

### 密码检查挂钩代码列表
<a name="PostgreSQL_trusted_language_extension-example-hook_code_listing"></a>

此处显示的示例代码定义了 `my_password_check_rules` TLE 扩展的规范。当您复制此代码并将其粘贴到数据库中时，`my_password_check_rules` 扩展的代码将加载到数据库中，并注册 `password_check` 挂钩以供扩展使用。

```
SELECT pgtle.install_extension (
  'my_password_check_rules',
  '1.0',
  'Do not let users use the 10 most commonly used passwords',
$_pgtle_$
  CREATE SCHEMA password_check;
  REVOKE ALL ON SCHEMA password_check FROM PUBLIC;
  GRANT USAGE ON SCHEMA password_check TO PUBLIC;

  CREATE TABLE password_check.bad_passwords (plaintext) AS
  VALUES
    ('123456'),
    ('password'),
    ('12345678'),
    ('qwerty'),
    ('123456789'),
    ('12345'),
    ('1234'),
    ('111111'),
    ('1234567'),
    ('dragon');
  CREATE UNIQUE INDEX ON password_check.bad_passwords (plaintext);

  CREATE FUNCTION password_check.passcheck_hook(username text, password text, password_type pgtle.password_types, valid_until timestamptz, valid_null boolean)
  RETURNS void AS $$
    DECLARE
      invalid bool := false;
    BEGIN
      IF password_type = 'PASSWORD_TYPE_MD5' THEN
        SELECT EXISTS(
          SELECT 1
          FROM password_check.bad_passwords bp
          WHERE ('md5' || md5(bp.plaintext || username)) = password
        ) INTO invalid;
        IF invalid THEN
          RAISE EXCEPTION 'Cannot use passwords from the common password dictionary';
        END IF;
      ELSIF password_type = 'PASSWORD_TYPE_PLAINTEXT' THEN
        SELECT EXISTS(
          SELECT 1
          FROM password_check.bad_passwords bp
          WHERE bp.plaintext = password
        ) INTO invalid;
        IF invalid THEN
          RAISE EXCEPTION 'Cannot use passwords from the common password dictionary';
        END IF;
      END IF;
    END
  $$ LANGUAGE plpgsql SECURITY DEFINER;

  GRANT EXECUTE ON FUNCTION password_check.passcheck_hook TO PUBLIC;

  SELECT pgtle.register_feature('password_check.passcheck_hook', 'passcheck');
$_pgtle_$
);
```

# 在 TLE 中使用自定义数据类型
<a name="PostgreSQL_trusted_language_extension-custom-data-type"></a>

PostgreSQL 支持注册新的基本类型（也称为标量类型）的命令，以便高效地处理数据库中的复杂数据结构。基本类型允许您自定义在内部存储数据的方式，以及如何将其与外部文本表示形式相互转换。在扩展 PostgreSQL 以支持功能域时，这些自定义数据类型非常有用，在这种情况下，诸如数字或文本之类的内置类型无法提供足够的搜索语义。

RDS for PostgreSQL 允许您在可信语言扩展中创建自定义数据类型，并为这些新的数据类型定义支持 SQL 和索引操作的函数。自定义数据类型适用于以下版本：
+ RDS for PostgreSQL 15.4 和更高的 15 版本
+ RDS for PostgreSQL 14.9 和更高的 14 版本
+ RDS for PostgreSQL 13.12 和更高的 13 版本

有关更多信息，请参阅[可信语言库类型](https://github.com/aws/pg_tle/blob/main/docs/09_datatypes.md)。

# 适用于 PostgreSQL 的可信语言扩展的函数参考
<a name="PostgreSQL_trusted_language_extension-functions-reference"></a>

查看以下有关适用于 PostgreSQL 的可信语言扩展中提供的函数的参考文档。使用这些函数安装、注册、更新和管理您的 *TLE 扩展*，即您使用可信语言扩展开发套件开发的 PostgreSQL 扩展。

**Topics**
+ [pgtle.available\$1extensions](#pgtle.available_extensions)
+ [pgtle.available\$1extension\$1versions](#pgtle.available_extension_versions)
+ [pgtle.extension\$1update\$1paths](#pgtle.extension_update_paths)
+ [pgtle.install\$1extension](#pgtle.install_extension)
+ [pgtle.install\$1update\$1path](#pgtle.install_update_path)
+ [pgtle.register\$1feature](#pgtle.register_feature)
+ [pgtle.register\$1feature\$1if\$1not\$1exists](#pgtle.register_feature_if_not_exists)
+ [pgtle.set\$1default\$1version](#pgtle.set_default_version)
+ [pgtle.uninstall\$1extension(name)](#pgtle.uninstall_extension-name)
+ [pgtle.uninstall\$1extension(name, version)](#pgtle.uninstall_extension-name-version)
+ [pgtle.uninstall\$1extension\$1if\$1exists](#pgtle.uninstall_extension_if_exists)
+ [pgtle.uninstall\$1update\$1path](#pgtle.uninstall_update_path)
+ [pgtle.uninstall\$1update\$1path\$1if\$1exists](#pgtle.uninstall_update_path_if_exists)
+ [pgtle.unregister\$1feature](#pgtle.unregister_feature)
+ [pgtle.unregister\$1feature\$1if\$1exists](#pgtle.unregister_feature_if_exists)

## pgtle.available\$1extensions
<a name="pgtle.available_extensions"></a>

`pgtle.available_extensions` 函数是一个集合返回函数。它返回数据库中所有可用的 TLE 扩展。返回的每一行都包含有关单个 TLE 扩展的信息。

### 函数原型
<a name="pgtle.available_extensions-prototype"></a>

```
pgtle.available_extensions()
```

### 角色
<a name="pgtle.available_extensions-role"></a>

无。

### 参数
<a name="pgtle.available_extensions-arguments"></a>

无。

### 输出
<a name="pgtle.available_extensions-output"></a>
+ `name` – TLE 扩展的名称。
+ `default_version` – 在未指定版本的情况下调用 `CREATE EXTENSION` 时要使用的 TLE 扩展的版本。
+ `description` – 有关 TLE 扩展的更详细描述。

### 用法示例
<a name="pgtle.available_extensions-usage-example"></a>

```
SELECT * FROM pgtle.available_extensions();
```

## pgtle.available\$1extension\$1versions
<a name="pgtle.available_extension_versions"></a>

`available_extension_versions` 函数是一个集合返回函数。它返回所有可用 TLE 扩展及其版本的列表。每行都包含有关给定 TLE 扩展的特定版本的信息，包括它是否需要特定角色。

### 函数原型
<a name="pgtle.available_extension_versions-prototype"></a>

```
pgtle.available_extension_versions()
```

### 角色
<a name="pgtle.available_extension_versions-role"></a>

无。

### 参数
<a name="pgtle.available_extension_versions-arguments"></a>

无。

### 输出
<a name="pgtle.available_extension_versions-output"></a>
+ `name` – TLE 扩展的名称。
+ `version` – TLE 扩展的版本。
+ `superuser` – 对于您的 TLE 扩展，此值始终为 `false`。创建 TLE 扩展或更新 TLE 扩展所需的权限与在给定数据库中创建其他对象所需的权限相同。
+ `trusted` – 对于您的 TLE 扩展，此值始终为 `false`。
+ `relocatable` – 对于您的 TLE 扩展，此值始终为 `false`。
+ `schema` – 指定安装 TLE 扩展的模式的名称。
+ `requires` – 包含此 TLE 扩展所需的其他扩展的名称的数组。
+ `description` – TLE 扩展的详细描述。

有关输出值的更多信息，请参阅 PostgreSQL 文档中的[将相关对象打包为扩展 > 扩展文件](https://www.postgresql.org/docs/current/extend-extensions.html#id-1.8.3.20.11)。

### 用法示例
<a name="pgtle.available_extension_versions-example"></a>

```
SELECT * FROM pgtle.available_extension_versions();
```

## pgtle.extension\$1update\$1paths
<a name="pgtle.extension_update_paths"></a>

`extension_update_paths` 函数是一个集合返回函数。它返回 TLE 扩展的所有可能更新路径的列表。每行都包含该 TLE 扩展的可用升级或降级。

### 函数原型
<a name="pgtle.extension_update_paths-prototype"></a>

```
pgtle.extension_update_paths(name)
```

### 角色
<a name="pgtle.extension_update_paths-role"></a>

无。

### 参数
<a name="pgtle.extension_update_paths-arguments"></a>

`name` – 从中获取升级路径的 TLE 扩展的名称。

### 输出
<a name="pgtle.extension_update_paths-output"></a>
+ `source` – 更新的源版本。
+ `target` – 更新的目标版本。
+ `path` – 用于将 TLE 扩展从 `source` 版本更新到 `target` 版本的升级路径，例如 `0.1--0.2`。

### 用法示例
<a name="pgtle.extension_update_paths-example"></a>

```
SELECT * FROM pgtle.extension_update_paths('your-TLE');
```

## pgtle.install\$1extension
<a name="pgtle.install_extension"></a>

`install_extension` 函数允许您在数据库中安装构成 TLE 扩展的构件，之后可以使用 `CREATE EXTENSION` 命令创建 TLE 扩展。

### 函数原型
<a name="pgtle.install_extension-prototype"></a>

```
pgtle.install_extension(name text, version text, description text, ext text, requires text[] DEFAULT NULL::text[])
```

### 角色
<a name="pgtle.install_extension-role"></a>

无。

### 参数
<a name="pgtle.install_extension-arguments"></a>
+ `name` – TLE 扩展的名称。调用 `CREATE EXTENSION` 时使用此值。
+ `version` – TLE 扩展的版本。
+ `description` – 有关 TLE 扩展的详细描述。此描述显示在 `pgtle.available_extensions()` 的 `comment` 字段中。
+ `ext` – TLE 扩展的内容。此值包含诸如函数之类的对象。
+ `requires` – 一个可选参数，用于指定此 TLE 扩展的依赖项。`pg_tle` 扩展会自动添加为依赖项。

其中许多参数与扩展控制文件中包含的参数相同，用于在 PostgreSQL 实例的文件系统上安装 PostgreSQL 扩展。有关更多信息，请参阅 PostgreSQL 文档的[将相关对象打包为扩展](https://www.postgresql.org/docs/current/extend-extensions.html)中的[扩展文件](http://www.postgresql.org/docs/current/extend-extensions.html#id-1.8.3.20.11)。

### 输出
<a name="pgtle.install_extension-output"></a>

此函数在成功时返回 `OK`，在出现错误时返回 `NULL`。
+ `OK` – TLE 扩展已成功安装在数据库中。
+ `NULL` – TLE 扩展未成功安装在数据库中。

### 用法示例
<a name="pgtle.install_extension-example"></a>

```
SELECT pgtle.install_extension(
 'pg_tle_test',
 '0.1',
 'My first pg_tle extension',
$_pgtle_$
  CREATE FUNCTION my_test()
  RETURNS INT
  AS $$
    SELECT 42;
  $$ LANGUAGE SQL IMMUTABLE;
$_pgtle_$
);
```

## pgtle.install\$1update\$1path
<a name="pgtle.install_update_path"></a>

`install_update_path` 函数提供 TLE 扩展的两个不同版本之间的更新路径。此功能允许您的 TLE 扩展的用户使用 `ALTER EXTENSION ... UPDATE` 语法更新其版本。

### 函数原型
<a name="pgtle.install_update_path-prototype"></a>

```
pgtle.install_update_path(name text, fromvers text, tovers text, ext text)
```

### 角色
<a name="pgtle.install_update_path-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.install_update_path-arguments"></a>
+ `name` – TLE 扩展的名称。调用 `CREATE EXTENSION` 时使用此值。
+ `fromvers` – 用于升级的 TLE 扩展的源版本。
+ `tovers` – 用于升级的 TLE 扩展的目标版本。
+ `ext` – 更新的内容。此值包含诸如函数之类的对象。

### 输出
<a name="pgtle.install_update_path-output"></a>

无。

### 用法示例
<a name="pgtle.install_update_path-example"></a>

```
SELECT pgtle.install_update_path('pg_tle_test', '0.1', '0.2',
  $_pgtle_$
    CREATE OR REPLACE FUNCTION my_test()
    RETURNS INT
    AS $$
      SELECT 21;
    $$ LANGUAGE SQL IMMUTABLE;
  $_pgtle_$
);
```

## pgtle.register\$1feature
<a name="pgtle.register_feature"></a>

`register_feature` 函数向 `pgtle.feature_info` 表中添加了指定的内部 PostgreSQL 功能。PostgreSQL 挂钩是 PostgreSQL 内部功能的一个示例。可信语言扩展开发套件支持使用 PostgreSQL 挂钩。目前，此函数支持以下功能。
+ `passcheck` – 将密码检查挂钩注册到自定义 PostgreSQL 的密码检查行为的过程或函数。

### 函数原型
<a name="pgtle.register_feature-prototype"></a>

```
pgtle.register_feature(proc regproc, feature pg_tle_feature)
```

### 角色
<a name="pgtle.register_feature-role"></a>

`pgtle_admin` 

### 参数
<a name="pgtle.register_feature-arguments"></a>
+ `proc` – 用于该功能的存储过程或函数的名称。
+ `feature` – 要注册到该函数的 `pg_tle` 功能（例如 `passcheck`）的名称。

### 输出
<a name="pgtle.register_feature-output"></a>

无。

### 用法示例
<a name="pgtle.register_feature-example"></a>

```
SELECT pgtle.register_feature('pw_hook', 'passcheck');
```

## pgtle.register\$1feature\$1if\$1not\$1exists
<a name="pgtle.register_feature_if_not_exists"></a>

`pgtle.register_feature_if_not_exists` 函数将指定的 PostgreSQL 功能添加到 `pgtle.feature_info` 表中，并标识使用该功能的 TLE 扩展或其他过程或函数。有关挂钩和可信语言扩展的更多信息，请参阅 [在您的 TLE 扩展中使用 PostgreSQL 挂钩](PostgreSQL_trusted_language_extension.overview.tles-and-hooks.md)。

### 函数原型
<a name="pgtle.register_feature_if_not_exists-prototype"></a>

```
pgtle.register_feature_if_not_exists(proc regproc, feature pg_tle_feature)
```

### 角色
<a name="pgtle.register_feature_if_not_exists-role"></a>

`pgtle_admin` 

### 参数
<a name="pgtle.register_feature_if_not_exists-arguments"></a>
+ `proc` – 包含用作 TLE 扩展的功能的逻辑（代码）的存储过程或函数的名称。例如，`pw_hook` 代码。
+ `feature` – 要为 TLE 函数注册的 PostgreSQL 功能的名称。目前，唯一可用的功能是 `passcheck` 挂钩。有关更多信息，请参阅 [密码检查挂钩（passcheck）](PostgreSQL_trusted_language_extension-hooks-reference.md#passcheck_hook)。

### 输出
<a name="pgtle.register_feature_if_not_exists-output"></a>

为指定的扩展注册该功能后返回 `true`。如果该功能已经注册，则返回 `false`。

### 用法示例
<a name="pgtle.register_feature_if_not_exists-example"></a>

```
SELECT pgtle.register_feature_if_not_exists('pw_hook', 'passcheck');
```

## pgtle.set\$1default\$1version
<a name="pgtle.set_default_version"></a>

`set_default_version` 函数可让您指定 TLE 扩展的 `default_version`。您可以使用此函数定义升级路径，并将该版本指定为 TLE 扩展的缺省版本。当数据库用户在 `CREATE EXTENSION` 和 `ALTER EXTENSION ... UPDATE` 命令中指定您的 TLE 扩展时，将在数据库中为该用户创建该版本的 TLE 扩展。

成功时，此函数返回 `true`。如果在 `name` 参数中指定的 TLE 扩展不存在，此函数将返回错误。同样，如果 TLE 扩展的 `version` 不存在，它会返回错误。

### 函数原型
<a name="pgtle.set_default_version-prototype"></a>

```
pgtle.set_default_version(name text, version text)
```

### 角色
<a name="pgtle.set_default_version-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.set_default_version-arguments"></a>
+ `name` – TLE 扩展的名称。调用 `CREATE EXTENSION` 时使用此值。
+ `version` – 用于设置缺省设置的 TLE 扩展版本。

### 输出
<a name="pgtle.set_default_version-output"></a>
+ `true` – 成功设置缺省版本时，此函数返回 `true`。
+ `ERROR` – 如果具有指定名称或版本的 TLE 扩展不存在，则返回错误消息。

### 用法示例
<a name="pgtle.set_default_version-example"></a>

```
SELECT * FROM pgtle.set_default_version('my-extension', '1.1');
```

## pgtle.uninstall\$1extension(name)
<a name="pgtle.uninstall_extension-name"></a>

`uninstall_extension` 函数从数据库中删除 TLE 扩展的所有版本。此函数可防止 `CREATE EXTENSION` 的将来调用安装 TLE 扩展。如果数据库中不存在 TLE 扩展，则会引发错误。

`uninstall_extension` 函数不会删除数据库中当前处于活动状态的 TLE 扩展。要删除当前处于活动状态的 TLE 扩展，您需要显式调用 `DROP EXTENSION` 以将其删除。

### 函数原型
<a name="pgtle.uninstall_extension-name-prototype"></a>

```
pgtle.uninstall_extension(extname text)
```

### 角色
<a name="pgtle.uninstall_extension-name-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.uninstall_extension-name-arguments"></a>
+ `extname` – 要卸载的 TLE 扩展的名称。此名称与用于 `CREATE EXTENSION` 的名称相同，旨在加载 TLE 扩展以便在给定数据库中使用。

### 输出
<a name="pgtle.uninstall_extension-name-output"></a>

无。

### 用法示例
<a name="pgtle.uninstall_extension-name-example"></a>

```
SELECT * FROM pgtle.uninstall_extension('pg_tle_test');
```

## pgtle.uninstall\$1extension(name, version)
<a name="pgtle.uninstall_extension-name-version"></a>

`uninstall_extension(name, version)` 函数从数据库中删除指定版本的 TLE 扩展。此功能可防止 `CREATE EXTENSION` 和 `ALTER EXTENSION` 将 TLE 扩展安装或更新到指定版本。此函数还删除指定版本的 TLE 扩展的所有更新路径。如果 TLE 扩展当前在数据库中处于活动状态，则此函数不会将其卸载。必须显式调用 `DROP EXTENSION` 才能删除 TLE 扩展。要卸载 TLE 扩展的所有版本，请参阅 [pgtle.uninstall\$1extension(name)](#pgtle.uninstall_extension-name)。

### 函数原型
<a name="pgtle.uninstall_extension-name-version-prototype"></a>

```
pgtle.uninstall_extension(extname text, version text)
```

### 角色
<a name="pgtle.uninstall_extension-name-version-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.uninstall_extension-name-version-arguments"></a>
+ `extname` – TLE 扩展的名称。调用 `CREATE EXTENSION` 时使用此值。
+ `version` – 要从数据库中卸载的 TLE 扩展的版本。

### 输出
<a name="pgtle.uninstall_extension-name-version-output"></a>

无。

### 用法示例
<a name="pgtle.uninstall_extension-name-version-example"></a>

```
SELECT * FROM pgtle.uninstall_extension('pg_tle_test', '0.2');
```

## pgtle.uninstall\$1extension\$1if\$1exists
<a name="pgtle.uninstall_extension_if_exists"></a>

`uninstall_extension_if_exists` 函数从给定的数据库中删除 TLE 扩展的所有版本。如果 TLE 扩展不存在，则该函数会静默返回（不会引发任何错误消息）。如果指定的扩展当前在数据库中处于活动状态，则此函数不会将其删除。必须先显式调用 `DROP EXTENSION` 以删除 TLE 扩展，然后才能使用此函数卸载其构件。

### 函数原型
<a name="pgtle.uninstall_extension_if_exists-prototype"></a>

```
pgtle.uninstall_extension_if_exists(extname text)
```

### 角色
<a name="pgtle.uninstall_extension_if_exists-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.uninstall_extension_if_exists-arguments"></a>
+ `extname` – TLE 扩展的名称。调用 `CREATE EXTENSION` 时使用此值。

### 输出
<a name="pgtle.uninstall_extension_if_exists-output"></a>

在卸载指定扩展后，`uninstall_extension_if_exists` 函数返回 `true`。如果指定的扩展不存在，则此函数将返回 `false`。
+ `true` – 卸载 TLE 扩展后返回 `true`。
+ `false` – 当数据库中不存在 TLE 扩展时返回 `false`。

### 用法示例
<a name="pgtle.uninstall_extension_if_exists-example"></a>

```
SELECT * FROM pgtle.uninstall_extension_if_exists('pg_tle_test');
```

## pgtle.uninstall\$1update\$1path
<a name="pgtle.uninstall_update_path"></a>

`uninstall_update_path` 函数从 TLE 扩展中删除特定的更新路径。这可以防止 `ALTER EXTENSION ... UPDATE TO` 将其用作更新路径。

如果 TLE 扩展当前正由此更新路径上的其中一个版本使用，则该扩展保留在数据库中。

如果指定的更新路径不存在，则此函数会引发错误。

### 函数原型
<a name="pgtle.uninstall_update_path-prototype"></a>

```
pgtle.uninstall_update_path(extname text, fromvers text, tovers text)
```

### 角色
<a name="pgtle.uninstall_update_path-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.uninstall_update_path-arguments"></a>
+ `extname` – TLE 扩展的名称。调用 `CREATE EXTENSION` 时使用此值。
+ `fromvers` – 更新路径上使用的 TLE 扩展的源版本。
+  `tovers` – 更新路径上使用的 TLE 扩展的目标版本。

### 输出
<a name="pgtle.uninstall_update_path-output"></a>

无。

### 用法示例
<a name="pgtle.uninstall_update_path-example"></a>

```
SELECT * FROM pgtle.uninstall_update_path('pg_tle_test', '0.1', '0.2');
```

## pgtle.uninstall\$1update\$1path\$1if\$1exists
<a name="pgtle.uninstall_update_path_if_exists"></a>

`uninstall_update_path_if_exists` 函数与 `uninstall_update_path` 类似，它从 TLE 扩展中删除指定的更新路径。但是，如果更新路径不存在，则此函数不会引发错误消息。相反，该函数返回 `false`。

### 函数原型
<a name="pgtle.uninstall_update_path_if_exists-prototype"></a>

```
pgtle.uninstall_update_path_if_exists(extname text, fromvers text, tovers text)
```

### 角色
<a name="pgtle.uninstall_update_path_if_exists-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.uninstall_update_path_if_exists-arguments"></a>
+ `extname` – TLE 扩展的名称。调用 `CREATE EXTENSION` 时使用此值。
+ `fromvers` – 更新路径上使用的 TLE 扩展的源版本。
+ `tovers` – 更新路径上使用的 TLE 扩展的目标版本。

### 输出
<a name="pgtle.uninstall_update_path_if_exists-output"></a>
+ `true` – 该函数已成功更新 TLE 扩展的路径。
+ `false` – 该函数无法更新 TLE 扩展的路径。

### 用法示例
<a name="pgtle.uninstall_update_path_if_exists-example"></a>

```
SELECT * FROM pgtle.uninstall_update_path_if_exists('pg_tle_test', '0.1', '0.2');
```

## pgtle.unregister\$1feature
<a name="pgtle.unregister_feature"></a>

`unregister_feature` 函数提供了一种方法，用于删除注册为使用 `pg_tle` 功能（如挂钩）的函数。有关注册功能的信息，请参阅 [pgtle.register\$1feature](#pgtle.register_feature)。

### 函数原型
<a name="pgtle.unregister_feature-prototype"></a>

```
pgtle.unregister_feature(proc regproc, feature pg_tle_features)
```

### 角色
<a name="pgtle.unregister_feature-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.unregister_feature-arguments"></a>
+ `proc` – 要向 `pg_tle` 功能注册的存储函数的名称。
+ `feature` – 要向函数注册的 `pg_tle` 功能的名称。例如，`passcheck` 是一项可以注册以供您开发的可信语言扩展使用的功能。有关更多信息，请参阅 [密码检查挂钩（passcheck）](PostgreSQL_trusted_language_extension-hooks-reference.md#passcheck_hook)。

### 输出
<a name="pgtle.unregister_feature-output"></a>

无。

### 用法示例
<a name="pgtle.unregister_feature-example"></a>

```
SELECT * FROM pgtle.unregister_feature('pw_hook', 'passcheck');
```

## pgtle.unregister\$1feature\$1if\$1exists
<a name="pgtle.unregister_feature_if_exists"></a>

`unregister_feature` 函数提供了一种方法，用于删除注册为使用 `pg_tle` 功能（如挂钩）的函数。有关更多信息，请参阅 [在您的 TLE 扩展中使用 PostgreSQL 挂钩](PostgreSQL_trusted_language_extension.overview.tles-and-hooks.md)。成功取消注册该功能后，返回 `true`。如果未注册该功能，则返回 `false`。

有关为 TLE 扩展注册 `pg_tle` 功能的信息，请参阅 [pgtle.register\$1feature](#pgtle.register_feature)。

### 函数原型
<a name="pgtle.unregister_feature_if_exists-prototype"></a>

```
pgtle.unregister_feature_if_exists('proc regproc', 'feature pg_tle_features')
```

### 角色
<a name="pgtle.unregister_feature_if_exists-role"></a>

`pgtle_admin`

### 参数
<a name="pgtle.unregister_feature_if_exists-arguments"></a>
+ `proc` – 为包含 `pg_tle` 功能而注册的存储函数的名称。
+ `feature` – 向可信语言扩展注册的 `pg_tle` 功能的名称。

### 输出
<a name="pgtle.unregister_feature_if_exists-output"></a>

返回 `true` 或 `false`，如下所示。
+ `true` – 该函数已成功将该功能从扩展中取消注册。
+ `false` – 该函数无法从 TLE 扩展中取消注册该功能。

### 用法示例
<a name="pgtle.unregister_feature_if_exists-example"></a>

```
SELECT * FROM pgtle.unregister_feature_if_exists('pw_hook', 'passcheck');
```

# 适用于 PostgreSQL 的可信语言扩展的挂钩参考
<a name="PostgreSQL_trusted_language_extension-hooks-reference"></a>

适用于 PostgreSQL 的可信语言扩展支持 PostgreSQL 挂钩。*挂钩*是一种内部回调机制，可供开发人员扩展 PostgreSQL 的核心功能。通过使用挂钩，开发人员可以实现自己的函数或过程以在各种数据库操作中使用，从而以某种方式修改 PostgreSQL 的行为。例如，您可以使用 `passcheck` 挂钩自定义 PostgreSQL 如何处理在为用户（角色）创建或更改密码时提供的密码。

查看以下文档，了解可用于 TLE 扩展的 passcheck 钩子。要了解有关可用钩子（包括客户端身份验证钩子）的更多信息，请参阅 [Trusted Language Extensions hooks](https://github.com/aws/pg_tle/blob/main/docs/04_hooks.md)。

## 密码检查挂钩（passcheck）
<a name="passcheck_hook"></a>

`passcheck` 挂钩用于在以下 SQL 命令和 `psql` 元命令的密码检查过程中自定义 PostgreSQL 行为。
+ `CREATE ROLE username ...PASSWORD` – 有关更多信息，请参阅 PostgreSQL 文档中的 [CREATE ROLE](https://www.postgresql.org/docs/current/sql-createrole.html)。
+ `ALTER ROLE username...PASSWORD` – 有关更多信息，请参阅 PostgreSQL 文档中的 [ALTER ROLE](https://www.postgresql.org/docs/current/sql-alterrole.html)。
+ `\password username` – 此交互式 `psql` 元命令在透明地使用 `ALTER ROLE ... PASSWORD` 语法之前，通过对密码进行哈希处理来安全地更改指定用户的密码。元命令是 `ALTER ROLE ... PASSWORD` 命令的安全包装器，因此挂钩适用于 `psql` 元命令的行为。

有关示例，请参阅[密码检查挂钩代码列表](PostgreSQL_trusted_language_extension.overview.tles-and-hooks.md#PostgreSQL_trusted_language_extension-example-hook_code_listing)。

**Contents**
+ [函数原型](#passcheck_hook-prototype)
+ [参数](#passcheck_hook-arguments)
+ [配置](#passcheck_hook-configuration)
+ [使用说明](#passcheck_hook-usage)

### 函数原型
<a name="passcheck_hook-prototype"></a>

```
passcheck_hook(username text, password text, password_type pgtle.password_types, valid_until timestamptz, valid_null boolean)
```

### 参数
<a name="passcheck_hook-arguments"></a>

`passcheck` 挂钩函数采用以下参数。
+ `username` – 设置密码的角色（用户名）的名称（文本）。
+ `password` – 纯文本或哈希处理的密码。输入的密码应与在 `password_type` 中指定的类型相匹配。
+ `password_type` – 指定密码的 `pgtle.password_type` 格式。此格式可能是以下选项之一。
  + `PASSWORD_TYPE_PLAINTEXT` – 纯文本密码。
  + `PASSWORD_TYPE_MD5` – 已使用 MD5（消息摘要 5）算法进行哈希处理的密码。
  + `PASSWORD_TYPE_SCRAM_SHA_256` – 已使用 SCRAM-SHA-256 算法进行哈希处理的密码。
+ `valid_until` – 指定密码变为失效的时间。此参数是可选的。如果使用此参数，请将时间指定为 `timestamptz` 值。
+ `valid_null` – 如果此布尔值设置为 `true`，则 `valid_until` 选项设置为 `NULL`。

### 配置
<a name="passcheck_hook-configuration"></a>

函数 `pgtle.enable_password_check` 控制 passcheck 挂钩是否处于活动状态。passcheck 挂钩有三种可能的设置。
+ `off` – 关闭 `passcheck` 密码检查挂钩。这是默认值。
+ `on` – 打开 `passcode` 密码检查挂钩，以便对照表检查密码。
+ `require` – 需要定义密码检查挂钩。

### 使用说明
<a name="passcheck_hook-usage"></a>

要打开或关闭 `passcheck` 挂钩，您需要修改 RDS for PostgreSQL 数据库实例的自定义数据库参数组。

对于 Linux、macOS 或 Unix：

```
aws rds modify-db-parameter-group \
    --region aws-region \
    --db-parameter-group-name your-custom-parameter-group \
    --parameters "ParameterName=pgtle.enable_password_check,ParameterValue=on,ApplyMethod=immediate"
```

对于：Windows

```
aws rds modify-db-parameter-group ^
    --region aws-region ^
    --db-parameter-group-name your-custom-parameter-group ^
    --parameters "ParameterName=pgtle.enable_password_check,ParameterValue=on,ApplyMethod=immediate"
```