

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

Amazon RDS는 여러 PostgreSQL 버전을 실행하는 DB 인스턴스를 지원합니다. 사용 가능한 버전 목록은 [사용 가능한 PostgreSQL 데이터베이스 버전](PostgreSQL.Concepts.General.DBVersions.md) 섹션을 참조하세요.

DB 인스턴스 및 DB 스냅샷, 특정 시점으로 복원 및 백업을 만들 수 있습니다. PostgreSQL을 실행하는 DB 인스턴스는 다중 AZ 배포, 읽기 전용 복제본,프로비저닝된 IOPS를 지원하며 Virtual Private Cloud(VPC) 내부에서 생성될 수 있습니다. 또한, SSL(Secure Socket Layer)을 사용하여 PostgreSQL을 실행하는 DB 인스턴스에 연결할 수 있습니다.

DB 인스턴스를 생성하기 전에 [Amazon RDS 환경 설정](CHAP_SettingUp.md) 단계를 완료해야 합니다.

클라이언트 컴퓨터에서 표준 SQL 클라이언트 애플리케이션을 사용하여 인스턴스에 대한 명령을 실행할 수 있습니다. 이런 애플리케이션으로는 PostgreSQL용으로 널리 사용되는 오픈 소스 관리 및 개발 도구인 pgAdmin 또는 PostgreSQL 설치 시 포함되는 명령줄 유틸리티인 psql이 포함됩니다. 관리형 서비스 환경을 제공하기 위해 Amazon RDS는 DB 인스턴스에 대해 호스트 액세스를 제공하지 않습니다. 또한 고급 권한이 필요한 특정 시스템 절차와 테이블에 대한 액세스를 제한합니다. Amazon RDS는 표준 SQL 클라이언트 애플리케이션을 사용하여 DB 인스턴스의 데이터베이스에 대한 액세스를 지원합니다. Amazon RDS에서는 Telnet 또는 SSH(Secure Shell)를 사용하여 DB 인스턴스에 대한 직접 호스트 액세스를 허용하지 않습니다.

Amazon RDS for PostgreSQL은 다수의 산업 표준을 준수합니다. 예를 들어 Amazon RDS for PostgreSQL 데이터베이스를 사용하여 HIPAA 준수 애플리케이션을 구축하고 의료 관련 정보를 저장할 수 있습니다. 여기에는 AWS와 체결한 비즈니스 제휴 계약(BAA)에 따라 보호 대상 건강 정보(PHI)를 위한 스토리지가 포함됩니다. 또한 Amazon RDS for PostgreSQL은 또한 연방 위험 및 인증 관리 프로그램(FedRAMP) 보안 요건을 충족합니다. Amazon RDS for PostgreSQL은 FedRAMP 공동 승인 위원회(JAB)로부터 AWS GovCloud (US) 리전 내에 FedRAMP High Baseline 수준의 잠정적 운영 권한(P-ATO)을 받았습니다. 지원되는 규정 준수 표준에 대한 자세한 내용은 [AWS 클라우드 규정 준수](https://aws.amazon.com/compliance/)를 참조하세요.

PostgreSQL 데이터를 DB 인스턴스로 가져오려면 [Amazon RDS에서 PostgreSQL로 데이터 가져오기](PostgreSQL.Procedural.Importing.md) 섹션의 정보를 따릅니다.

**중요**  
RDS for PostgreSQL DB 인스턴스에 문제가 발생하면 AWS Support 에이전트가 데이터베이스 상태에 대한 추가 정보가 필요할 수 있습니다. AWS Support가 가능한 한 빨리 필요한 정보를 확보하는 것이 목표입니다.  
PG 컬렉터를 사용하여 통합 HTML 파일에서 중요한 데이터베이스 정보를 수집할 수 있습니다. PG 컬렉터, 실행 방법 및 HTML 보고서 다운로드 방법에 대한 자세한 내용은 [PG 컬렉터](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 데이터베이스 엔진을 실행하는 DB 인스턴스에 연결](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 DB 엔진 업그레이드](USER_UpgradeDBInstance.PostgreSQL.md)
+ [PostgreSQL DB 스냅샷 엔진 버전 업그레이드](USER_UpgradeDBSnapshot.PostgreSQL.md)
+ [Amazon RDS for PostgreSQL의 읽기 전용 복제본 작업](USER_PostgreSQL.Replication.ReadReplicas.md)
+ [Amazon RDS Optimized Reads로 RDS for PostgreSQL 쿼리 성능 개선](USER_PostgreSQL.optimizedreads.md)
+ [Amazon RDS에서 PostgreSQL로 데이터 가져오기](PostgreSQL.Procedural.Importing.md)
+ [RDS for PostgreSQL DB 인스턴스에서 Amazon S3로 데이터 내보내기](postgresql-s3-export.md)
+ [RDS for PostgreSQL DB 인스턴스에서 AWS Lambda 함수 호출](PostgreSQL-Lambda.md)
+ [Amazon RDS for PostgreSQL의 일반적인 DBA 태스크](Appendix.PostgreSQL.CommonDBATasks.md)
+ [RDS for PostgreSQL의 대기 이벤트를 사용한 튜닝](PostgreSQL.Tuning.md)
+ [Amazon DevOps Guru의 사전 예방 인사이트를 활용하여 RDS for PostgreSQL 튜닝](PostgreSQL.Tuning_proactive_insights.md)
+ [Amazon RDS for PostgreSQL로 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 DB 인스턴스로 수행하는 일반적인 관리 작업과 각 작업에 해당하는 문서 링크입니다.


| 작업 영역 | 관련 설명서 | 
| --- | --- | 
|  **처음 사용 시 Amazon RDS 설정** DB 인스턴스를 생성하기 전에 몇 가지 사전 요구 사항을 완료해야 합니다. 예를 들어, DB 인스턴스는 기본적으로 인스턴스에 대한 액세스를 막는 방화벽도 함께 생성됩니다. 따라서 DB 인스턴스에 액세스하기 위한 알맞은 IP 주소와 네트워크 구성으로 보안 그룹을 만들어야 합니다.  |  [Amazon RDS 환경 설정](CHAP_SettingUp.md)  | 
|  **Amazon RDS DB 인스턴스 이해** 프로덕션 목적으로 DB 인스턴스를 만들 경우에는 Amazon RDS에서 인스턴스 클래스, 스토리지 유형 및 프로비저닝된 IOPS이 작동하는 방식을 이해해야 합니다.  |  [DB 인스턴스 클래스](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)  | 
|  **고가용성 및 장애 조치 지원 설정** 프로덕션 DB 인스턴스에서는 다중 AZ 배포를 사용해야 합니다. 다중 AZ 배포는 DB 인스턴스를 위해 향상된 가용성, 데이터 내구성 및 내결함성을 제공합니다.  |  [Amazon RDS에 대한 다중 AZ 배포 구성 및 관리](Concepts.MultiAZ.md)  | 
|  **Amazon Virtual Private Cloud(VPC) 네트워크 이해** AWS 계정에 기본 VPC가 있는 경우에는 DB 인스턴스가 기본 VPC 내부에 자동으로 생성됩니다. 경우에 따라 계정에 기본 VPC가 없을 수 있으며 VPC에 DB 인스턴스가 필요할 수 있습니다. 이러한 경우에는 DB 인스턴스를 생성하기 전에 VPC 및 서브넷 그룹을 생성하세요.   |  [VPC에서 DB 인스턴스를 사용한 작업](USER_VPC.WorkingWithRDSInstanceinaVPC.md)  | 
|  **Amazon RDS PostgreSQL로 데이터 가져오기** 다양한 도구를 사용하여 Amazon RDS의 PostgreSQL DB 인스턴스로 데이터를 가져올 수 있습니다.  |  [Amazon RDS에서 PostgreSQL로 데이터 가져오기](PostgreSQL.Procedural.Importing.md)  | 
|  **읽기 전용 복제본(기본 및 스탠바이) 설정** RDS for PostgreSQL는 프라이머리 인스턴스와 동일한 AWS 리전과 다른 AWS 리전 모두에서 읽기 전용 복제본을 지원합니다.  |  [DB 인스턴스 읽기 전용 복제본 작업](USER_ReadRepl.md) [Amazon RDS for PostgreSQL의 읽기 전용 복제본 작업](USER_PostgreSQL.Replication.ReadReplicas.md) [다른 에서 읽기 전용 복제본 생성AWS 리전](USER_ReadRepl.XRgn.md)  | 
|  **보안 그룹 이해** 기본적으로, DB 인스턴스와 함께 인스턴스에 대한 액세스를 막는 방화벽도 생성됩니다. 해당 방화벽을 통한 액세스를 제공하기 위해 DB 인스턴스를 호스팅하는 VPC와 연결된 VPC 보안 그룹의 인바운드 규칙을 편집합니다.  |  [보안 그룹을 통한 액세스 제어](Overview.RDSSecurityGroups.md)  | 
|  **파라미터 그룹 및 기능 설정** DB 인스턴스의 기본 파라미터를 변경하려면 사용자 지정 DB 파라미터 그룹을 생성하고 설정을 변경하세요. DB 인스턴스를 생성하기 전인 경우, 인스턴스를 생성할 때 사용자 지정 DB 파라미터 그룹을 선택할 수 있습니다.  |  [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md)  | 
|  **PostgreSQL DB 인스턴스에 연결** 보안 그룹을 만들고 이를 DB 인스턴스에 연결한 후 `psql` 또는 `pgAdmin`과 같은 스탠더드 SQL 클라이언트 애플리케이션을 사용하여 DB 인스턴스에 연결할 수 있습니다.  |  [PostgreSQL 데이터베이스 엔진을 실행하는 DB 인스턴스에 연결](USER_ConnectToPostgreSQLInstance.md) [PostgreSQL DB 인스턴스와 함께 SSL 사용](PostgreSQL.Concepts.General.SSL.md)  | 
|  **DB 인스턴스 백업 및 복원** DB 인스턴스를 구성하여 자동 백업을 생성하거나 수동 스냅샷을 생성한 다음 백업 또는 스냅샷에서 인스턴스를 복원할 수 있습니다.  |  [데이터 백업, 복원 및 내보내기](CHAP_CommonTasks.BackupRestore.md)  | 
|  **DB 인스턴스 활동 및 성능 모니터링** CloudWatch Amazon RDS 측정치, 이벤트 및 향상된 모니터링 기능을 통해 PostgreSQL DB 인스턴스를 모니터링할 수 있습니다.  |  [Amazon RDS 콘솔에서 지표 보기](USER_Monitoring.md) [Amazon RDS 이벤트 보기](USER_ListEvents.md)  | 
|  **PostgreSQL 데이터베이스 버전 업그레이드** PostgreSQL DB 인스턴스의 메이저 버전과 마이너 버전을 모두 업그레이드할 수 있습니다.  |  [RDS for PostgreSQL DB 엔진 업그레이드](USER_UpgradeDBInstance.PostgreSQL.md) [RDS for PostgreSQL 업그레이드에 대한 메이저 버전 선택](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.md)  | 
|  **로그 파일 작업** PostgreSQL DB 인스턴스의 로그 파일에 액세스할 수 있습니다.  |  [ RDS for PostgreSQL 데이터베이스 로그 파일](USER_LogAccess.Concepts.PostgreSQL.md)  | 
|  **PostgreSQL DB 인스턴스에 대한 모범 사례 이해** Amazon RDS의 PostgreSQL 사용에 대한 몇 가지 모범 사례를 찾아 보십시오.  |  [PostgreSQL로 작업하기 위한 모범 사례](CHAP_BestPractices.md#CHAP_BestPractices.PostgreSQL)  | 

다음은 PostgreSQL용 RDS의 주요 기능을 이해하고 사용하는 데 도움이 되는 이 가이드의 다른 섹션 목록입니다.
+  [PostgreSQL 역할 및 권한 이해](Appendix.PostgreSQL.CommonDBATasks.Roles.md) 
+  [PostgreSQL 데이터베이스에 대한 사용자 액세스 제어PostgreSQL에 대한 사용자 액세스 제어](Appendix.PostgreSQL.CommonDBATasks.Access.md) 
+  [RDS for PostgreSQL DB 인스턴스에 파라미터로 작업](Appendix.PostgreSQL.CommonDBATasks.Parameters.md) 
+  [RDS for PostgreSQL에서 지원되는 로깅 메커니즘 이해](Appendix.PostgreSQL.CommonDBATasks.md#Appendix.PostgreSQL.CommonDBATasks.Auditing) 
+  [Amazon RDS for PostgreSQL에서 PostgreSQL 자동 정리 사용](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 베타 버전을 미리 보기 릴리스로 제공합니다. 이를 통해 사용자는 미리 보기 버전을 사용하여 DB 인스턴스를 만들고 데이터베이스 미리 보기 환경에서 관련 기능을 테스트할 수 있습니다.

데이터베이스 미리 보기 환경의 RDS for PostgreSQL DB 인스턴스는 다른 RDS for PostgreSQL 인스턴스와 기능적으로 유사합니다. 그러나 프로덕션에는 미리 보기 버전을 사용할 수 없습니다.

이 방식을 사용하는 경우 다음과 같은 중요 제한 사항에 유의하십시오.
+ 모든 DB 인스턴스는 생성 60일 후 백업 및 스냅샷과 함께 삭제됩니다.
+ Amazon VPC 서비스 기반의 Virtual Private Cloud(VPC)에서만 DB 인스턴스를 생성할 수 있습니다.
+ 범용 SSD와 프로비저닝된 IOPS SSD 스토리지만 사용할 수 있습니다.
+ DB 인스턴스와 관련해서는 AWS Support의 지원을 받을 수 없습니다. 대신 AWS 관리형 Q&A 커뮤니티인 [AWS re:Post](https://repost.aws/tags/TAsibBK6ZeQYihN9as4S_psg/amazon-relational-database-service)에 질문을 게시할 수 있습니다.
+ DB 인스턴스의 스냅샷을 프로덕션 환경으로 복제할 수 없습니다.

미리 보기에서 지원되는 옵션은 다음과 같습니다.
+ DB 인스턴스는 M6i, R6i, M6g, M5, T3, R6g 및 R5인스턴스 유형으로만 만들 수 있습니다. RDS 인스턴스 클래스에 대한 자세한 내용은 [DB 인스턴스 클래스](Concepts.DBInstanceClass.md) 섹션을 참조하세요.
+ 단일 AZ 배포와 다중 AZ 배포를 모두 사용할 수 있습니다.
+ 표준 PostgreSQL 덤프 및 로드 함수를 사용하여 데이터베이스 미리 보기 환경에서 데이터베이스를 내보내거나 데이터베이스 미리 보기 환경으로 데이터베이스를 가져올 수 있습니다.

**Topics**
+ [데이터베이스 미리 보기 환경에서 지원하지 않는 기능](#preview-environment-exclusions)
+ [데이터베이스 미리 보기 환경의 PostgreSQL 버전 17](#PostgreSQL.Concepts.General.version17)
+ [데이터베이스 미리 보기 환경에서 새 DB 인스턴스 생성](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 Database Preview Environment에서 사용할 수 있습니다. PostgreSQL 버전 17.0에는 여러 개선 사항이 포함되어 있으며, 이에 관한 설명은 다음 PostgreSQL 설명서에 나와 있습니다. [PostgreSQL 17 릴리스](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/)를 선택합니다.

# 데이터베이스 미리 보기 환경에서 새 DB 인스턴스 생성
<a name="create-db-instance-in-preview-environment"></a>

다음 절차를 이용하여 미리 보기 환경에서 DB 인스턴스를 새로 만듭니다.

**데이터베이스 미리 보기 환경에서 DB 인스턴스를 생성하는 방법**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 탐색 창에서 **대시보드**를 선택합니다.

1. 다음 그림과 같이 Dashboard(대시보드) 페이지에서 **Database Preview Environment**(데이터베이스 미리 보기 환경) 섹션을 찾습니다.  
![\[RDS 콘솔, 대시보드에 링크가 표시된 미리 보기 환경 섹션\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/preview-environment-dashboard.png)

   [데이터베이스 미리 보기 환경](https://us-east-2.console.aws.amazon.com/rds-preview/home?region=us-east-2#)으로 바로 이동할 수도 있습니다. 계속하려면 먼저 제한 사항을 확인하고 수락해야 합니다.  
![\[미리 보기 환경 제한 사항 대화 상자\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/preview-environment-console.png)

1. RDS for PostgreSQL DB 인스턴스를 생성하려면 아무 Amazon RDS DB 인스턴스를 생성할 때와 동일한 프로세스를 따릅니다. 자세한 내용은 [DB 인스턴스 생성](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 에디션을 실행하는 DB 인스턴스를 지원합니다. 새 DB 인스턴스를 생성할 때는 현재 사용 가능한 모든 PostgreSQL 버전을 지정할 수 있습니다. 메이저 버전(예: PostgreSQL 14) 및 지정된 메이저 버전에 대해 사용 가능한 모든 마이너 버전을 지정할 수 있습니다. 버전이 지정되지 않은 경우 Amazon RDS는 사용 가능한 버전(보통 최신 버전)을 기본값으로 설정합니다. 메이저 버전이 지정되었지만 마이너 버전이 지정되지 않은 경우, Amazon RDS는 고객이 지정한 메이저 버전의 최근 릴리스를 기본값으로 설정합니다.

사용 가능한 버전 목록과 새로 만든 DB 인스턴스의 기본값을 보려면 [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 추가 지원에 자동 등록합니다. 그런 다음 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 FAQ](https://aws.amazon.com/rds/faqs/)를 참조하세요. PostgreSQL 버전에 대한 자세한 내용은 PostgreSQL 설명서의 [Versioning Policy](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>

증분 릴리스 프로세스는 다음과 같은 이점을 제공합니다.
+ 후속 릴리스를 통해 RDS별 개선 사항을 별도로 관리하면서 새로운 PostgreSQL 커뮤니티 릴리스를 빠르게 도입합니다. 이렇게 하면 릴리스 프로세스가 간소화되고 중요한 업데이트를 더 빠르게 제공할 수 있습니다.
+ PostgreSQL 마이너 버전과의 호환성을 유지하면서 버그 수정, 새 기능, 보안 업데이트 및 확장 프로그램 업데이트에 액세스할 수 있습니다.

## 릴리스 업데이트 관리
<a name="PostgreSQL.Concepts.General.ReleaseProcess.Manage"></a>

Amazon RDS는 AWS Management Console에서 보류 중인 유지 관리 작업을 통해 새 증분 릴리스에 대해 알립니다. 다음 방법 중 하나를 사용하여 데이터베이스를 업데이트할 수 있습니다.
+ 예약된 유지 관리 기간 동안 자동 업데이트를 활성화합니다.
+ 보류 중인 유지 관리 작업을 통해 업데이트를 수동으로 적용합니다.
+ 물리적 복제와 함께 블루/그린 배포를 사용하여 가동 중지 시간을 최소화합니다. 자세한 내용은 [Amazon RDS 블루/그린 배포, RDS for PostgreSQL의 마이너 버전 업그레이드 지원](https://aws.amazon.com/about-aws/whats-new/2024/11/rds-blue-green-deployments-upgrade-rds-postgresql/)을 참조하세요.

데이터베이스를 업데이트하기 전에 다음과 같은 중요한 점을 고려합니다.
+ 물리적 복제와 함께 블루/그린 배포를 사용하지 않는 한 업데이트에는 데이터베이스 재부팅이 필요합니다.
+ 일부 증분 릴리스, 특히 보안 수정 사항이 포함된 릴리스는 필수입니다.

Amazon RDS DB 인스턴스 업데이트에 대한 자세한 내용은 [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 버전의 기본 DB 파라미터 그룹에서 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 for PostgreSQL DB 인스턴스에 설치할 수 있는 확장을 `rds_superuser` 제한할 수 있습니다. 자세한 내용은 [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 DB 인스턴스에 설치할 수 있는 확장을 제한할 수 있습니다. 기본적으로 이 파라미터는 설정되지 않으므로 사용자에게 권한이 있는 경우 지원되는 확장 프로그램을 추가할 수 있습니다. 이렇게 하려면 `rds.allowed_extensions` 파라미터를 쉼표로 구분된 확장 이름의 문자열로 설정합니다. 이 파라미터에 확장 프로그램 목록을 추가하면 RDS for PostgreSQL DB 인스턴스가 사용할 수 있는 확장을 명시적으로 식별할 수 있습니다. 그런 다음 해당 확장만 PostgreSQL DB 인스턴스에 설치할 수 있습니다.

`rds.allowed_extensions` 파라미터의 기본 문자열은 '\$1'입니다. 즉, 해당 엔진 버전에 사용할 수 있는 모든 확장을 설치할 수 있습니다. `rds.allowed_extensions` 파라미터는 동적 파라미터이므로 변경해도 데이터베이스를 다시 시작할 필요가 없습니다.

`rds.allowed_extensions` 파라미터를 사용하려면 PostgreSQL DB 인스턴스 엔진이 다음 버전 중 하나여야 합니다.
+ 모든 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 [CREATE EXTENSION ](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에는 데이터베이스에서 일상적인 유지 관리를 수행하는 자동 autovacuum 기능이 있습니다. 자동 정리 실행 기능은 기본적으로 활성화되어 있습니다. 이 기능을 끌 수 있지만 계속 사용하는 것이 좋습니다. 이 기능을 이해하고 제대로 작동하는지 확인하기 위해 수행할 수 있는 작업은 모든 DBA의 기본 작업입니다. autovacuum에 대한 자세한 내용은 [Amazon RDS for PostgreSQL에서 PostgreSQL 자동 정리 사용](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md) 섹션을 참조하세요. 기타 일반적인 DBA 작업에 대해 자세히 알아보려면 [Amazon RDS for PostgreSQL의 일반적인 DBA 태스크](Appendix.PostgreSQL.CommonDBATasks.md) 섹션을 참조하세요.

RDS for PostgreSQL은 DB 인스턴스에 중요한 기능을 추가하는 확장도 지원합니다. 예를 들어 PostGIS 확장을 사용하여 공간 데이터로 작업하거나 pg\$1cron 확장을 사용하여 인스턴스 내에서 유지 관리를 예약할 수 있습니다. PostgreSQL 확장에 대한 자세한 내용은 [Amazon RDS for PostgreSQL로 PostgreSQL 확장 사용](Appendix.PostgreSQL.CommonDBATasks.Extensions.md) 섹션을 참조하세요.

외부 데이터 래퍼는 RDS for PostgreSQL DB 인스턴스가 다른 상용 데이터베이스 또는 데이터 유형과 함께 작동하도록 설계된 특정 유형의 확장입니다. 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`)을 사용하여 이벤트 트리거를 생성, 수정, 이름 변경 및 삭제할 수 있습니다. 이벤트 트리거는 DB 인스턴스 레벨에서 수행되므로 인스턴스에 대한 모든 데이터베이스에 적용될 수 있습니다.

예를 들어 다음 코드는 모든 데이터 정의 언어(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 문서의 [Event Triggers](https://www.postgresql.org/docs/current/static/event-triggers.html) 단원을 참조하세요.

Amazon RDS에서 PostgreSQL 이벤트 트리거를 사용하는 데 대한 몇 가지 제한 사항이 있습니다. 여기에는 다음이 포함됩니다.
+ 읽기 전용 복제본에 대한 이벤트 트리거를 생성할 수 없지만, 읽기 전용 복제 원본에 대한 이벤트 트리거는 생성할 수 있습니다. 그러면 이벤트 트리거가 읽기 전용 복제본으로 복사됩니다. 읽기 전용 복제본으로 복사된 이벤트 트리거는 변경 내용이 원본에서 푸시되더라도 읽기 전용 복제본에서 발생하지 않습니다. 하지만 읽기 전용 복제본이 승격되면 데이터베이스 작업이 있을 때 기존 이벤트 트리거가 발생합니다.
+ 이벤트 트리거를 사용하는 PostgreSQL DB 인스턴스로의 메이저 버전 업그레이드를 수행하려면 인스턴스를 업그레이드하기 전에 이벤트 트리거를 삭제해야 합니다.

# RDS for PostgreSQL용 방대한 페이지
<a name="PostgreSQL.Concepts.General.FeatureSupport.HugePages"></a>

*방대한 페이지*는 DB 인스턴스가 공유 버퍼에서 사용하는 것과 같은 대규모 연속 메모리 청크로 작업할 때 오버헤드를 줄이는 메모리 관리 기능입니다. 이 PostgreSQL 기능은 현재 사용 가능한 모든 RDS for PostgreSQL 버전에서 지원됩니다. 애플리케이션에 방대한 페이지를 할당하려면 `mmap` 또는 `SYSV` 공유 메모리 호출을 사용합니다. RDS for PostgreSQL은 4KB 페이지 크기와 2MB 페이지 크기를 모두 지원합니다.

`huge_pages` 파라미터의 값을 변경하여 방대한 페이지를 활성화하거나 비활성화할 수 있습니다. 이 기능은 마이크로, 스몰, 미디엄 DB 인스턴스 클래스를 제외한 모든 DB 인스턴스 클래스에 대해 기본적으로 사용 설정되어 있습니다.

RDS for PostgreSQL는 사용 가능한 공유 메모리를 기반으로 방대한 페이지를 사용합니다. DB 인스턴스가 공유 메모리 제약 때문에 방대한 페이지를 사용할 수 없을 경우 Amazon RDS는 DB 인스턴스 시작을 금지합니다. 이 경우 Amazon RDS는 DB 인스턴스 상태를 파라미터 호환 불가 상태로 설정합니다. 이렇게 되면 `huge_pages` 파라미터를 `off`로 설정하여 Amazon RDS가 DB 인스턴스를 시작하도록 허용할 수 있습니다.

`shared_buffers` 파라미터가 방대한 페이지를 사용하는 데 필요한 공유 메모리 풀을 설정하는 관건입니다. `shared_buffers` 파라미터의 기본값은 데이터베이스 파라미터 매크로를 사용합니다. 이 매크로는 DB 인스턴스 메모리에서 사용 가능한 총 8KB 페이지 중 백분율을 설정합니다. 방대한 페이지를 사용할 때 이러한 페이지는 방대한 페이지에 할당됩니다. 공유 메모리 파라미터를 DB 인스턴스 메모리의 90% 이상을 요구하도록 설정할 경우 Amazon RDS가 DB 인스턴스를 파라미터 호환 장애 상태로 설정하므로 유의해야 합니다.

PostgreSQL 메모리 관리에 대한 자세한 내용은 PostgreSQL 설명서의 [Resource Consumption](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) 문서를 참조하세요.

**참고**  
RDS for PostgreSQL은 PostgreSQL 10에 도입된 기본 PostgreSQL 논리적 복제 기능 외에 `pglogical` 확장도 지원합니다. 자세한 내용은 [pglogical을 사용하여 인스턴스 간 데이터 동기화](Appendix.PostgreSQL.CommonDBATasks.pglogical.md) 섹션을 참조하세요.

다음에서 RDS for PostgreSQL DB 인스턴스의 논리적 복제 설정에 관한 정보를 확인할 수 있습니다.

**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 논리적 복제용 클라이언트는 Amazon EC2 인스턴스의 사용자 지정 관리형 호스트 또는 AWS Database Migration Service입니다. 논리적 복제 슬롯에는 스트림 수신기에 대한 정보가 없습니다. 또한 대상이 복제본 데이터베이스일 필요는 없습니다. 논리적 복제 슬롯을 설정하고 슬롯에서 데이터를 읽지 않을 경우 데이터가 DB 인스턴스의 스토리지에 기록되고 빠르게 가득 찰 수 있습니다.

Amazon RDS의 PostgreSQL 논리적 복제 및 논리적 디코딩은 파라미터, 복제 연결 유형 및 보안 역할에 의해 활성화됩니다. PostgreSQL DB 인스턴스의 데이터베이스에 대한 복제 연결을 설정할 수 있는 모든 클라이언트는 논리적 디코딩용 클라이언트가 될 수 있습니다.

**RDS for PostgreSQL DB 인스턴스에 논리적 디코딩 사용 설정**

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` 파라미터가 적용되도록 DB 인스턴스를 재부팅합니다.

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 문서의 [Logical Decoding Examples](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 DB 인스턴스의 소스 데이터베이스에 연결합니다.

   ```
   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. 

**대상 데이터베이스에 연결 및 대상 테이블 생성**
   + 대상 DB 인스턴스의 대상 데이터베이스에 연결합니다. 소스 테이블과 이름이 동일한 대상 테이블을 생성합니다.

     ```
     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>

PostgreSQL용 RDS 버전 11 이상부터는 복제 연결에 AWS Identity and Access Management(IAM) 인증을 사용할 수 있습니다. 이 기능을 사용하면 암호 대신 IAM 역할을 사용하여 데이터베이스 액세스를 관리할 수 있으므로 보안이 강화됩니다. 이 기능은 클러스터 및 인스턴스 수준 모두에서 작동하며 표준 IAM 인증과 동일한 보안 모델을 따릅니다.

복제 연결을 위한 IAM 인증은 옵트인 기능입니다. 활성화하려면 DB 클러스터 또는 DB 파라미터 그룹의 `rds.iam_auth_for_replication` 파라미터를 1로 설정합니다. 동적 파라미터이므로 DB 클러스터 또는 인스턴스를 다시 시작할 필요가 없으므로, 가동 중지 시간 없이 기존 워크로드에서 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 DB 인스턴스는 버전 11 이상이어야 합니다.
+ 게시자 RDS for PostgreSQL DB 인스턴스에서:
  + 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 DB 인스턴스에서 IAM 인증과 논리적 복제가 모두 활성화되어 있어야 합니다. 둘 중 하나가 활성화되지 않은 경우 복제 연결에 IAM 인증을 사용할 수 없습니다.

## 복제 연결에 대한 IAM 인증 활성화
<a name="PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Enabling"></a>

다음 단계를 완료하여 복제 연결에 대한 IAM 인증을 활성화합니다.

**복제 연결에 대한 IAM 인증 활성화**

1. RDS for PostgreSQL DB 클러스터 또는 인스턴스가 복제 연결을 사용한 IAM 인증에 필요한 모든 필수 조건을 충족하는지 확인합니다. 자세한 내용은 [사전 조건](#PostgreSQL.Concepts.General.FeatureSupport.IAMLogicalReplication.Prerequisites)을 참조하세요.

1. RDS for PostgreSQL 설정을 기반으로 `rds.iam_auth_for_replication` 파라미터를 구성합니다.
   + RDS for PostgreSQL DB 인스턴스의 경우: DB 파라미터 그룹을 수정합니다.
   + 다중 AZ 클러스터의 경우: DB 클러스터 파라미터 그룹을 수정합니다.

   `rds.iam_auth_for_replication`을 1로 설정합니다. 재부팅할 필요 없이 즉시 적용되는 동적 파라미터입니다.
**참고**  
다중 AZ 클러스터는 DB 클러스터 파라미터 그룹만 사용합니다. 다중 AZ 클러스터에서는 개별 인스턴스 파라미터 그룹을 수정할 수 없습니다.

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 인증을 비활성화할 수 있습니다.
+ DB 인스턴스의 경우 DB 파라미터 그룹에서 `rds.iam_auth_for_replication` 파라미터를 0으로 설정하고 다중 AZ 클러스터의 경우 DB 클러스터 파라미터 그룹에서 파라미터를 0으로 설정합니다.
+ 또는 RDS for PostgreSQL DB 클러스터 또는 인스턴스에서 이러한 기능 중 하나를 비활성화할 수도 있습니다.
  + `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 디스크를 설정하려면 DB 인스턴스에 사용되는 파라미터 그룹에서 `rds.pg_stat_ramdisk_size` 파라미터를 정수 리터럴 값으로 설정합니다. 이 파라미터는 MB를 나타내므로 정수 값을 사용해야 합니다. 표현식, 공식 및 함수는 `rds.pg_stat_ramdisk_size` 파라미터에 유효하지 않습니다. 변경 사항을 적용하려면 DB 인스턴스를 재부팅해야 합니다. 파라미터 설정에 대한 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md)을 참조하세요.

예를 들어 다음 AWS CLI 명령은 RAM 디스크 파라미터를 256MB로 설정합니다.

```
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 분할 또는 격리를 위해 테이블스페이스를 사용할 수 없습니다. Amazon의 벤치마크 결과와 실용적 경험에 따르면 단일 논리 볼륨이 대부분의 사용 사례에 최선의 설정입니다.

RDS for PostgreSQL DB 인스턴스로 테이블스페이스를 생성하고 사용하려면 `rds_superuser` 역할이 필요합니다. RDS for PostgreSQL DB 인스턴스의 기본 사용자 계정(기본 이름, `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 테이블스페이스에 대한 자세한 내용은 [Tablespaces](https://www.postgresql.org/docs/current/manage-ag-tablespaces.html)(테이블스페이스)를 참조하세요.

# EBCDIC 및 기타 메인프레임 마이그레이션을 위한 RDS for PostgreSQL 데이터 정렬
<a name="PostgreSQL.Collations.mainframe.migration"></a>

PostgreSQL용 RDS 버전 10 이상에는 유니코드 10.0을 기반으로 하고 유니코드 공통 로케일 데이터 저리포지토리(CLDR 32)의 데이터 정렬이 포함된 ICU 버전 60.2가 포함되어 있습니다. 이러한 소프트웨어 국제화 라이브러리는 운영 체제나 플랫폼에 관계없이 문자 인코딩이 일관된 방식으로 표시되도록 합니다. 유니코드 CLDR-32에 대한 자세한 내용은 유니코드 CLDR 웹 사이트의 [CLDR 32 릴리스 노트](https://cldr.unicode.org/index/downloads/cldr-32)에서 확인할 수 있습니다. [ICU 기술 위원회(ICU-TC)](https://icu.unicode.org/home) 웹 사이트에서 유니코드(ICU)의 국제화 구성 요소에 대해 자세히 알아볼 수 있습니다. ICU-60에 대한 정보는 [ICU 60 다운로드](https://icu.unicode.org/download/60)를 참조하세요.

14.3 버전부터 PostgreSQL용 RDS에는 EBCDIC 기반 시스템에서 데이터 통합 및 변환을 지원하는 데이터 정렬도 포함됩니다. 확장 이진 코딩 십진 교환 코드 또는 *EBCDIC* 인코딩은 일반적으로 메인프레임 운영 체제에서 사용됩니다. Amazon RDS에서 제공하는 이러한 데이터 정렬은 EBCDIC 코드 페이지에 직접 매핑되는 유니코드 문자만 정렬하도록 좁게 정의되어 있습니다. 문자는 변환 후 데이터 유효성 검사가 가능하도록 EBCDIC 코드 포인트 순서로 정렬됩니다. 이러한 데이터 정렬에는 비정규화된 형식이 포함되지 않으며 소스 EBCDIC 코드 페이지의 문자에 직접 매핑되지 않는 유니코드 문자도 포함되지 않습니다.

EBCDIC 코드 페이지와 유니코드 코드 포인트 간의 문자 매핑은 IBM에서 게시한 테이블을 기반으로 합니다. 전체 세트는 다운로드용 [압축 파일](http://download.boulder.ibm.com/ibmdl/pub/software/dw/java/cdctables.zip)로 IBM에서 사용할 수 있습니다. PostgreSQL용 RDS는 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 데이터베이스에서 이러한 데이터 정렬을 사용할 수 있습니다.

 

다음 표에는 EBCDIC 코드 페이지를 유니코드 코드 포인트에 매핑하는 RDS for PostgreSQL에서 사용할 수 있는 데이터 정렬이 나와 있습니다. IBM 코드 페이지의 순서를 기준으로 정렬해야 하는 애플리케이션 개발에는 이 테이블의 데이터 정렬을 사용하는 것이 좋습니다.<a name="ebcdic-table"></a>


| PostgreSQL 데이터 정렬 이름 | 코드 페이지 매핑 및 정렬 순서에 대한 설명 | 
| --- | --- | 
| da-DK-cp277-x-icu | IBM EBCDIC 코드 페이지 277에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 277 코드 포인트 순서로 정렬됩니다. | 
| de-DE-cp273-x-icu | IBM EBCDIC 코드 페이지 273에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 273 코드 포인트 순서로 정렬됩니다. | 
| en-GB-cp285-x-icu | IBM EBCDIC 코드 페이지 285에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 285 코드 포인트 순서로 정렬됩니다. | 
| en-US-cp037-x-icu | IBM EBCDIC 코드 페이지 037에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 37 코드 포인트 순서로 정렬됩니다. | 
| es-ES-cp284-x-icu | IBM EBCDIC 코드 페이지 284에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 284 코드 포인트 순서로 정렬됩니다. | 
| fi-FI-cp278-x-icu | IBM EBCDIC 코드 페이지 278에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 278 코드 포인트 순서로 정렬됩니다. | 
| fr-FR-cp297-x-icu | IBM EBCDIC 코드 페이지 297에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 297 코드 포인트 순서로 정렬됩니다. | 
| it-IT-cp280-x-icu | IBM EBCDIC 코드 페이지 280에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 280 코드 포인트 순서로 정렬됩니다. | 
| nl-BE-cp500-x-icu | IBM EBCDIC 코드 페이지 500에 직접 매핑되는 유니코드 문자(변환 테이블당)는 IBM CP 500 코드 포인트 순서로 정렬됩니다. | 

Amazon RDS는 소스 데이터의 EBCDIC 코드 페이지에 따라 원래 코드 포인트의 순서로 IBM에서 게시한 테이블을 사용하여 LATIN9 문자에 매핑되는 유니코드 코드 포인트를 정렬하는 추가 데이터 정렬 세트를 제공합니다.<a name="latin9-table"></a>


| PostgreSQL 데이터 정렬 이름 | 코드 페이지 매핑 및 정렬 순서에 대한 설명 | 
| --- | --- | 
| da-DK-cp1142b-x-icu | IBM EBCDIC 코드 페이지 1142(변환 테이블당)에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1142 코드 포인트 순서로 정렬됩니다. | 
| de-DE-cp1141m-x-icu | IBM EBCDIC 코드 페이지 1141(변환 테이블당)에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1141 코드 포인트 순서로 정렬됩니다. | 
| en-GB-cp1146m-x-icu | IBM EBCDIC 코드 페이지 1146(변환 테이블당)에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1146 코드 포인트 순서로 정렬됩니다. | 
| en-US-cp1140m-x-icu | IBM EBCDIC 코드 페이지 1140(변환 테이블당)에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1140 코드 포인트 순서로 정렬됩니다. | 
| es-ES-cp1145m-x-icu | IBM EBCDIC 코드 페이지 1145(변환 테이블당)에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1145 코드 포인트 순서로 정렬됩니다. | 
| fi-FI-cp1143m-x-icu | IBM EBCDIC 코드 페이지 1143(변환 테이블당) 에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1143 코드 포인트 순서로 정렬됩니다. | 
| fr-FR-cp1147m-x-icu | IBM EBCDIC 코드 페이지 1147(변환 테이블당) 에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1147 코드 포인트 순서로 정렬됩니다. | 
| it-IT-cp1144m-x-icu | IBM EBCDIC 코드 페이지 1144(변환 테이블당) 에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 IBM CP 1144 코드 포인트 순서로 정렬됩니다. | 
| nl-BE-cp1148m-x-icu | IBM EBCDIC 코드 페이지 1148(변환 테이블당) 에서 원래 변환된 LATIN9 문자에 매핑되는 유니코드 문자는 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
```

IBM 코드 페이지의 순서를 기반으로 정렬해야 하는 애플리케이션 개발의 경우 [Unicode to EBCDIC collations table](#ebcdic-table) 및 [Unicode to LATIN9 collations table](#latin9-table)의 데이터 정렬을 사용하는 것이 좋습니다. 다음 데이터 정렬(문자 "b" 접미사)도 `pg_collation`에서 볼 수 있지만 특정 코드 포인트 이동이 있는 코드 페이지를 매핑하고 데이터 정렬에서 특별한 처리가 필요한 AWS의 메인프레임 데이터 통합 및 마이그레이션 도구에서 사용하기 위한 것입니다. 즉, 다음과 같은 데이터 정렬 데이터 정렬 방식은 권장되지 않습니다.
+ da-DK-cp1142b-x-icu
+ da-DK-cp1142b-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 데이터베이스 엔진을 실행하는 DB 인스턴스에 연결
<a name="USER_ConnectToPostgreSQLInstance"></a>

Amazon RDS가 DB 인스턴스를 프로비저닝한 후에는 표준 SQL 클라이언트 애플리케이션을 사용해 인스턴스에 연결할 수 있습니다. 연결하려면 먼저 DB 인스턴스를 사용할 수 있고 액세스할 수 있어야 합니다. VPC 외부에서 인스턴스에 연결할 수 있는지 여부는 Amazon RDS DB 인스턴스를 생성한 방법에 따라 달라집니다.
+ DB 인스턴스를 *퍼블릭*으로 생성한 경우 VPC 외부의 디바이스 및 Amazon EC2 인스턴스를 데이터베이스에 연결할 수 있습니다.
+ DB 인스턴스를 *프라이빗*으로 생성한 경우 Amazon VPC 내의 Amazon EC2 인스턴스 및 디바이스만 데이터베이스에 연결할 수 있습니다.

DB 인스턴스가 퍼블릭인지 프라이빗인지 확인하려면 AWS Management Console을 사용하여 인스턴스의 **연결 & 보안(Connectivity & security)** 탭을 봅니다. **보안(Security)** 아래에서 "퍼블릭 액세스 가능(Publicly accessible)" 값이 아니요(No)이면 프라이빗이고 예(Yes)이면 퍼블릭입니다.

다양한 Amazon RDS 및 Amazon VPC 구성과 이러한 구성이 접근성에 미치는 영향에 대한 자세한 내용은 [VPC에서 DB 인스턴스에 액세스하는 시나리오](USER_VPC.Scenarios.md) 섹션을 참조하세요.

**Contents**
+ [psql 클라이언트 설치](#install-psql)
+ [RDS for PostgreSQL DB 인스턴스에 대한 연결 정보 찾기](#postgresql-endpoint)
+ [pgAdmin을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결](USER_ConnectToPostgreSQLInstance.pgAdmin.md)
+ [psql을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결](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)
  + [Error – FATAL: database *name* does not exist](USER_ConnectToPostgreSQLInstance.Troubleshooting.md#USER_ConnectToPostgreSQLInstance.Troubleshooting-DBname)
  + [Error – Could not connect to server: Connection timed out](USER_ConnectToPostgreSQLInstance.Troubleshooting.md#USER_ConnectToPostgreSQLInstance.Troubleshooting-timeout)
  + [보안 그룹 액세스 규칙 오류](USER_ConnectToPostgreSQLInstance.Troubleshooting.md#USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules)

## psql 클라이언트 설치
<a name="install-psql"></a>

EC2 인스턴스에서 DB 인스턴스에 연결하려면 EC2 인스턴스에 PostgreSQL 클라이언트를 설치하면 됩니다. 최신 버전의 psql 클라이언트를 Amazon Linux 2023에 설치하려면 다음 명령을 실행하세요.

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

최신 버전의 psql 클라이언트를 Amazon Linux 2에 설치하려면 다음 명령을 실행하세요.

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

최신 버전의 psql 클라이언트를 Ubuntu에 설치하려면 다음 명령을 실행하세요.

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

## RDS for PostgreSQL DB 인스턴스에 대한 연결 정보 찾기
<a name="postgresql-endpoint"></a>

DB 인스턴스를 사용할 수 있고 액세스할 수 있는 경우 SQL 클라이언트 애플리케이션에 다음 정보를 제공하여 연결할 수 있습니다.
+ 인스턴스의 호스트 이름(DNS 이름) 역할을 하는 DB 인스턴스 엔드포인트입니다.
+ DB 인스턴스 서버가 수신 대기하는 포트입니다. PostgreSQL의 경우 기본 포트는 5432입니다.
+ DB 인스턴스의 사용자 이름 및 암호입니다. 기본으로 설정된 PostgreSQL의 '기본 사용자 이름'은 `postgres`입니다.
+ 데이터베이스의 이름 및 암호입니다(DB 이름).

 이러한 세부 정보는 AWS Management Console, 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 Management Console을 사용하여 엔드포인트, 포트 번호, DB 이름을 찾는 방법**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. RDS 콘솔을 연 다음 **데이터베이스**를 선택해 DB 인스턴스의 목록을 표시합니다.

1. 세부 정보를 표시하고자 하는 PostgreSQL DB 인스턴스 이름을 선택합니다.

1. **Connectivity & security(연결 및 보안)** 탭에서 엔드포인트를 복사합니다. 또한 포트 번호를 적어 둡니다. DB 인스턴스에 연결하려면 엔드포인트와 포트 번호가 모두 필요합니다.  
![\[RDS 콘솔에서 엔드포인트 가져오기\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/PostgreSQL-endpoint.png)

1. **구성** 탭에 나와 있는 DB 이름을 적어 둡니다. RDS for PostgreSQL 인스턴스를 만들 때 데이터베이스를 생성한 경우 DB 이름 아래에 이름이 표시됩니다. 데이터베이스를 만들지 않은 경우 DB 이름에 대시(‐)가 표시됩니다.  
![\[RDS 콘솔에서 DB 이름 가져오기\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/PostgreSQL-db-name.png)

다음은 PostgreSQL DB 인스턴스에 연결하는 두 가지 방법입니다. 첫 번째 예에서는 PostgreSQL의 잘 알려진 오픈 소스 관리 및 개발 도구인 pgAdmin을 사용합니다. 두 번째 예에서는 PostgreSQL 설치에 속하는 명령행 유틸리티인 psql을 사용합니다.

# pgAdmin을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결
<a name="USER_ConnectToPostgreSQLInstance.pgAdmin"></a>

오픈 소스 도구인 pgAdmin을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결할 수 있습니다. 클라이언트 컴퓨터에 로컬 PostgreSQL 인스턴스가 없어도 [http://www.pgadmin.org/](http://www.pgadmin.org/)에서 pgAdmin을 다운로드하여 설치할 수 있습니다.

**pgAdmin을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결하는 방법**

1. 클라이언트 컴퓨터에서 pgAdmin 애플리케이션을 실행합니다.

1. [**Dashboard**] 탭에서 [**Add New Server**]를 선택합니다.

1. [**Create - Server**] 대화 상자에서 pgAdmin의 서버를 식별하기 위해 [**General**] 탭에 이름을 입력합니다.

1. [**Connection**] 탭에서 사용자 DB 인스턴스에 있는 다음 정보를 입력합니다.
   + **Host(호스트)**에 엔드포인트를 입력합니다(예: `mypostgresql.c6c8dntfzzhgv0.us-east-2.rds.amazonaws.com`).
   + **포트**에 할당된 포트를 입력합니다.
   + **사용자 이름(Username)**에 DB 인스턴스를 생성할 때 입력한 사용자 이름을 입력합니다('기본 사용자 이름'을 기본값에서 변경한 경우 `postgres`).
   + **암호**에 DB 인스턴스를 생성할 떄 입력했던 암호를 입력합니다.  
![\[DB 인스턴스를 만들 때 입력한 암호 입력\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/Postgres-Connect01.png)

1. **저장**을 선택합니다.

   연결 문제는 [RDS for PostgreSQL 인스턴스에 대한 연결 문제 해결](USER_ConnectToPostgreSQLInstance.Troubleshooting.md)를 참조하십시오.

1. pgAdmin 브라우저에서 데이터베이스에 액세스 하려면, [**Servers**], DB 인스턴스, [**Databases**]를 확장합니다. DB 인스턴스의 데이터베이스 이름을 선택합니다.  
![\[pgAdmin 브라우저에서 DB 인스턴스의 데이터베이스 이름 선택\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/Postgres-Connect02.png)

1. SQL 명령을 입력할 수 있는 패널을 열려면, **도구**, **쿼리 도구**를 선택합니다.

# psql을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결
<a name="USER_ConnectToPostgreSQLInstance.psql"></a>

psql 명령줄 유틸리티의 로컬 인스턴스를 사용하여 RDS for PostgreSQL DB 인스턴스에 연결할 수 있습니다. 클라이언트 컴퓨터에 PostgreSQL 또는 psql 클라이언트를 설치해야 할 수도 있습니다.

[PostgreSQL](https://www.postgresql.org/download/) 웹 사이트에서 PostgreSQL 클라이언트를 다운로드할 수 있습니다. psql을 설치하려면 운영 체제 버전별 지침을 따르세요.

psql을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결하려면 호스트(DNS) 정보, 액세스 자격 증명 및 데이터베이스 이름을 제공해야 합니다.

다음 형식 중 하나를 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다. 연결이 되면 암호를 입력하라는 메시지가 표시됩니다. 배치 작업이나 스크립트에는 `--no-password` 옵션을 사용합니다. 이 옵션은 전체 세션에 대해 설정됩니다.

**참고**  
서버에 암호 인증이 필요하고 다른 소스에서 암호를 사용할 수 없는 경우 `--no-password`를 사용한 연결 시도가 실패합니다. 자세한 내용은 [psql 설명서](https://www.postgresql.org/docs/13/app-psql.html)를 참조하세요.

이 DB 인스턴스에 처음 연결하는 경우 또는 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 DB 인스턴스에서 `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 드라이버를 설치하려면 `CLASSPATH` 애플리케이션에 있는 AWS JDBC 드라이버 .jar 파일을 추가하고 해당 커뮤니티 드라이버에 대한 참조를 보관해 두세요. 다음과 같이 해당 연결 URL 접두사를 업데이트하세요.
+ `jdbc:postgresql://`\$1`jdbc:aws-wrapper:postgresql://`

AWS JDBC 드라이버에 대한 자세한 내용 및 사용 방법에 대한 전체 지침은 [Amazon Web Services (AWS) JDBC Driver GitHub repository](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 드라이버는 고급 Python 래퍼로 설계되었습니다. 이 래퍼는 오픈 소스 Psycopg 드라이버의 기능을 보완하고 확장합니다. AWS Python 드라이버는 Python 버전 3.8 이상을 지원합니다. `pip` 명령을 사용하여 `psycopg` 오픈 소스 패키지와 함께 `aws-advanced-python-wrapper` 패키지를 설치할 수 있습니다.

AWS Python 드라이버에 대한 자세한 내용 및 사용 방법에 대한 전체 지침은 [Amazon Web Services (AWS) JDBC Python GitHub repository](https://github.com/awslabs/aws-advanced-python-wrapper)를 참조하세요.

# RDS for PostgreSQL 인스턴스에 대한 연결 문제 해결
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting"></a>

**Topics**
+ [Error – FATAL: database *name* does not exist](#USER_ConnectToPostgreSQLInstance.Troubleshooting-DBname)
+ [Error – Could not connect to server: Connection timed out](#USER_ConnectToPostgreSQLInstance.Troubleshooting-timeout)
+ [보안 그룹 액세스 규칙 오류](#USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules)

## Error – FATAL: database *name* does not exist
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting-DBname"></a>

연결할 때 `FATAL: database name does not exist` 같은 오류가 발생하면 `--dbname` 옵션에 기본 데이터베이스 이름 **postgres**를 사용해봅니다.

## Error – Could not connect to server: Connection timed out
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting-timeout"></a>

DB 인스턴스에 연결할 수 없도록 만드는 가장 많은 오류가 `Could not connect to server: Connection timed out.`입니다. 이 오류 메시지가 표시되면 다음을 확인합니다.
+ 사용한 호스트 이름이 DB 인스턴스 엔드포인트이고 포트 번호가 올바른지 확인하십시오.
+ 외부 연결을 허용하도록 DB 인스턴스의 퍼블릭 액세스 가능성이 **예(Yes)**로 설정되어 있는지 확인합니다. **퍼블릭 액세스(Public access)** 설정을 수정하려면 [Amazon RDS DB 인스턴스 수정](Overview.DBInstance.Modifying.md) 섹션을 참조하세요.
+ 데이터베이스에 연결하는 사용자에게 CONNECT 액세스 권한이 있는지 확인합니다. 다음 쿼리를 사용하여 데이터베이스에 대한 연결 액세스를 제공할 수 있습니다.

  ```
  GRANT CONNECT ON DATABASE database name TO username;
  ```
+ DB 인스턴스에 할당된 보안 그룹에 모든 연결이 통과할 수 있는 방화벽을 통한 액세스를 허용하는 데 필요한 규칙이 있는지 확인하십시오. 기본값 포트 5432를 사용해 DB 인스턴스를 생성했는데, 기업 방화벽 규칙이 외부 회사 디바이스의 해당 포트 연결을 차단하는 경우를 예로 들 수 있습니다.

  이 오류를 수정하려면 다른 포트를 사용하도록 DB 인스턴스를 수정해야 합니다. 또 DB 인스턴스에 적용된 보안 그룹의 새로운 포트에 대한 연결이 허용되어야 합니다. **데이터베이스 포트(Database port)** 설정을 수정하려면 [Amazon RDS DB 인스턴스 수정](Overview.DBInstance.Modifying.md) 섹션을 참조하세요.
+ 사용하려는 포트가 PostgreSQL의 로컬 인스턴스 또는 컴퓨터에서 실행되는 다른 서비스에 의해 이미 사용 중인지 확인합니다. 예를 들어 동일한 포트(기본값은 5432)에서 실행 중인 로컬 PostgreSQL 데이터베이스가 있는 경우 RDS for PostgreSQL DB 인스턴스에 성공적으로 연결되지 않을 수 있습니다. 포트가 사용 가능한지 확인하거나 가능하면 다른 포트 번호로 연결을 시도합니다.
+ 또한 [보안 그룹 액세스 규칙 오류](#USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules) 단원도 참조하십시오.

## 보안 그룹 액세스 규칙 오류
<a name="USER_ConnectToPostgreSQLInstance.Troubleshooting-AccessRules"></a>

지금까지 가장 많이 발생하고 있는 연결 문제는 DB 인스턴스에 할당된 보안 그룹의 액세스 규칙과 관련이 있습니다. DB 인스턴스를 만들 때 기본 보안 그룹을 사용한 경우 인스턴스에 액세스할 수 있도록 허용하는 규칙이 보안 그룹에 없을 확률이 큽니다.

연결이 되도록 만들려면, 생성 때 DB 인스턴스에 할당한 보안 그룹이 DB 인스턴스 액세스를 허용해야 합니다. 예를 들어, DB 인스턴스가 VPC 내부에서 생성된 경우 이 인스턴스의 VPC 보안 그룹에서 연결 권한을 부여해야 합니다. 애플리케이션이 실행되고 있는 디바이스 또는 Amazon EC2 인스턴스의 연결을 승인하지 않는 보안 그룹을 사용하여 DB 인스턴스를 생성했는지 여부를 확인합니다.

보안 그룹에서 인바운드 규칙을 추가하거나 편집할 수 있습니다. **소스**로 **내 IP**를 선택하면 브라우저에서 감지된 IP 주소에서 DB 인스턴스에 액세스할 수 있습니다. 자세한 내용은 [보안 그룹을 생성하여 VPC 내부의 DB 인스턴스에 대한 액세스를 제공](CHAP_SettingUp.md#CHAP_SettingUp.SecurityGroup) 섹션을 참조하세요.

또한, DB 인스턴스가 VPC 외부에서 생성된 경우에는 이 인스턴스의 데이터베이스 보안 그룹에서 이 연결을 승인해야 합니다.

Amazon RDS 보안 그룹에 대한 자세한 내용은 [보안 그룹을 통한 액세스 제어](Overview.RDSSecurityGroups.md) 단원을 참조하십시오.

# SSL/TLS를 사용한 RDS for PostgreSQL 연결 보안
<a name="PostgreSQL.Concepts.General.Security"></a>

RDS for PostgreSQL은 PostgreSQL DB 인스턴스를 위한 SSL 암호화를 지원합니다. SSL을 사용하여 애플리케이션과 PostgreSQL DB 인스턴스 사이의 PostgreSQL 연결을 암호화할 수 있습니다. 또한 PostgreSQL DB 인스턴스에 대한 모든 연결에서 SSL을 사용하도록 지정할 수도 있습니다. 또한 RDS for PostgreSQL은 SSL에 대한 후속 프로토콜인 전송 계층 보안(TLS)을 지원합니다.

SSL/TLS를 사용하는 연결 암호화 등 Amazon RDS 및 데이터 보호에 대한 자세한 내용은 [Amazon RDS의 데이터 보호](DataDurability.md) 섹션을 참조하세요.

**Topics**
+ [PostgreSQL DB 인스턴스와 함께 SSL 사용](PostgreSQL.Concepts.General.SSL.md)
+ [새 SSL/TLS 인증서를 사용해 PostgreSQL DB 인스턴스에 연결할 애플리케이션 업데이트](ssl-certificate-rotation-postgresql.md)

# PostgreSQL DB 인스턴스와 함께 SSL 사용
<a name="PostgreSQL.Concepts.General.SSL"></a>

Amazon RDS는 PostgreSQL DB 인스턴스를 위한 SSL 암호화를 지원합니다. SSL을 사용하여 애플리케이션과 PostgreSQL DB 인스턴스 사이의 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 DB 인스턴스가 생성될 때 해당 인스턴스의 SSL 인증서를 만듭니다. SSL 인증서 확인을 활성화하는 경우에는 SSL 인증서에 스푸핑 공격으로부터 보호해주는 SSL 인증서를 위한 일반 이름(CN)으로 DB 인스턴스 엔드포인트가 포함됩니다.

**Topics**
+ [SSL을 통해 PostgreSQL DB 인스턴스에 연결](#PostgreSQL.Concepts.General.SSL.Connecting)
+ [PostgreSQL DB 인스턴스에 SSL 연결 요구](#PostgreSQL.Concepts.General.SSL.Requiring)
+ [SSL 연결 상태 확인](#PostgreSQL.Concepts.General.SSL.Status)
+ [RDS for PostgreSQL의 SSL 암호 제품군](#PostgreSQL.Concepts.General.SSL.Ciphers)

## SSL을 통해 PostgreSQL DB 인스턴스에 연결
<a name="PostgreSQL.Concepts.General.SSL.Connecting"></a>

**SSL을 통해 PostgreSQL DB 인스턴스에 연결하려면**

1. 인증서를 다운로드합니다.

   인증서 다운로드에 대한 자세한 내용은 [SSL/TLS를 사용하여 DB 인스턴스 또는 클러스터 에 대한 연결 암호화](UsingWithRDS.SSL.md) 단원을 참조하세요.

1. SSL을 통해 PostgreSQL DB 인스턴스에 연결합니다.

   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`을 사용하여 인증서 확인과 함께 SSL을 사용하여 PostgreSQL DB 인스턴스에 연결하는 예입니다.

```
$ 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 DB 인스턴스에 SSL 연결 요구
<a name="PostgreSQL.Concepts.General.SSL.Requiring"></a>

`rds.force_ssl` 파라미터를 사용하여 PostgreSQL DB 인스턴스에 대한 연결이 SSL을 사용하도록 요구할 수 있습니다. RDS for PostgreSQL 버전 15 이상의 `rds.force_ssl` 파라미터 기본값은 1(켜짐)입니다. 다른 모든 RDS for PostgreSQL 메이저 버전 14 이상에는 이 파라미터의 기본값이 0(꺼짐)입니다. `rds.force_ssl` 파라미터를 1(설정)로 설정하면 해당 DB 클러스터에 대한 연결 시 SSL/TLS를 요구합니다. `rds.force_ssl` 파라미터를 1(설정)로 설정하면 해당 DB 인스턴스에 대한 연결에 대해 SSL을 요구합니다.

이 파라미터의 값을 변경하려면 사용자 지정 DB 파라미터 그룹을 생성해야 합니다. 그런 다음 사용자 지정 DB 파라미터 그룹의 `rds.force_ssl` 값을 `1`로 변경하여 이 기능을 켭니다. RDS for PostgreSQL DB 인스턴스를 생성하기 전에 사용자 지정 DB 파라미터 그룹을 준비하는 경우 생성 과정 중에 기본 파라미터 그룹 대신 선택할 수 있습니다. RDS for PostgreSQL DB 인스턴스가 이미 실행된 후에 이 작업을 수행하는 경우 인스턴스가 사용자 지정 파라미터 그룹을 사용하도록 인스턴스를 재부팅해야 합니다. 자세한 정보는 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md)의 내용을 참조하세요.

DB 인스턴스에서 `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>

DB 인스턴스에 연결할 때 로그온 배너에 연결의 암호화된 상태가 표시됩니다.

```
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 DB 인스턴스의 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 콘솔 또는 다음 AWS CLI 명령을 사용합니다.

```
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\$1ciphers는 지원되지 않음 | 
| 14 | HIGH:\$1aNULL:\$13DES | 사용자 지정 ssl\$1ciphers는 지원되지 않음 | 
| 13 | HIGH:\$1aNULL:\$13DES | 사용자 지정 ssl\$1ciphers는 지원되지 않음 | 
| 12 | HIGH:\$1aNULL:\$13DES | 사용자 지정 ssl\$1ciphers는 지원되지 않음 | 
| 11.4 이상의 마이너 버전 | HIGH:MEDIUM:\$13DES:\$1aNULL:\$1RC4 | 사용자 지정 ssl\$1ciphers는 지원되지 않음 | 
| 11.1, 11.2 | HIGH:MEDIUM:\$13DES:\$1aNULL | 사용자 지정 ssl\$1ciphers는 지원되지 않음 | 
| 10.9 이상의 마이너 버전 | HIGH:MEDIUM:\$13DES:\$1aNULL:\$1RC4 | 사용자 지정 ssl\$1ciphers는 지원되지 않음 | 
| 10.7 이하 마이너 버전 | HIGH:MEDIUM:\$13DES:\$1aNULL | 사용자 지정 ssl\$1ciphers는 지원되지 않음 | 

`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"
```

이 예제에서는 인스턴스가 타원 곡선 암호(ECC)를 갖춘 인증 기관을 사용하여 연결을 설정해야 하는 ECDSA 암호를 사용합니다. Amazon RDS에서 제공하는 인증 기관에 대한 자세한 내용은 [Certificate authorities](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/singWithRDS.SSL.html#UsingWithRDS.SSL.RegionCertificateAuthorities)를 참조하세요.

[Determining the SSL connection status](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.3은 `ssl_ciphers` 파라미터에 지정된 암호 구성을 사용하지 않으므로 이 파라미터의 값을 TLS v1.2로 설정해야 합니다. 값을 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로 설정합니다. 파라미터 및 파라미터 그룹에 대한 자세한 내용은 [Parameter groups for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html)를 참조하세요.

# 새 SSL/TLS 인증서를 사용해 PostgreSQL DB 인스턴스에 연결할 애플리케이션 업데이트
<a name="ssl-certificate-rotation-postgresql"></a>

보안 소켓 계층 또는 전송 계층(SSL/TLS)에 사용되는 인증서는 일반적으로 설정된 수명을 가집니다. 서비스 공급자가 인증 기관(CA) 인증서를 업데이트할 때 클라이언트는 새 인증서를 사용하도록 애플리케이션을 업데이트해야 합니다. 다음은 클라이언트 애플리케이션에서 SSL/TLS를 사용하여 Amazon RDS for PostgreSQL DB 인스턴스에 연결하는지 판단하는 방법에 대한 정보를 확인할 수 있습니다. 또한 이러한 애플리케이션이 연결할 때 서버 인증서를 확인하는지 확인하는 방법에 대한 정보도 확인할 수 있습니다.

**참고**  
SSL/TLS 연결 전에 서버 인증서를 확인하도록 구성된 클라이언트 애플리케이션은 클라이언트의 트러스트 스토어에 유효한 CA 인증서가 있어야 합니다. 새 인증서에 필요한 경우 클라이언트 트러스트 스토어를 업데이트합니다.

클라이언트 애플리케이션 트러스트 스토어에서 CA 인증서를 업데이트한 후에는 DB 인스턴스에서 인증서를 교환할 수 있습니다. 이 절차를 프로덕션 환경에서 구현하기 전에 비 프로덕션 환경에서 테스트해볼 것을 적극 권장합니다.

인증서 교환에 대한 자세한 내용은 [SSL/TLS 인증서 교체](UsingWithRDS.SSL-certificate-rotation.md) 단원을 참조하십시오. 인증서 다운로드에 대한 자세한 내용은 [SSL/TLS를 사용하여 DB 인스턴스 또는 클러스터 에 대한 연결 암호화](UsingWithRDS.SSL.md) 단원을 참조하십시오. PostgreSQL DB 인스턴스에서 SSL/TLS를 사용하는 방법에 관한 자세한 내용은 [PostgreSQL DB 인스턴스와 함께 SSL 사용](PostgreSQL.Concepts.General.SSL.md) 단원을 참조하십시오.

**Topics**
+ [애플리케이션에서 SSL을 사용해 PostgreSQL DB 인스턴스에 연결하는지 여부 확인](#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 DB 인스턴스에 연결하는지 여부 확인
<a name="ssl-certificate-rotation-postgresql.determining-server"></a>

`rds.force_ssl` 파라미터의 값에 대한 DB 인스턴스 구성을 확인하십시오. 기본적으로 이 `rds.force_ssl` 파라미터는 버전 15 이하의 PostgreSQL 버전을 사용하는 DB 인스턴스의 경우 `0`(꺼짐)으로 설정되어 있습니다. 기본적으로 이 `rds.force_ssl` 파라미터는 PostgreSQL 버전 15 이상의 메이저 버전을 사용하는 DB 인스턴스의 경우 `1`(켜짐)으로 설정되어 있습니다. `rds.force_ssl` 파라미터가 `1`(켜짐)로 설정된 경우 클라이언트는 연결 시 SSL/TLS를 사용해야 합니다. 파라미터 그룹에 대한 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 단원을 참조하십시오.

RDS PostgreSQL 버전 9.5 이상 메이저 버전을 사용 중이고 `rds.force_ssl`이 `1`(켜짐)로 설정되어 있지 않으면 SSL을 사용하여 연결을 확인하도록 `pg_stat_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`가 `verify-ca` 또는 `verify-full`로 설정된 `PGSSLMODE` 환경 변수로 인증서를 확인하세요.

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

`sslrootcert` 인수를 사용해 `sslmode`, `verify-ca` 또는 `verify-full`로 설정된 연결 문자열 형식의 `sslmode`로 인증서를 확인하세요.

```
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를 사용하여 DB 인스턴스 또는 클러스터 에 대한 연결 암호화](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 인증서를 사용하도록 업데이트할 수 있습니다. 지침은 [DB 인스턴스또는 클러스터를 수정하여 CA 인증서 업데이트](UsingWithRDS.SSL-certificate-rotation.md#UsingWithRDS.SSL-certificate-rotation-updating)의 3단계를 참조하십시오.

# Amazon RDS for PostgreSQL과 함께 Kerberos 인증 사용
<a name="postgresql-kerberos"></a>

사용자가 PostgreSQL이 실행되는 DB 인스턴스에 연결할 때 Kerberos를 사용하여 사용자를 인증할 수 있습니다. 이를 위해서는 Kerberos 인증을 위한 AWS Directory Service for Microsoft Active Directory를 사용하도록 인스턴스를 구성해야 합니다. 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 디렉터리를 만듭니다. 그런 다음 PostgreSQL DB 인스턴스에 Active Directory의 도메인 및 기타 정보를 제공합니다. PostgreSQL DB 인스턴스에 대해 사용자가 인증될 때 AWS Managed Microsoft AD 디렉터리에 인증 요청이 전달됩니다.

모든 자격 증명을 동일한 디렉터리에 보관하면 시간과 노력을 절약할 수 있습니다. 여러 DB 인스턴스에 대한 자격 증명을 보관하고 관리할 수 있는 중앙 집중식 공간이 있습니다. 디렉터리를 사용하면 전체 보안 프로필을 향상할 수도 있습니다.

자체 온프레미스 Microsoft Active Directory에서 자격 증명에 액세스할 수도 있습니다. 이렇게 하려면 AWS Managed Microsoft AD 디렉터리가 온프레미스 Microsoft Active Directory를 신뢰하도록 신뢰 도메인 관계를 만듭니다. 그러면 사용자가 온프레미스 네트워크에서 워크로드에 액세스할 때와 동일한 Windows SSO(Single Sign-On) 환경을 사용하여 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 DB 인스턴스에 대한 Kerberos 인증 개요](#postgresql-kerberos-overview)
+ [PostgreSQL DB 인스턴스에 대해 Kerberos 인증 설정](postgresql-kerberos-setting-up.md)
+ [Active Directory 도메인에서 RDS for PostgreSQL DB 인스턴스 관리](postgresql-kerberos-managing.md)
+ [Kerberos 인증을 사용하여 PostgreSQL 연결](postgresql-kerberos-connecting.md)

## 리전 및 버전 사용 가능 여부
<a name="postgresql-kerberos.RegionVersionAvailability"></a>

기능 가용성 및 해당 지원은 각 데이터베이스 엔진의 특정 버전 및 AWS 리전에 따라 다릅니다. Kerberos 인증을 사용하는 PostgreSQL용 RDS의 버전 및 리전 가용성에 대한 자세한 내용은 [Amazon RDS에서 Kerberos 인증을 지원하는 리전 및 DB 엔진](Concepts.RDS_Fea_Regions_DB-eng.Feature.KerberosAuthentication.md) 섹션을 참조하십시오.

## PostgreSQL DB 인스턴스에 대한 Kerberos 인증 개요
<a name="postgresql-kerberos-overview"></a>

PostgreSQL DB 인스턴스에 대해 Kerberos 인증을 설정하려면 다음 단계(나중에 자세히 설명함)를 수행하십시오.

1. AWS Managed Microsoft AD를 사용하여 AWS Managed Microsoft AD 디렉터리를 생성합니다. AWS Management Console, AWS CLI 또는 Directory Service API를 사용하여 디렉터리를 생성할 수 있습니다. 디렉터리가 인스턴스와 통신할 수 있도록 디렉터리 보안 그룹에서 관련 아웃바운드 포트를 열어야 합니다.

1. AWS Managed Microsoft AD 디렉터리에 호출할 수 있는 Amazon RDS 액세스를 제공하는 역할을 생성합니다. 이를 위해 관리형 IAM 정책 `AmazonRDSDirectoryServiceAccess`를 사용하는 AWS Identity and Access Management(IAM) 역할을 생성합니다.

   IAM 역할이 액세스를 허용하게 하려면 올바른 AWS Security Token Service 리전에서 AWS STS 계정의 AWS(AWS) 엔드포인트를 활성화해야 합니다. 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. 디렉터리와 DB 인스턴스를 다른 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 DB 인스턴스를 생성하거나 수정합니다.
   + [Amazon RDS DB 인스턴스 생성](USER_CreateDBInstance.md) 
   + [Amazon RDS DB 인스턴스 수정](Overview.DBInstance.Modifying.md) 
   + [DB 인스턴스 복원](USER_RestoreFromSnapshot.md)
   + [Amazon RDS에서 DB 인스턴스를 지정된 시간으로 복원](USER_PIT.md)

   디렉터리와 동일한 Amazon Virtual Private Cloud(VPC) 또는 다른 AWS 계정이나 VPC에 인스턴스를 배치할 수 있습니다. PostgreSQL DB 인스턴스를 생성하거나 수정할 때는 다음을 수행합니다.
   + 디렉터리를 만들 때 생성된 도메인 식별자(`d-*` 식별자)를 제공합니다.
   + 생성한 IAM 역할의 이름을 제공합니다.
   + DB 인스턴스의 보안 그룹이 디렉터리의 보안 그룹에서 인바운드 트래픽을 수신할 수 있는지 확인합니다.

1. RDS 마스터 사용자 자격 증명을 사용하여 PostgreSQL DB 인스턴스에 연결합니다. 외부에서 식별할 사용자를 PostgreSQL에서 생성합니다. 외부에서 식별되는 사용자는 Kerberos 인증을 사용하여 PostgreSQL DB 인스턴스에 로그인할 수 있습니다.

# PostgreSQL DB 인스턴스에 대해 Kerberos 인증 설정
<a name="postgresql-kerberos-setting-up"></a>

AWS Directory Service for Microsoft Active Directory(AWS Managed Microsoft AD)를 사용하여 PostgreSQL DB 인스턴스에 대해 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가 Directory Service에 액세스할 수 있는 IAM 역할 생성](#postgresql-kerberos-setting-up.CreateIAMRole)
+ [4단계: 사용자 생성 및 구성](#postgresql-kerberos-setting-up.create-users)
+ [5단계: 디렉터리와 DB 인스턴스 사이에 VPC 간 트래픽 활성화](#postgresql-kerberos-setting-up.vpc-peering)
+ [6단계: PostgreSQL DB 인스턴스 생성 또는 수정](#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 클라우드에서 완전 관리형 Microsoft Active Directory를 생성합니다. AWS Managed Microsoft AD 디렉터리를 생성할 때 Directory Service에서 두 개의 도메인 컨트롤러와 DNS 서버가 자동으로 생성됩니다. 디렉터리 서버는 VPC 내 다른 서브넷에서 생성됩니다. 이러한 중복으로 인해 장애가 발생해도 디렉터리에 액세스할 수 있습니다.

 AWS Managed Microsoft AD 디렉터리를 생성할 때 AWS Directory Service에서 다음 작업을 자동으로 수행합니다.
+ VPC 내에서 Active Directory를 설정합니다.
+ 사용자 이름 `Admin` 과 지정된 암호를 사용하여 디렉터리 관리자 계정을 생성합니다. 이 계정을 사용하여 디렉터리를 관리할 수 있습니다.
**중요**  
반드시 이 암호를 저장해야 합니다. Directory Service에서는 이 암호를 저장하지 않으므로 암호를 검색하거나 다시 설정할 수 없습니다.
+ 디렉터리 컨트롤러에 대한 보안 그룹을 만듭니다. 보안 그룹이 PostgreSQL DB 인스턴스와의 통신을 허용해야 합니다.

AWS Directory Service for Microsoft Active Directory를 시작하면 AWS가 모든 디렉터리의 객체를 포함하는 OU(조직 단위)를 생성합니다. 디렉터리를 만들 때 입력한 NetBIOS 이름이 있는 이 OU는 도메인 루트에 있습니다. 도메인 루트는 AWS에서 소유하고 관리합니다.

 `Admin` 디렉터리를 사용하여 생성한 AWS Managed Microsoft AD 계정은 OU의 가장 일반적인 관리 활동에 대한 권한이 있습니다.
+ 사용자 생성, 업데이트 또는 삭제
+ 도메인(예: 파일 또는 인쇄 서버)에 리소스를 추가한 다음 OU 내의 사용자에 해당 리소스에 대한 권한 할당 
+ 추가 OU 및 컨테이너 생성 
+ 권한 위임 
+ Active Directory 휴지통에서 삭제된 객체 복원 
+ Active Directory 웹 서비스에서 Active Directory 및 Windows PowerShell에 대한 DNS(Domain Name Service) 모듈 실행 

또한 `Admin` 계정은 다음 도메인 차원 활동을 수행할 권한이 있습니다.
+ DNS 구성 관리(레코드, 영역 및 전달자 추가, 제거 또는 업데이트) 
+ DNS 이벤트 로그 보기 
+ 보안 이벤트 로그 보기 

**AWS Managed Microsoft AD으로 디렉터리를 생성하려면**

1.  [Directory Service 콘솔](https://console.aws.amazon.com/directoryservicev2/) 탐색 창에서 **디렉터리**를 선택한 후 **디렉터리 설정**을 선택합니다.

1. **AWS Managed Microsoft AD**를 선택합니다. AWS Managed Microsoft AD는 현재 Amazon RDS에서 사용하도록 지원되는 유일한 옵션입니다.

1. [**Next**]를 선택합니다.

1. **디렉터리 정보 입력** 페이지에서 다음 정보를 제공합니다.  
**Edition**  
 요구 사항에 맞는 에디션을 선택합니다.  
**디렉터리 DNS 이름**  
 디렉터리를 위한 정규화된 이름(예: **corp.example.com**)입니다.  
**디렉터리 NetBIOS 이름**  
 디렉터리의 선택적 짧은 이름(예: `CORP`)입니다.  
**디렉터리 설명**  
 디렉터리에 대한 선택적 설명을 입력합니다.  
**관리자 암호**  
 디렉터리 관리자의 암호입니다. 디렉터리 생성 프로세스에서는 사용자 이름 `Admin`와 이 암호를 사용하여 관리자 계정을 생성합니다.  
 디렉터리 관리자 암호는 "admin"이라는 단어를 포함할 수 없습니다. 암호는 대소문자를 구분하며 길이가 8\$164자 사이여야 합니다. 또한 다음 네 범주 중 세 개에 해당하는 문자를 1자 이상 포함해야 합니다.  
   +  소문자(a–z) 
   +  대문자(A–Z) 
   +  숫자(0–9) 
   +  영숫자 외의 특수 문자(\$1\$1@\$1\$1%^&\$1\$1-\$1=`\$1\$1()\$1\$1[]:;"'<>,.?/)   
**[Confirm Password]**  
 관리자 암호를 다시 입력합니다.  
반드시 이 암호를 저장해야 합니다. Directory Service에서는 이 암호를 저장하지 않으며 암호를 검색하거나 재설정할 수 없습니다.

1. **Next**(다음)를 선택합니다.

1. **Choose VPC and subnets(VPC 및 서브넷 선택)** 페이지에 다음 정보를 입력합니다.  
**VPC**  
디렉터리에 대한 VPC를 선택합니다. PostgreSQL DB 인스턴스는 이와 동일한 VPC 또는 다른 VPC에서 생성할 수 있습니다.  
**서브넷**  
 디렉터리 서버에 대한 서브넷을 선택합니다. 두 서브넷이 서로 다른 가용 영역에 있어야 합니다.

1. **Next**(다음)를 선택합니다.

1.  디렉터리 정보를 검토합니다. 변경이 필요하면 **이전**을 선택하여 변경합니다. 정보가 올바르면 **Create directory(디렉터리 생성)**을 선택합니다.  
![\[디렉터리 세부 정보 페이지\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/WinAuth2.png)

 디렉터리를 생성하는 데 몇 분 정도 걸립니다. 디렉터리가 성공적으로 생성되면 **상태** 값이 **활성**으로 변경됩니다.

 디렉터리에 대한 정보를 보려면 디렉터리 목록에서 해당 디렉터리 ID를 선택합니다. **디렉터리 ID** 값을 적어 두십시오. PostgreSQL DB 인스턴스를 생성하거나 수정할 때 이 값이 필요합니다.

![\[세부 정보 페이지 이미지\]](http://docs.aws.amazon.com/ko_kr/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가 Directory Service에 액세스할 수 있는 IAM 역할 생성](#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) 디렉터리 간에 forest trust를 사용하여 신뢰 도메인 관계를 생성해야 합니다. 신뢰는 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 클라이언트에서 rds.amazonaws.com 대신 엔드포인트에 있는 Directory Service의 도메인 이름을 사용하여 연결합니다. 자세한 내용은 [Kerberos 인증을 사용하여 PostgreSQL 연결](postgresql-kerberos-connecting.md)를 참조하세요.

온프레미스 Microsoft Active Directory 도메인 이름에 새로 만든 신뢰 관계에 해당하는 DNS 접미사 라우팅이 포함되어 있는지 확인합니다. 다음 스크린샷은 예를 보여줍니다.

![\[DNS 라우팅이 생성된 신뢰에 대응\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/kerberos-auth-trust.png)


## 3단계: Amazon RDS가 Directory Service에 액세스할 수 있는 IAM 역할 생성
<a name="postgresql-kerberos-setting-up.CreateIAMRole"></a>

Directory Service를 호출하는 Amazon RDS의 경우 AWS 계정에 관리형 IAM 정책 `AmazonRDSDirectoryServiceAccess`를 사용하는 IAM 역할이 필요합니다. 이 역할을 사용하여 Amazon RDS에서 Directory Service를 호출할 수 있습니다. 

AWS Management Console을 사용하여 DB 인스턴스를 생성할 때 콘솔 사용자에게 `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 Users and Computers 도구를 사용하여 사용자를 생성할 수 있습니다. 이 도구는 Active Directory 도메인 서비스 및 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)를 참조하세요. 이 경우 사용자는 도메인에 속하며 디렉터리에서 ID가 유지되는 개인 또는 기타 엔터티(예: 사용자의 컴퓨터)입니다.

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단계: 디렉터리와 DB 인스턴스 사이에 VPC 간 트래픽 활성화
<a name="postgresql-kerberos-setting-up.vpc-peering"></a>

디렉터리와 DB 인스턴스를 동일한 VPC에 배치하려면 이 단계를 건너뛰고 [6단계: PostgreSQL DB 인스턴스 생성 또는 수정](#postgresql-kerberos-setting-up.create-modify) 단원으로 이동하십시오.

디렉터리와 DB 인스턴스를 서로 다른 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. DB 인스턴스의 보안 그룹이 디렉터리의 보안 그룹에서 인바운드 트래픽을 수신할 수 있는지 확인합니다.

1. 트래픽을 차단하는 네트워크 ACL(액세스 제어 목록) 규칙이 없어야 합니다.

다른 AWS 계정이 디렉터리를 소유하는 경우 디렉터리를 공유해야 합니다.

**AWS 계정 간에 디렉터리를 공유하려면**

1. *AWS 관리 안내서*의 [자습서: 원활한 EC2 도메인 조인을 위해 AWS Managed Microsoft AD 디렉터리 공유](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/ms_ad_tutorial_directory_sharing.html)에 있는 지침에 따라 DB 인스턴스가 생성될 Directory Service 계정과 디렉터리를 공유하는 작업을 시작합니다.

1. DB 인스턴스용 계정을 사용하여 Directory Service 콘솔에 로그인하고 계속하기 전에 도메인이 `SHARED` 상태가 되었는지 확인합니다.

1. DB 인스턴스용 계정을 사용하여 Directory Service 콘솔에 로그인하는 동안 **디렉터리 ID** 값을 기록해 둡니다. 이 디렉터리 ID를 사용하여 DB 인스턴스를 도메인에 조인합니다.

## 6단계: PostgreSQL DB 인스턴스 생성 또는 수정
<a name="postgresql-kerberos-setting-up.create-modify"></a>

디렉터리에서 사용할 PostgreSQL DB 인스턴스를 생성하거나 수정합니다. 콘솔, CLI 또는 RDS API를 사용하여 DB 인스턴스를 디렉터리에 연결할 수 있습니다. 이 작업을 다음 중 한 가지 방법으로 수행할 수 있습니다.
+  콘솔, [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 DB 인스턴스를 생성합니다. 지침은 [Amazon RDS DB 인스턴스 생성](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 DB 인스턴스를 수정합니다. 지침은 [Amazon RDS DB 인스턴스 수정](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 작업을 사용하여 DB 스냅샷에서 PostgreSQL DB 인스턴스를 복원합니다. 지침은 [DB 인스턴스 복원](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 DB 인스턴스를 특정 시점으로 복원합니다. 지침은 [Amazon RDS에서 DB 인스턴스를 지정된 시간으로 복원](USER_PIT.md) 섹션을 참조하세요.

Kerberos 인증은 VPC의 PostgreSQL DB 인스턴스에 대해서만 지원됩니다. DB 인스턴스는 디렉터리와 동일한 VPC 또는 다른 VPC에 있을 수 있습니다. DB 인스턴스가 디렉터리와 통신할 수 있도록 DB 인스턴스는 디렉터리의 VPC 내 수신 및 송신을 허용하는 보안 그룹을 사용해야 합니다.

### 콘솔
<a name="postgresql-kerberos-setting-up.create-modify.Console"></a>

콘솔을 사용하여 DB 인스턴스를 생성, 수정 또는 복원하는 경우 [**데이터베이스 인증(Database authentication)**] 섹션에서 [**암호 및 Kerberos 인증(Password and Kerberos authentication)**]을 선택합니다. 그런 다음 [**디렉터리 찾아보기(Browse Directory)**]를 선택합니다. 디렉터리를 선택하거나 [**새 디렉토리 생성(Create a new directory)**]을 클릭하여 Directory Service를 사용합니다.

![\[인증을 위해 Kerberos 선택 및 사용할 디렉토리 식별.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/rpg-authentication-use-kerberos.png)


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

AWS CLI를 사용하는 경우 생성한 디렉터리를 DB 인스턴스에서 사용하려면 다음과 같은 파라미터가 필요합니다.
+ `--domain` 파라미터의 경우 디렉터리를 만들 때 생성된 도메인 식별자("d-\$1" 식별자)를 사용하십시오.
+ `--domain-iam-role-name` 파라미터의 경우 귀하가 생성한, 관리형 IAM 정책 `AmazonRDSDirectoryServiceAccess`를 사용하는 역할을 사용하십시오.

예를 들어, 다음 CLI 명령은 디렉터리를 사용하도록 DB 인스턴스를 수정합니다.

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

**중요**  
DB 인스턴스를 수정하여 Kerberos 인증을 사용 설정하는 경우 변경 후 DB 인스턴스를 재부팅합니다.

## 7단계: Kerberos 보안 주체를 위한 PostgreSQL 사용자 생성
<a name="postgresql-kerberos-setting-up.create-logins"></a>

이때 RDS for PostgreSQL DB 인스턴스가 AWS Managed Microsoft AD 도메인에 조인됩니다. [4단계: 사용자 생성 및 구성](#postgresql-kerberos-setting-up.create-users)에서 디렉터리에서 생성한 사용자는 PostgreSQL 데이터베이스 사용자로 설정하고 데이터베이스에 로그인할 수 있는 권한을 부여해야 합니다. `rds_superuser` 권한이 있는 데이터베이스 사용자로 로그인하면 됩니다. 예를 들어 , RDS for PostgreSQL DB 인스턴스를 생성할 때 기본값을 수락한 경우 다음 단계에 표시된 대로 `postgres`를 사용합니다.

**Kerberos 보안 주체를 위한 PostgreSQL 데이터베이스 사용자를 생성하는 방법**

1. `psql`을 사용하여 의 RDS for PostgreSQL DB 인스턴스 엔드포인트에 연결합니다. 다음 예에서는 `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 인스턴스에 정의된 표준 사용자 이름(ID), 즉 해당 사용자 이름에 대한 Active Directory 도메인의 소문자 `alias`(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 사용자 ID에 대한 모든 PostgreSQL 사용자 생성을 완료하면 사용자는 Kerberos 보안 인증 정보를 사용하여 RDS for PostgreSQL DB 인스턴스에 액세스할 수 있습니다.

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 및 Directory Service용 포트 88 및 464를 포함하는 Kerberos의 TCP/UDP를 통한 트래픽을 확인합니다.
+ 데이터베이스 포트를 통해 클라이언트 호스트와 DB 인스턴스 간에 트래픽이 흐를 수 있는지 확인합니다. 예를 들어, 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 DB 인스턴스 관리
<a name="postgresql-kerberos-managing"></a>

콘솔, CLI 또는 RDS API를 사용하여 DB 인스턴스 및 Microsoft Active Directory와의 관계를 관리할 수 있습니다. 예를 들어, Active Directory를 연결하여 Kerberos 인증을 활성화할 수 있습니다. 또한 Active Directory 연결을 제거하여 Kerberos 인증을 비활성화할 수 있습니다. 또한 DB 인스턴스를 이동하여 한 Microsoft Active Directory에서 다른 Microsoft Active Directory로 외부적으로 인증해 줄 수 있습니다.

예를 들어 CLI를 사용하여 다음 작업을 수행할 수 있습니다.
+ 실패한 멤버십에 대한 Kerberos 인증 활성화를 다시 시도하려면 [modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) CLI 명령을 사용합니다. `--domain` 옵션에 대해 현재 멤버십의 디렉터리 ID를 지정합니다.
+ DB 인스턴스에서 Kerberos 인증을 비활성화하려면 [modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) CLI 명령을 사용합니다. `none` 옵션의 경우 `--domain`을 지정합니다.
+ 한 도메인에서 다른 도메인으로 DB 인스턴스를 이동하려면 [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>

DB 인스턴스를 생성하거나 수정하면 멤버가 됩니다. 콘솔에서 또는 [describe-db-instances](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-instances.html) CLI 명령을 실행하여 도메인 멤버십의 상태를 확인할 수 있습니다. DB 인스턴스의 상태는 다음 중 한 가지가 될 수 있습니다.
+ `kerberos-enabled` - DB 인스턴스에 Kerberos 인증이 활성화되어 있습니다.
+ `enabling-kerberos` - AWS에서 이 DB 인스턴스에 대한 Kerberos 인증 활성화를 진행 중입니다.
+ `pending-enable-kerberos` - 이 DB 인스턴스에 대한 Kerberos 인증 활성화가 보류 중입니다.
+ `pending-maintenance-enable-kerberos` - AWS에서 예약된 다음 유지 관리 기간에 DB 인스턴스에 대한 Kerberos 인증을 활성화하려 합니다.
+ `pending-disable-kerberos` - 이 DB 인스턴스에 대한 Kerberos 인증 비활성화가 보류 중입니다.
+ `pending-maintenance-disable-kerberos` - AWS에서 예약된 다음 유지 관리 기간에 DB 인스턴스에 대한 Kerberos 인증을 비활성화하려 합니다.
+ `enable-kerberos-failed` - 구성 문제로 인해 AWS가 DB 인스턴스에 대해 Kerberos 인증을 활성화하지 못했습니다. DB 인스턴스 수정 명령을 다시 실행하기 전에 구성 문제를 해결하십시오.
+ `disabling-kerberos` - AWS에서 이 DB 인스턴스에 대한 Kerberos 인증 비활성화를 진행 중입니다.

네트워크 연결 문제 또는 잘못된 IAM 역할로 인해 Kerberos 인증 활성화 요청이 실패할 수 있습니다. 경우에 따라 DB 인스턴스를 생성하거나 수정할 때 Kerberos 인증을 사용하려고 하면 실패할 수 있습니다. 이런 경우 올바른 IAM 역할을 사용하고 있는지 확인한 다음 도메인에 조인하도록 DB 인스턴스를 수정합니다.

**참고**  
RDS for PostgreSQL을 사용한 Kerberos 인증에서만 트래픽을 도메인의 DNS 서버로 전송합니다. 다른 모든 DNS 요청은 PostgreSQL을 실행 중인 DB 인스턴스에서 아웃바운드 네트워크 액세스로 취급됩니다. RDS for PostgreSQL을 사용한 아웃바운드 네트워크 액세스에 대한 자세한 내용은 [아웃바운드 네트워크 액세스에 사용자 지정 DNS 서버 사용](Appendix.PostgreSQL.CommonDBATasks.CustomDNS.md) 단원을 참조하십시오.

# Kerberos 인증을 사용하여 PostgreSQL 연결
<a name="postgresql-kerberos-connecting"></a>

pgAdmin 인터페이스 또는 psql과 같은 명령줄 인터페이스를 사용하여 Kerberos 인증으로 PostgreSQL에 연결할 수 있습니다. 연결에 대한 자세한 내용은 [PostgreSQL 데이터베이스 엔진을 실행하는 DB 인스턴스에 연결](USER_ConnectToPostgreSQLInstance.md) 섹션을 참조하세요. 연결에 필요한 엔드포인트, 포트 번호 및 기타 세부 정보를 얻는 방법에 대한 자세한 내용은 [PostgreSQL DB 인스턴스에 연결](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. **생성 - 서버** 대화 상자에서 pgAdmin의 서버를 식별하기 위해 **일반** 탭에 이름을 입력합니다.

1. **연결** 탭에서 RDS for PostgreSQL 데이터베이스에 있는 다음 정보를 입력합니다.
   + **호스트**의 경우 에 대한 엔드포인트를 입력합니다. RDS for PostgreSQL DB 인스턴스  엔드포인트는 다음과 유사하게 표시됩니다.

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

     Windows 클라이언트에서 온-프레미스 Microsoft Active Directory에 연결하려면 호스트 엔드포인트의 `rds.amazonaws.com` 대신 AWS Managed Active Directory의 도메인 이름을 사용합니다. 예를 들어 AWS Managed Active Directory의 도메인 이름이 `corp.example.com`일 경우 그런 다음**호스트**에서는 엔드포인트가 다음과 같이 지정됩니다.

     ```
     RDS-DB-instance.111122223333.aws-region.corp.example.com
     ```
   + **포트**에 할당된 포트를 입력합니다.
   + **Maintenance database(유지 관리 데이터베이스)**에 클라이언트가 연결될 초기 데이터베이스의 이름을 입력합니다.
   + **Username(사용자 이름)**에 [7단계: Kerberos 보안 주체를 위한 PostgreSQL 사용자 생성](postgresql-kerberos-setting-up.md#postgresql-kerberos-setting-up.create-logins)의 Kerberos 인증을 위해 입력했던 사용자 이름을 입력합니다.

1. **저장**을 선택합니다.

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

psql을 사용하여 Kerberos 인증으로 PostgreSQL에 연결하려면 다음 단계를 수행하십시오.

1. 명령 프롬프트에서 다음 명령을 실행합니다.

   ```
   kinit username                
   ```

   *`username`*을 사용자 이름으로 대체합니다. 프롬프트에서 Microsoft Active Directory에 저장된 사용자 암호를 입력합니다.

1. PostgreSQL DB 인스턴스가 공개적으로 액세스 가능한 VPC를 사용하는 경우 DB 인스턴스 엔드포인트의 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를 사용하는 경우 특수 엔드포인트를 사용하여 연결해야 합니다. 호스트 엔드포인트에서 Amazon 도메인 `rds.amazonaws.com`을 사용하는 대신 AWS Managed Active Directory의 도메인 이름을 사용합니다.

   예를 들어 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 DB 인스턴스에 로그인합니다. 

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

   온프레미스 Active Directory를 사용하여 Windows 클러스터에서 PostgreSQL DB 클러스터에 로그인하려면 이전 단계의 도메인 이름(`corp.example.com`)과 함께 다음 psql 명령을 사용합니다.

   ```
   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은 DB 인스턴스에서 아웃바운드 네트워크 액세스를 지원하고, 고객이 소유한 사용자 정의 DNS 서버에서의 DNS(Domain Name Service) 확인을 허용합니다. 사용자 지정 DNS 서버를 통해 RDS for PostgreSQL DB 인스턴스에서 전체 주소 도메인 이름만을 확인할 수 있습니다.

**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 해결을 활성화하려면, 먼저 사용자 지정 DB 파라미터 그룹을 RDS for PostgreSQL 인스턴스에 연결합니다. 그런 다음 `rds.custom_dns_resolution` 파라미터를 1로 설정하여 변경 사항이 적용되도록 DB 인스턴스를 다시 시작합니다.

## 사용자 지정 DNS 해결 비활성화
<a name="Appendix.PostgreSQL.CommonDBATasks.CustomDNS.Disable"></a>

고객 VPC에서 DNS 해결을 비활성화하려면, 먼저 사용자 지정 DB 파라미터 그룹을 0으로 설정하여 `rds.custom_dns_resolution`을 비활성화합니다. 변경 사항이 적용되도록 DB 인스턴스를 다시 시작합니다.

## 사용자 지정 DNS 서버 설정
<a name="Appendix.Oracle.CommonDBATasks.CustomDNS.Setup"></a>

사용자 지정 DNS 이름 서버를 설정한 후 변경 사항이 DB 인스턴스에 전파되는 데 최대 30분이 걸립니다. 변경 사항이 DB 인스턴스에 전파된 후 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 DB 인스턴스의 사용자 지정 DNS 서버 설정**

1. VPC에 연결된 동적 호스트 구성 프로토콜(DHCP) 옵션 세트에서 DNS 이름 서버의 IP 주소에 대해 `domain-name-servers` 옵션을 설정합니다. 자세한 내용은 [DHCP 옵션 세트](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_DHCP_Options.html) 단원을 참조하세요.
**참고**  
`domain-name-servers` 옵션은 최대 4개의 값을 받아들이지만 Amazon RDS DB 인스턴스는 첫 번째 값만을 사용합니다.

1. DNS 서버가 DNS 이름, Amazon EC2 프라이빗 DNS 이름, 고객별 DNS 이름을 비롯한 모든 조회 쿼리를 확인할 수 있는지 확인합니다. 아웃바운드 네트워크 트래픽에 DNS 서버가 처리할 수 없는 DNS 조회가 포함된 경우, DNS 서버에 적절한 업스트림 DNS 공급자가 구성되어 있어야 합니다.

1. 512바이트 이하의 UDP(User Datagram Protocol) 응답을 생성하도록 DNS 서버를 구성하세요.

1. 1,024바이트 이하의 TCP(Transmission Control Protocol) 응답을 생성하도록 DNS 서버를 구성하세요.

1. 포트 53을 통한 Amazon RDS DB 인스턴스로부터의 인바운드 트래픽을 허용하도록 DNS 서버를 구성하세요. 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. 포트 53을 통한 아웃바운드 트래픽을 허용하도록 Amazon RDS DB 인스턴스의 VPC를 구성하세요. 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 DB 인스턴스와 DNS 서버 간 라우팅 경로가 DNS 트래픽을 허용하도록 올바로 구성되는지 확인하세요.

   또한 Amazon RDS DB 인스턴스와 DNS 서버가 같은 VPC에 있지 않은 경우, 그 사이에 피어링 연결을 구축해야 합니다. 자세한 내용은 *Amazon VPC Peering Guide*의 [VPC 피어링이란?](https://docs.aws.amazon.com/vpc/latest/peering/Welcome.html)을 참조하세요.

# RDS for PostgreSQL DB 엔진 업그레이드
<a name="USER_UpgradeDBInstance.PostgreSQL"></a>

PostgreSQL 데이터베이스에서 관리할 수 있는 업그레이드 유형은 다음과 같이 2가지입니다.
+ 운영 체제 업데이트 – 경우에 따라 보안 수정 사항이나 OS 변경 사항을 적용하기 위해 Amazon RDS에서 데이터베이스의 기본 운영 체제를 업데이트해야 할 수 있습니다. RDS 콘솔, AWS Command Line Interface(AWS CLI) 또는 RDS API를 사용하여 Amazon RDS에서 OS 업데이트를 적용하는 시기를 결정할 수 있습니다. OS 업데이트에 대한 자세한 내용은 다음단원을 참조하십시오. [DB 인스턴스 에 업데이트 적용](USER_UpgradeDBInstance.Maintenance.md#USER_UpgradeDBInstance.OSUpgrades) 
+  데이터베이스 엔진 업그레이드 – Amazon RDS에서 새 버전의 데이터베이스 엔진이 지원되면 데이터베이스를 새 버전으로 업그레이드할 수 있습니다.

컨텍스트에 포함된 데이터베이스는 RDS for PostgreSQL DB 인스턴스 또는 다중 AZ DB 클러스터입니다.**

PostgreSQL 데이터베이스의 엔진 업그레이드에는 메이저 버전 업그레이드와 마이너 버전 업그레이드라는 2가지 종류가 있습니다.

**메이저 버전 업그레이드**  
*메이저 버전 업그레이드*에는 기존 애플리케이션과 호환되지 않는 데이터베이스 변경 사항이 포함될 수 있습니다. 따라서 데이터베이스의 메이저 버전 업그레이드를 수동으로 수행해야 합니다. DB 인스턴스 또는 다중 AZ DB 클러스터를 수정하여 메이저 버전 업그레이드를 시작할 수 있습니다. 메이저 버전 업그레이드를 수행하기 전에 [RDS for PostgreSQL 업그레이드에 대한 메이저 버전 선택](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.md)에 설명된 단계를 수행하는 것이 좋습니다.  
Amazon RDS는 다음과 같은 방법으로 다중 AZ 메이저 버전 업그레이드를 처리합니다.  
+ **다중 AZ DB 인스턴스 배포** - Amazon RDS가 기본 인스턴스와 대기 인스턴스를 동시에 업그레이드합니다. 업그레이드가 완료되는 동안 데이터베이스를 몇 분간 사용하지 못할 수 있습니다.
+ **다중 AZ DB 클러스터 배포** - Amazon RDS가 리더 인스턴스와 라이터 인스턴스를 동시에 업그레이드합니다. 업그레이드가 완료되는 동안 데이터베이스를 몇 분간 사용하지 못할 수 있습니다.
리전 내 읽기 전용 복제본이 있는 DB 인스턴스를 업그레이드하는 경우 Amazon RDS는 기본 DB 인스턴스와 함께 복제본을 업그레이드합니다.  
Amazon RDS는 다중 AZ DB 클러스터 읽기 전용 복제본은 업그레이드하지 않습니다. 다중 AZ DB 클러스터의 메이저 버전 업그레이드를 수행하면 읽기 복제본의 복제 상태가 **종료**로 변경됩니다. 업그레이드가 완료된 후 읽기 전용 복제본은 수동으로 삭제하고 다시 생성해야 합니다.  
블루/그린 배포를 사용하면 메이저 버전 업그레이드에 필요한 다운타임을 최소화할 수 있습니다. 자세한 내용은 [데이터베이스 업데이트에 Amazon RDS 블루/그린 배포 사용](blue-green-deployments.md) 섹션을 참조하세요.

**마이너 버전 업그레이드**  
반대로 *마이너 버전 업그레이드*에는 기존 애플리케이션과 호환되는 변경 사항만 포함됩니다. 데이터베이스를 수정하여 마이너 버전 업그레이드를 수동으로 시작할 수 있습니다. 또는 데이터베이스를 생성하거나 수정할 때 **마이너 버전 자동 업그레이드** 옵션을 활성화할 수 있습니다. 이렇게 하면 Amazon RDS에서 새 버전을 테스트 및 승인한 후 인스턴스가 자동으로 업그레이드됩니다.  
Amazon RDS는 다음과 같은 방법으로 다중 AZ 마이너 버전 업그레이드를 처리합니다.  
+ **다중 AZ DB 인스턴스 배포** - Amazon RDS가 기본 인스턴스와 대기 인스턴스를 동시에 업그레이드합니다. 업그레이드가 완료되는 동안 데이터베이스를 몇 분간 사용하지 못할 수 있습니다.
+ **다중 AZ DB 클러스터 배포** - Amazon RDS가 리더 DB 인스턴스를 한 번에 하나씩 업그레이드합니다. 그러면 리더 DB 인스턴스가 새 라이터 DB 인스턴스로 전환됩니다. 그러면 Amazon RDS가 이전 라이터 인스턴스(현재는 리더 인스턴스)를 업그레이드합니다. 다중 AZ DB 클러스터는 일반적으로 마이너 버전 업그레이드의 가동 중지 시간을 약 35초로 줄입니다. RDS 프록시와 함께 사용하면 가동 중지 시간을 1초 이하로 더 줄일 수 있습니다. 자세한 내용은 [ Amazon RDS Proxy](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 고급 JDBC 래퍼 드라이버](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 FAQ의 [데이터베이스 엔진 버전](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 설명서](https://www.postgresql.org/docs/current/pgupgrade.html)에 설명된 `pg_upgrade` 유틸리티를 사용합니다.

백업 보존 기간이 0보다 큰 경우 업그레이드 프로세스 중에 Amazon RDS가 두 개의 DB 스냅샷을 생성합니다. 첫 번째 DB 스냅샷은 업그레이드 변경 이전 데이터베이스의 스냅샷입니다. 데이터베이스의 업그레이드가 완료되지 않으면 이 스냅샷을 복구하여 기존 버전을 실행하는 데이터베이스를 생성할 수 있습니다. 두 번째 DB 스냅샷은 업그레이드 완료 이후에 캡처됩니다. 이러한 DB 스냅샷은 백업 보존 기간이 만료되면 자동으로 삭제됩니다.

**참고**  
데이터베이스에 대한 백업 보존 기간을 0보다 큰 수로 설정하는 경우에만 Amazon RDS가 업그레이드 프로세스 중에 DB 스냅샷을 캡처합니다. DB 인스턴스의 백업 보존 기간을 수정하려면 [Amazon RDS DB 인스턴스 수정](Overview.DBInstance.Modifying.md) 단원을 참조하세요. 다중 AZ DB 클러스터의 경우 사용자 지정 백업 보존 기간을 구성할 수 없습니다.

DB 인스턴스의 메이저 버전 업그레이드를 수행하면 리전 내 읽기 전용 복제본도 모두 자동으로 업그레이드됩니다. 업그레이드 워크플로가 시작된 후 읽기 전용 복제본은 기본 DB 인스턴스에서 `pg_upgrade`가 성공적으로 완료될 때까지 기다립니다. 그런 다음 프라이머리 DB 인스턴스 업그레이드는 읽기 전용 복제본 업그레이드가 완료될 때까지 기다립니다. 업그레이드가 완료될 때까지 중단이 발생합니다. 다중 AZ DB 클러스터의 메이저 버전 업그레이드를 수행하면 읽기 전용 복제본의 복제 상태가 **종료**로 변경됩니다.

업그레이드가 완료된 후에는 이전 버전의 DB 엔진으로 되돌릴 수 없습니다. 이때 이전 버전으로 되돌리려면 업그레이드 전에 캡처한 DB 스냅샷을 복원하여 새로운 데이터베이스를 생성해야 합니다.

## 유효한 업그레이드 대상 찾기
<a name="USER_UpgradeDBInstance.PostgreSQL.FindingTargets"></a>

AWS Management Console을 사용하여 데이터베이스를 업그레이드할 때 데이터베이스의 유효한 업그레이드 대상이 표시됩니다. 또한 다음 AWS CLI 명령을 사용하여 데이터베이스의 유효한 업그레이드 대상을 식별할 수 있습니다.

대상 LinuxmacOS, 또는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 명령을 실행합니다.

대상 LinuxmacOS, 또는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.*minor*에서 11.*minor*로의 업그레이드와 같이 버전 번호의 정수 부분이 증가합니다.
+ PostgreSQL 버전 10 미만의 경우 엔진 버전 번호는 *major.minor* 형식입니다. 버전 번호의 정수 부분과 첫 번째 소수 부분 모두가 메이저 엔진 버전 번호입니다. 예를 들어, 9.6이 메이저 버전입니다. 버전 번호의 세 번째 부분이 마이너 버전 번호입니다. 예를 들어, 버전 9.6.12의 경우 12가 마이너 버전 번호입니다.

  메이저 버전 업그레이드는 버전 번호의 메이저 부분이 증가합니다. 예를 들어 *9.6*.12에서 11.14로 업그레이드하는 것은 메이저 버전 업그레이드입니다. 여기서 *9.6*과 *11*이 메이저 버전 번호입니다.

RDS 추가 지원 버전 번호 지정에 대한 자세한 내용은 [Amazon RDS 추가 지원 버전 명명 규칙](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-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 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 단일 AZ DB 인스턴스 또는 다중 AZ DB 인스턴스 배포를 다음 메이저 버전으로 업그레이드하면 데이터베이스에 연결된 읽기 전용 복제본도 다음 메이저 버전으로 업그레이드됩니다. 경우에 따라 업그레이드할 때 상위 메이저 버전으로 건너뛸 수 있습니다. 업그레이드에서 메이저 버전을 건너뛰면 읽기 전용 복제본도 해당 대상 메이저 버전으로 업그레이드됩니다. 다른 메이저 버전을 건너뛰어 버전 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), [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) | 
| 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), [16.8](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version168), [16.7](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version167), [16.6](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version166), [16.5](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version165), [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.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.11](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1511), [15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510), [15.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version159), [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), [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 | [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), [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.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), [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.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), [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.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), [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) | 
| 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), [15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512), [15.11](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1511), [15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510), [15.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version159), [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), [14.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1417), [14.16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1416), [14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415), [14.14](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), [15.12](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1512), [15.11](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1511), [15.10](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1510), [15.9](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version159), [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.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.16](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1416), [14.15](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1415), [14.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1414), [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), [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 | [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), [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.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), [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.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), [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.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), [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.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1414), [14.13](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), [13.20](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1320), [13.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1319), [13.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318), [13.17](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), [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), [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.14](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1414), [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.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.19](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1319), [13.18](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1318), [13.17](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-versions.html#postgresql-versions-version1317), [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), [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-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.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.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), [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.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), [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.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. ** 버전 호환 가능 파라미터 그룹 준비** – 사용자 지정 파라미터 그룹을 사용하는 경우 두 가지 옵션이 있습니다. 새 DB 엔진 버전에 대한 기본 파라미터 그룹을 지정할 수 있습니다. 또는 새 DB 엔진 버전에 대한 사용자 지정 파라미터 그룹을 직접 만들 수도 있습니다. 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 및 [다중 AZ DB 클러스터용 DB 클러스터 파라미터 그룹 작업](USER_WorkingWithDBClusterParamGroups.md)(을)를 참조하세요.

1. **지원되지 않는 데이터베이스 클래스 확인** – 데이터베이스의 인스턴스 클래스가 업그레이드하려는 PostgreSQL 버전과 호환되는지 확인합니다. 자세한 내용은 [DB 인스턴스 클래스에 지원되는 DB 엔진](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` 열에는 `DROP DATABASE` 작업 중에 중단된 데이터베이스를 유효하지 않은 것으로 표시하는 `-2` 값이 포함되어 있습니다.

     다음 쿼리를 사용하여 잘못된 데이터베이스를 확인합니다.

     ```
     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 이상에서는, non-read-replicas의 논리적 복제 슬롯을 업그레이드 후에도 유지할 수 있습니다. 읽기 전용 복제본에서 생성된 논리적 복제 슬롯은 업그레이드를 통해 보존되지 않습니다.

   업그레이드를 시작하기 전에 슬롯에서 모든 트랜잭션 및 논리적 디코딩 메시지가 사용되었는지 확인합니다. 논리적 복제 슬롯에 유지된 소비되지 않은 미리 쓰기 로그 파일(WAL)이 있는 경우 문제 슬롯을 식별하는 메시지와 함께 업그레이드가 실패합니다. 자세한 내용은 [PostgreSQL 설명서](https://www.postgresql.org/docs/current/logical-replication-upgrade.html)를 참조하세요.

   소스 버전이 17.8 또는 18.2 이전인 다중 AZ 클러스터에서 `flow_control`가 비활성화되어 있는지 확인합니다. 자세한 내용은 [다중 AZ DB 클러스터에 대한 흐름 제어 켜기 및 끄기](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html#multi-az-db-clusters-concepts-replica-lag)를 참조하세요. `shared_preload_libraries`에서 확장을 제거하고 DB 인스턴스를 재부팅하여 흐름 제어를 해제할 수 있습니다.

1. **읽기 전용 복제본 처리** – 단일 AZ DB 인스턴스 또는 다중 AZ DB 인스턴스 배포 업그레이드에서는 기본 DB 인스턴스와 함께 리전 내 읽기 전용 복제본도 업그레이드됩니다. Amazon RDS는 다중 AZ DB 클러스터 읽기 전용 복제본은 업그레이드하지 않습니다.

   읽기 전용 복제본은 별도로 업그레이드할 수 없습니다. 가능하다 하더라도 기본 및 복제본 데이터베이스가 서로 다른 PostgreSQL 메이저 버전을 갖는 상황이 발생할 수 있습니다. 그런데 읽기 전용 복제본 업그레이드는 프라이머리 DB 인스턴스의 가동 중지 시간을 증가시킬 수 있습니다. 읽기 전용 복제본 업그레이드를 방지하려면 업그레이드 프로세스를 시작하기 전에 복제본을 독립형 인스턴스로 승격하거나 삭제합니다.

   업그레이드 과정에서 읽기 전용 복제본 인스턴스의 현재 파라미터 그룹을 기반으로 읽기 전용 복제본의 파라미터 그룹이 다시 생성됩니다. 읽기 전용 복제본을 수정하여 업그레이드가 완료된 후에만 사용자 지정 파라미터 그룹을 읽기 전용 복제본에 적용할 수 있습니다. 읽기 전용 복제본에 대한 자세한 내용은 [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)를 참조하세요.

   메이저 버전 업그레이드를 계획할 때 데이터베이스에 2,500\$13,000만 개의 대형 객체가 포함된 경우 메모리가 32GB 이상인 인스턴스 유형을 사용하는 것이 좋습니다. 이 권장 사항은 테스트를 기반으로 하며 해당 워크로드 및 데이터베이스 구성에 따라 달라질 수 있습니다. 데이터베이스에 추가 객체(예: 테이블, 인덱스 또는 구체화된 뷰)가 포함된 경우 업그레이드 프로세스 중에 최적의 성능을 보장하기 위해 더 큰 인스턴스 유형을 선택하는 것이 좋습니다.

1. **제로 ETL 통합 처리** - 기존 [제로 ETL 통합](zero-etl.md)이 있는 경우 메이저 버전 업그레이드를 수행하기 전에 [삭제](zero-etl.deleting.md)합니다. 그런 다음 업그레이드를 완료한 후 통합을 다시 만듭니다.

   소스 버전 메이저 17 이상에서는 업그레이드를 통해 제로 ETL 통합을 유지할 수 있습니다.

1. **백업 수행** – 메이저 버전 업그레이드를 하기 전에 백업을 수행하여 데이터베이스에 대해 알려진 복원 지점을 생성하는 것이 좋습니다. 백업 보존 기간이 0보다 큰 경우 업그레이드 프로세스는 업그레이드 전후에 데이터베이스의 DB 스냅샷을 생성합니다. 백업 보존 기간을 변경하려면 [Amazon RDS DB 인스턴스 수정](Overview.DBInstance.Modifying.md) 및 [Amazon RDS용 다중 AZ DB 클러스터 수정](modify-multi-az-db-cluster.md) 단원을 참조하세요.

   백업을 수동으로 수행하려면 [Amazon RDS의 단일 AZ DB 인스턴스에 대한 DB 스냅샷 생성](USER_CreateSnapshot.md) 및 [Amazon RDS용 다중 AZ DB 클러스터 스냅샷 생성](USER_CreateMultiAZDBClusterSnapshot.md) 단원을 참조하세요.

1. **메이저 버전 업그레이드 전에 특정 확장 업그레이드** – 업그레이드 시 메이저 버전을 건너뛰려면 메이저 버전 업그레이드를 수행하기 *전에* 특정 확장을 업데이트해야 합니다. 예를 들어 버전 9.5.x 또는 9.6에서 버전 11.x로 업그레이드하면 메이저 버전을 건너뜁니다. 업데이트할 확장에는 공간 데이터 처리를 위한 PostGIS 및 관련 확장이 포함됩니다.
   + `address_standardizer`
   + `address_standardizer_data_us`
   + `postgis_raster`
   + `postgis_tiger_geocoder`
   + `postgis_topology`

   `rdkit` 버전 4.6.0 이하 및 PostgreSQL 버전 16 이하를 사용하는 경우 `rdkit` 비호환성으로 인해 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부터 제거됩니다. 알려진 문제로 인해 RDS PostgreSQL 버전 18.1 및 18.2에서는 `postgis_topology` 확장을 사용할 수 없습니다[[1](https://trac.osgeo.org/postgis/ticket/5983)], [[2](https://trac.osgeo.org/postgis/ticket/6016)]. 업그레이드하기 전에 이러한 확장을 제거해야 합니다.

   메이저 버전을 건너뛰어 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에서 DB 인스턴스를 지정된 시간으로 복원](USER_PIT.md) 섹션을 참조하세요. 다중 AZ DB 클러스터의 경우 [스냅샷에서 다중 AZ DB 클러스터로 복원](USER_RestoreFromMultiAZDBClusterSnapshot.Restoring.md) 및 [다중 AZ DB 클러스터를 특정 시점으로 복원](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` DB 파라미터 그룹의 `max_parallel_workers_per_gather` 파라미터 기본값은 2입니다.

   자세한 내용은 PostgreSQL 설명서의 [Parallel Query](https://www.postgresql.org/docs/10/parallel-query.html)(병렬 쿼리)를 참조하세요. 버전 10에서 병렬 처리를 사용 중지하려면 `max_parallel_workers_per_gather` 파라미터를 0으로 설정합니다.

   메이저 버전 업그레이드 중에 `public` 및 `template1` 데이터베이스와 각 데이터베이스에 있는 `public` 스키마의 이름이 일시적으로 변경됩니다. 이러한 객체는 원래 이름 뒤에 임의의 문자열이 추가된 상태로 로그에 표시됩니다. 그러면 `locale` 및 `owner`와 같은 사용자 지정 설정이 메이저 버전 업그레이드 중에 유지되도록 문자열이 추가됩니다. 업그레이드가 완료되면 객체의 이름이 원래 이름으로 다시 변경됩니다.
**참고**  
메이저 버전 업그레이드 프로세스 중에는 DB 인스턴스 또는 다중 AZ DB 클러스터의 특정 시점으로 복원을 수행할 수 없습니다. Amazon RDS에서 업그레이드가 수행된 후 데이터베이스 자동 백업이 수행됩니다. 업그레이드를 시작하기 이전의 시간 및 데이터베이스 자동 백업을 완료한 이후의 시간으로 특정 시점 복원을 수행할 수 있습니다.

1. **사전 확인 절차 오류로 업그레이드가 실패하는 경우 문제 해결** – 메이저 버전 업그레이드 과정에서 Amazon RDS for PostgreSQL은 먼저 사전 확인 절차를 실행하여 업그레이드 실패를 일으킬 수 있는 문제를 식별합니다. 사전 확인 절차는 인스턴스의 모든 데이터베이스에서 호환되지 않는 모든 잠재적 조건을 확인합니다.

   사전 확인 시 문제가 발생하면 업그레이드 사전 확인이 실패했음을 나타내는 로그 이벤트가 생성됩니다. 사전 확인 프로세스 세부 정보는 데이터베이스의 모든 데이터베이스에 대해 `pg_upgrade_precheck.log`라는 업그레이드 로그에 있습니다. Amazon RDS는 파일 이름에 타임스탬프를 추가합니다. 로그 보기에 대한 자세한 내용은 [Amazon RDS 로그 파일 모니터링](USER_LogAccess.md) 단원을 참조하세요.

   사전 확인 시 복제본 업그레이드가 실패하면 실패한 복제본에 대한 복제가 중단되고 복제본이 종료 상태가 됩니다. 해당 읽기 전용 복제본을 삭제하고 업그레이드된 프라이머리 DB 인스턴스를 기반으로 새 읽기 전용 복제본을 다시 생성합니다.

   사전 확인 로그에서 식별된 모든 문제점을 해결한 후 메이저 버전 업그레이드를 다시 시도하세요. 다음은 사전 확인 로그의 예제입니다.

   ```
   ------------------------------------------------------------------------
   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` 상태가 되고 데이터베이스에서 복제가 종료됩니다. 해당 읽기 전용 복제본을 삭제하고 업그레이드된 프라이머리 DB 인스턴스를 기반으로 새 읽기 전용 복제본을 다시 생성합니다.
**참고**  
Amazon RDS는 다중 AZ DB 클러스터의 읽기 전용 복제본을 업그레이드하지 않습니다. 다중 AZ DB 클러스터의 메이저 버전 업그레이드를 수행하면, 읽기 전용 복제본의 복제 상태가 **종료**로 변경됩니다.

   다음과 같은 이유로 읽기 전용 복제본 업그레이드가 실패할 수 있습니다.
   + 대기 시간이 지난 후에도 프라이머리 DB 인스턴스를 따라잡지 못했습니다.
   + storage-full, incompatible-restore 등과 같이 종료 또는 호환되지 않는 수명 주기 상태에 있었습니다.
   + 프라이머리 DB 인스턴스 업그레이드가 시작되었을 때 읽기 전용 복제본에서 별도의 마이너 버전 업그레이드가 실행되었습니다.
   + 읽기 전용 복제본에서 호환되지 않는 파라미터를 사용했습니다.
   + 읽기 전용 복제본이 프라이머리 DB 인스턴스와 통신하여 데이터 폴더를 동기화하지 못했습니다.

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` 유틸리티에서 생성되는 2개의 로그를 표시합니다. 이러한 로그는 `pg_upgrade_internal.log` 및 `pg_upgrade_server.log`입니다. Amazon RDS는 이러한 로그의 파일 이름에 타임스탬프를 추가합니다. 다른 로그와 마찬가지로 이러한 로그를 볼 수 있습니다. 자세한 내용은 [Amazon RDS 로그 파일 모니터링](USER_LogAccess.md) 섹션을 참조하세요.

  업그레이드 로그를 Amazon CloudWatch Logs에 업로드할 수도 있습니다. 자세한 내용은 [Amazon CloudWatch Logs에 PostgreSQL 로그 게시](USER_LogAccess.Concepts.PostgreSQL.md#USER_LogAccess.Concepts.PostgreSQL.PublishtoCloudWatchLogs) 섹션을 참조하세요.
+ 모든 사항이 예상대로 작동하는지 확인하려면 비슷한 워크로드로 업그레이드된 데이터베이스에서 애플리케이션을 테스트합니다. 업그레이드를 확인한 후 이 테스트 인스턴스를 삭제할 수 있습니다.

# RDS for PostgreSQL 마이너 버전 자동 업그레이드
<a name="USER_UpgradeDBInstance.PostgreSQL.Minor"></a>

DB 인스턴스 또는 다중 AZ DB 클러스터를 생성하거나 수정할 때 **마이너 버전 자동 업그레이드** 옵션을 활성화하면 자동으로 데이터베이스가 업그레이드될 수 있습니다.

또한 Amazon RDS는 업그레이드 롤아웃 정책을 지원하여 여러 데이터베이스 리소스 및 AWS 계정에서 자동 마이너 버전 업그레이드를 관리합니다. 자세한 내용은 [자동 마이너 버전 AWS Organizations 업그레이드에 업그레이드 롤아웃 정책 사용](RDS.Maintenance.AMVU.UpgradeRollout.md) 섹션을 참조하세요.

RDS는 각 RDS for PostgreSQL 메이저 버전마다 하나의 마이너 버전을 자동 업그레이드 버전으로 지정합니다. Amazon RDS가 마이너 버전을 테스트하고 승인하면 유지 관리 기간 중에 자동으로 마이너 버전 업그레이드가 실행됩니다. RDS는 자동으로 새로 릴리스된 마이너 버전을 자동 업그레이드 버전으로 설정하지 않습니다. RDS가 더 새로운 자동 업그레이드 버전을 지정하기 전에 다음과 같은 여러 기준이 고려됩니다.
+ 알려진 보안 문제
+ PostgreSQL 커뮤니티 버전의 버그
+ 마이너 버전 릴리스 이후 전반적인 플릿 안정성

다음 AWS CLI 명령을 사용하여 특정 AWS 리전의 지정된 PostgreSQL 마이너 버전에 대한 현재의 자동 마이너 업그레이드 대상 버전을 확인할 수 있습니다.

대상 LinuxmacOS, 또는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에 대한 자동 마이너 업그레이드 대상을 안내합니다.

대상 LinuxmacOS, 또는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           |
+--------------+-----------------+
```

이 예시에서 PostgreSQL 버전 16.3의 경우 `AutoUpgrade` 값은 `True`입니다. 따라서 자동 마이너 업그레이드 대상은 출력에서 강조 표시된 PostgreSQL 버전 16.3입니다.

PostgreSQL 데이터베이스는 다음 기준이 충족되면 유지 관리 기간 중에 자동으로 업그레이드됩니다.
+ 데이터베이스에 **마이너 버전 자동 업그레이드** 옵션이 활성화되어 있습니다.
+ 데이터베이스가 현재 자동 업그레이드 마이너 버전보다 낮은 DB 엔진 버전을 실행 중입니다.

자세한 내용은 [마이너 엔진 버전 자동 업그레이드](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 DB 스냅샷 엔진 버전 업그레이드
<a name="USER_UpgradeDBSnapshot.PostgreSQL"></a>

Amazon RDS를 사용하여 PostgreSQL DB 인스턴스의 스토리지 볼륨 DB 스냅샷을 생성할 수 있습니다. 생성되는 DB 스냅샷은 Amazon RDS 인스턴스에서 사용하는 엔진 버전에 기반합니다. DB 스냅샷의 엔진 버전을 업그레이드할 수 있습니다.

새 엔진 버전으로 업그레이드된 DB 스냅샷을 복원한 후에는 업그레이드가 성공적이었는지 테스트해야 합니다. 메이저 버전 업그레이드에 대한 자세한 내용은 [RDS for PostgreSQL DB 엔진 업그레이드](USER_UpgradeDBInstance.PostgreSQL.md) 단원을 참조하십시오. DB 스냅샷을 복원하는 방법은 [DB 인스턴스 복원](USER_RestoreFromSnapshot.md) 단원을 참조하십시오.

암호화되었거나 암호화되지 않은 수동 DB 스냅샷을 업그레이드할 수 있습니다.

RDS for PostgreSQL DB 스냅샷에 사용 가능한 엔진 버전을 보려면 다음 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 DB 스냅샷에 사용할 수 있는 엔진 버전에 대한 자세한 내용은 [RDS for PostgreSQL 업그레이드에 대한 메이저 버전 선택](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.md) 섹션을 참조하세요.

**참고**  
자동 백업 과정에서 생성되는 자동 DB 스냅샷은 업그레이드할 수 없습니다.

## 콘솔
<a name="USER_UpgradeDBSnapshot.PostgreSQL.Console"></a>

**DB 스냅샷을 업그레이드하려면**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 탐색 창에서 [**Snapshots**]를 선택합니다.

1. 업그레이드할 스냅샷을 선택합니다.

1. **작업**에서 **Upgrade snapshot(스냅샷 업그레이드)**을 선택합니다. **Upgrade snapshot(스냅샷 업그레이드)** 페이지가 표시됩니다.

1. 업그레이드할 **New engine version(새 엔진 버전)**을 선택합니다.

1. 스냅샷을 업그레이드하려면 **변경 내용 저장**을 선택합니다.

   업그레이드 중에는 이 DB 스냅샷의 모든 스냅샷 작업이 비활성화됩니다. 또한 DB 스냅샷 상태가 **사용 가능**에서 **업그레이드 중**으로 바뀐 다음 완료되면 **활성**으로 바뀝니다 스냅샷 손상 문제로 인해 DB 스냅샷을 업그레이드할 수 없는 경우, 상태가 **사용할 수 없음**으로 바뀝니다. 이 상태로부터 스냅샷을 복구할 수는 없습니다.
**참고**  
DB 스냅샷 업그레이드에 실패하면 스냅샷이 원래 버전의 원래 상태로 롤백됩니다.

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

DB 스냅샷을 새 데이터베이스 엔진 버전으로 업그레이드하려면 AWS CLI [modify-db-snapshot](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-snapshot.html) 명령을 사용합니다.

**파라미터**
+ `--db-snapshot-identifier` – 업그레이드할 DB 스냅샷의 식별자입니다. 식별자는 고유의 Amazon 리소스 이름(ARN)이어야 합니다. 자세한 내용은 [Amazon RDS의 Amazon 리소스 이름(ARN)](USER_Tagging.ARN.md) 섹션을 참조하세요.
+ `--engine-version` – DB 스냅샷을 업그레이드할 엔진 버전입니다.

**Example**  
대상 LinuxmacOS, 또는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>

DB 스냅샷을 새 데이터베이스 엔진 버전으로 업그레이드하려면 Amazon RDS API [ModifyDBSnapshot](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBSnapshot.html) 작업을 호출하십시오.
+ `DBSnapshotIdentifier` – 업그레이드할 DB 스냅샷의 식별자입니다. 식별자는 고유의 Amazon 리소스 이름(ARN)이어야 합니다. 자세한 내용은 [Amazon RDS의 Amazon 리소스 이름(ARN)](USER_Tagging.ARN.md) 섹션을 참조하세요.
+ `EngineVersion` – DB 스냅샷을 업그레이드할 엔진 버전입니다.

# Amazon RDS for PostgreSQL의 읽기 전용 복제본 작업
<a name="USER_PostgreSQL.Replication.ReadReplicas"></a>

인스턴스에 읽기 복제본을 추가하여 Amazon RDS for PostgreSQL DB 인스턴스에 대한 읽기를 조정할 수 있습니다. 다른 Amazon RDS 데이터베이스 엔진과 마찬가지로 RDS for PostgreSQL은 PostgreSQL의 기본 복제 메커니즘을 사용하여 소스 DB에 대한 변경 사항이 반영되도록 읽기 복제본을 최신 상태로 유지합니다. 읽기 전용 복제본 및 Amazon RDS에 대한 일반적인 정보는 [DB 인스턴스 읽기 전용 복제본 작업](USER_ReadRepl.md) 섹션을 참조하세요.

다음으로, RDS for PostgreSQL에서의 읽기 전용 복제본 작업 관련 정보를 찾을 수 있습니다.



## PostgreSQL을 사용한 읽기 전용 복제본 제한
<a name="USER_PostgreSQL.Replication.ReadReplicas.Limitations"></a>

PostgreSQL 읽기 전용 복제본에 대한 제한 사항은 다음과 같습니다.
+ PostgreSQL 읽기 전용 복제본은 읽기 전용입니다. 읽기 전용 복제본은 쓰기 가능한 DB 인스턴스가 아니지만, 독립 실행형 RDS for PostgreSQL DB 인스턴스로 승격할 수 있습니다. 그러나 이 프로세스는 되돌릴 수 없습니다.
+ RDS for PostgreSQL DB 인스턴스에서 14.1 이전 버전의 PostgreSQL을 실행하는 경우에는 다른 읽기 전용 복제본에서 읽기 전용 복제본을 생성할 수 없습니다. RDS for PostgreSQL은 RDS for PostgreSQL 버전 14.1 이상 릴리스에서만 계단식 읽기 전용 복제를 지원합니다. 자세한 내용은 [RDS for PostgreSQL에서의 계단식 읽기 전용 복제본 사용](USER_PostgreSQL.Replication.ReadReplicas.Cascading.md) 섹션을 참조하세요.
+ PostgreSQL 읽기 전용 복제본을 승격하면 읽기 전용 복제본이 쓰기 가능한 DB 인스턴스가 됩니다. 소스 DB 인스턴스에서 미리 쓰기 로그(WAL) 파일 수신이 중단되며, 더 이상 읽기 전용 인스턴스가 아니게 됩니다. RDS for PostgreSQL DB 인스턴스와 마찬가지로 승격된 DB 인스턴스에서 새 읽기 전용 복제본을 생성할 수 있습니다. 자세한 내용은 [읽기 전용 복제본을 독립 DB 인스턴스로 승격](USER_ReadRepl.Promote.md) 섹션을 참조하세요.
+ 복제 체인(일련의 계단식 읽기 전용 복제본) 내에서 PostgreSQL 읽기 전용 복제본을 승격하면 기존의 다운스트림 읽기 전용 복제본은 승격된 인스턴스에서 자동으로 WAL 파일을 계속 수신합니다. 자세한 내용은 [RDS for PostgreSQL에서의 계단식 읽기 전용 복제본 사용](USER_PostgreSQL.Replication.ReadReplicas.Cascading.md) 섹션을 참조하세요.
+ 원본 DB 인스턴스에서 사용자 트랜잭션이 발생하지 않는 경우 PostgreSQL 읽기 전용 복제본은 최대 5분까지 복제 지연을 보고합니다. 복제 지연은 `currentTime - lastCommitedTransactionTimestamp`로 계산되며, 이는 처리 중인 트랜잭션이 없을 때 Write-Ahead Log(WAL) 세그먼트가 발생할 때까지 일정 기간 동안 복제 지연 값이 증가함을 의미합니다. 기본적으로 RDS for PostgreSQL는 WAL 세그먼트를 5분마다 전환하므로 트랜잭션 레코드가 생성되고 보고된 지연이 감소합니다.
+ RDS for PostgreSQL 14.1 이전 버전의 PostgreSQL 읽기 전용 복제본에 대해서는 자동 백업을 설정할 수 없습니다. 읽기 전용 복제본에 대한 자동 백업은 RDS for PostgreSQL 14.1 이상 버전에서만 지원됩니다. RDS for PostgreSQL 13 이전 버전의 경우 백업하려면 읽기 전용 복제본에서 스냅샷을 생성하면 됩니다.
+ 시점 복구(PITR)는 읽기 전용 복제본에 지원되지 않습니다. PITR은 읽기 전용 복제본을 제외한 프라이머리(라이터) 인스턴스에서만 사용할 수 있습니다. 자세한 내용은 [Amazon RDS에서 DB 인스턴스를 지정된 시간으로 복원](USER_PIT.md)를 참조하세요.
+ PostgreSQL 버전 12 이하의 읽기 전용 복제본은 60\$190일의 유지 관리 기간 동안 암호 교체를 적용하기 위해 자동으로 재부팅됩니다. 예약된 재부팅 전에 복제본과 소스 간의 연결이 끊어져도 복제를 재개하기 위해 여전히 재부팅됩니다. PostgreSQL 버전 13 이상의 경우 암호 교체 프로세스 중에 읽기 전용 복제본에서 잠시 복제 연결이 끊어지고 다시 연결되는 현상이 발생할 수 있습니다.

# PostgreSQL을 사용한 읽기 전용 복제본 구성
<a name="USER_PostgreSQL.Replication.ReadReplicas.Configuration"></a>

RDS for PostgreSQL은 PostgreSQL의 기본 스트리밍 복제 기능을 사용하여 소스 DB 인스턴스의 읽기 전용 복제본을 생성합니다. 이 읽기 전용 복제본 DB 인스턴스는 비동기식으로 생성된 소스 DB 인스턴스의 물리적 복제본입니다. 이는 소스 DB 인스턴스와 읽기 전용 복제본 간에 미리 쓰기 로그(WAL) 데이터를 전송하는 특수 연결에 의해 생성됩니다. 자세한 내용은 PostgreSQL 설명서에서 [스트리밍 복제](https://www.postgresql.org/docs/14/warm-standby.html#STREAMING-REPLICATION)를 참조하세요.

PostgreSQL은 소스 DB 인스턴스에서 이루어지는 대로 이 보안 연결에 대한 데이터베이스 변경 사항을 비동기식으로 스트리밍합니다. `ssl` 파라미터를 `1`로 설정하여 클라이언트 애플리케이션에서 소스 DB 인스턴스 또는 읽기 전용 복제본으로의 통신을 암호화할 수 있습니다. 자세한 내용은 [PostgreSQL DB 인스턴스와 함께 SSL 사용](PostgreSQL.Concepts.General.SSL.md)을 참조하세요.

PostgreSQL은 *복제* 역할을 사용하여 스트리밍 복제를 실행합니다. 이 역할에는 권한이 부여되지만, 데이터까지 수정하지는 못합니다. PostgreSQL은 단일 프로세스를 통해 복제를 처리합니다.

소스 DB 인스턴스의 작업 또는 사용자에게 영향을 주지 않고 PostgreSQL 읽기 전용 복제본을 생성할 수 있습니다. Amazon RDS는 서비스에 영향을 미치지 않고 소스 DB 인스턴스와 읽기 전용 복제본에 필요한 파라미터와 권한을 설정합니다. 소스 DB 인스턴스의 스냅샷이 생성되고, 이 스냅샷이 읽기 전용 복제본을 생성하는 데 사용됩니다. 향후 언제든지 읽기 전용 복제본을 삭제해도 중단이 발생하지 않습니다.

동일 리전 내의 소스 DB 인스턴스 하나에서 최대 15개까지 읽기 전용 복제본을 생성할 수 있습니다. RDS for PostgreSQL 14.1부터는 소스 DB 인스턴스에서 체인(계단식)에 최대 3가지 수준의 읽기 전용 복제본을 생성할 수도 있습니다. 자세한 내용은 [RDS for PostgreSQL에서의 계단식 읽기 전용 복제본 사용](USER_PostgreSQL.Replication.ReadReplicas.Cascading.md) 섹션을 참조하세요. 모든 경우에 소스 DB 인스턴스에는 자동 백업이 구성되어야 합니다. 이 작업을 수행하려면 DB 인스턴스의 백업 보존 기간을 0이 아닌 값으로 설정하면 됩니다. 자세한 내용은 [읽기 전용 복제본 생성](USER_ReadRepl.Create.md)을 참조하세요.

소스 DB 인스턴스와 동일한 AWS 리전에 RDS for PostgreSQL DB 인스턴스의 읽기 전용 복제본을 생성할 수 있습니다. 이를 *리전 내* 복제라고도 합니다. 소스 DB 인스턴스와 다른 AWS 리전에서 읽기 전용 복제본을 생성할 수도 있습니다. 이를 *교차 리전* 복제라고도 합니다. 교차 리전 읽기 전용 복제본 설정에 대한 자세한 내용은 [다른 에서 읽기 전용 복제본 생성AWS 리전](USER_ReadRepl.XRgn.md) 섹션을 참조하세요. 리전 내 및 교차 리전에 대한 복제 프로세스를 지원하는 다양한 메커니즘은 [서로 다른 RDS for PostgreSQL 버전에서 스트리밍 복제가 작동하는 방식](USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.md)에 설명된 대로 RDS for PostgreSQL 버전에 따라 약간 다릅니다.

효과적인 복제를 위해서는 읽기 전용 복제본도 각각 원본 DB 인스턴스와 동일한 양의 컴퓨팅 및 스토리지 리소스를 가져야 합니다. 소스 DB 인스턴스 크기를 조정하는 경우 읽기 전용 복제본 크기도 조정됩니다.

Amazon RDS는 파라미터가 읽기 전용 복제본의 시작을 방해하는 경우 읽기 전용 복제본의 호환되지 않는 파라미터를 재정의합니다. 예를 들어 `max_connections` 파라미터 값이 읽기 전용 복제본보다 원본 DB 인스턴스에서 더 크다고 가정하겠습니다. 이 경우 Amazon RDS가 원본 DB 인스턴스의 파라미터 값이 동일하도록 읽기 전용 복제본의 파라미터를 업데이트합니다.

RDS for PostgreSQL 읽기 전용 복제본은 소스 DB 인스턴스의 외부 데이터 래퍼(FDW)를 통해 사용 가능한 외부 데이터베이스에 액세스할 수 있습니다. 예를 들어 RDS for PostgreSQL DB 인스턴스에서 `mysql_fdw` 래퍼를 사용하여 RDS for MySQL의 데이터에 액세스한다고 가정해봅니다. 이 경우 읽기 전용 복제본도 해당 데이터에 액세스할 수 있습니다. 기타 지원되는 FDW는 `oracle_fdw`, `postgres_fdw`, `tds_fdw`입니다. 자세한 내용은 [Amazon RDS for PostgreSQL용 지원되는 외부 데이터 래퍼 작업](Appendix.PostgreSQL.CommonDBATasks.Extensions.foreign-data-wrappers.md)을 참조하세요.

## 다중 AZ 구성을 통한 RDS for PostgreSQL 읽기 전용 복제본 사용
<a name="USER_PostgreSQL.Replication.ReadReplicas.Configuration.multi-az"></a>

단일 AZ 또는 다중 AZ DB 인스턴스를 통해 읽기 전용 복제본을 생성할 수 있습니다. 다중 AZ 배포는 대기 복제본을 통해 중요 데이터의 내구성과 가용성을 개선하는 데 사용할 수 있습니다. *대기 본제본*은 소스 DB가 장애 조치될 경우 워크로드를 가정할 수 있는 전담 읽기 전용 복제본입니다. 대기 복제본을 사용하여 읽기 트래픽을 처리할 수 없습니다. 단, 트래픽이 많은 다중 AZ DB 인스턴스에서 읽기 전용 쿼리를 오프로드할 목적으로 읽기 전용 복제본을 생성할 수는 있습니다. 다중 AZ 배포에 대한 자세한 내용은 [Amazon RDS에 대한 다중 AZ 인스턴스 배포](Concepts.MultiAZSingleStandby.md) 섹션을 참조하세요.

다중 AZ 배포의 소스 DB 인스턴스가 대기로 장애 조치되는 경우 연결된 읽기 전용 복제본이 전환되어 대기(이제는 프라이머리)를 복제 소스로 사용합니다. RDS for PostgreSQL 버전에 따라 다음과 같이 읽기 전용 복제본을 다시 시작해야 할 수 있습니다.
+ **PostgreSQL 13 이상 버전** - 재시작이 필요하지 않습니다. 읽기 전용 복제본이 새 프라이머리 복제본과 자동으로 동기화됩니다. 그러나 경우에 따라 클라이언트 애플리케이션이 읽기 전용 복제본에 대한 도메인 이름 서비스(DNS) 세부 정보를 캐시할 수 있습니다. 이 경우에는 Time-to-Live(TTL) 값을 30초 미만으로 설정합니다. 이렇게 하면 읽기 전용 복제본이 오래된 IP 주소를 보유하지 못하게 되므로 새 프라이머리 복제본과 동기화되지 않습니다. 이 방법과 기타 모범 사례에 대해 자세히 알아보려면 [Amazon RDS 기본 운영 지침](CHAP_BestPractices.md#CHAP_BestPractices.DiskPerformance) 섹션을 참조하세요.
+ **PostgreSQL 12 및 모든 이전 버전** - 대기 복제본(현재 프라이머리)의 IP 주소와 인스턴스 이름이 다르기 때문에 대기 복제본으로 장애 조치 후 읽기 전용 복제본이 자동으로 다시 시작됩니다. 다시 시작하면 읽기 전용 복제본이 새 프라이머리 복제본과 동기화됩니다.

장애 조치에 대해 자세히 알아보려면 [Amazon RDS에 대한 다중 AZ DB 인스턴스 장애 조치](Concepts.MultiAZ.Failover.md) 섹션을 참조하세요. 다중 AZ 배포에서 읽기 전용 복제본이 작동하는 방식에 대한 자세한 내용은 [DB 인스턴스 읽기 전용 복제본 작업](USER_ReadRepl.md) 섹션을 참조하세요.

읽기 전용 복제본이 장애 조치를 지원하도록 하려면 Amazon RDS가 다른 가용 영역에 복제본의 대기 복제본을 만들 수 있게 읽기 전용 복제본을 다중 AZ DB 인스턴스로 생성하면 됩니다. 읽기 전용 복제본을 다중 AZ DB 인스턴스로 생성하는 작업은 원본 데이터베이스가 다중 AZ DB 인스턴스인지 여부와는 무관합니다.

# 읽기 복제본의 논리적 디코딩
<a name="USER_PostgreSQL.Replication.ReadReplicas.LogicalDecoding"></a>

 PostgreSQL용 RDS는 PostgreSQL 16.1을 사용하여 스탠바이 상태에서의 논리적 복제를 지원합니다. 이를 통해 읽기 전용 예비 복제본에서 논리적 디코딩을 생성하여 기본 DB 인스턴스의 부하를 줄일 수 있습니다. 여러 시스템에서 데이터를 동기화해야 하는 애플리케이션의 가용성을 높일 수 있습니다. 이 기능은 데이터 웨어하우스 및 데이터 분석의 성능을 향상합니다.

 또한 지정된 예비 복제본의 복제 슬롯은 해당 예비 복제본을 기본 스탠바이로 계속 승격시킵니다. 즉, 기본 DB 인스턴스가 장애 조치 처리되거나 예비 복제본을 새 기본 인스턴스로 승격하는 경우 복제 슬롯은 유지되며 이전 예비 복제본 구독자는 영향을 받지 않습니다.

**읽기 전용 복제본에 논리적 디코딩을 생성하려면**

1. **논리적 복제 활성화** - 예비 복제본에서 논리적 디코딩을 생성하려면 소스 DB 인스턴스와 물리적 복제본에서 논리적 복제를 활성화해야 합니다. 자세한 내용은 [PostgreSQL을 사용한 읽기 전용 복제본 구성](USER_PostgreSQL.Replication.ReadReplicas.Configuration.md) 섹션을 참조하세요.
   + **새로 만든 RDS for PostgreSQL DB 인스턴스의 논리적 복제를 활성화하려면** 새 DB 사용자 지정 파라미터 그룹을 만들고 정적 파라미터 `rds.logical_replication`을 `1`로 설정합니다. 그런 다음 이 DB 파라미터 그룹을 소스 DB 인스턴스 및 물리적 읽기 복제본과 연결합니다. 자세한 내용은 [Amazon RDS의 DB 인스턴스에 DB 파라미터 그룹 연결](USER_WorkingWithParamGroups.Associating.md) 섹션을 참조하세요.
   + **PostgreSQL DB 인스턴스용 기존 RDS의 논리적 복제를 활성화하려면** 소스 DB 인스턴스의 DB 사용자 지정 파라미터 그룹과 물리적 읽기 복제본을 수정하여 정적 파라미터 `rds.logical_replication`을 `1`로 설정합니다. 자세한 내용은 [Amazon RDS에서 DB 파라미터 그룹의 파라미터 수정](USER_WorkingWithParamGroups.Modifying.md) 섹션을 참조하세요.
**참고**  
이러한 파라미터 변경 사항을 적용하려면 DB 인스턴스를 재부팅해야만 합니다.

   다음 쿼리를 사용하여 소스 DB 인스턴스의 `rds.logical_replication`와 물리적 읽기 전용 복제본의 값과 `wal_level` 값을 확인할 수 있습니다.

   ```
   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. **소스 데이터베이스에 테이블 생성** - 소스 DB 인스턴스의 데이터베이스에 연결합니다. 자세한 내용은 [PostgreSQL 데이터베이스 엔진을 실행하는 DB 인스턴스에 연결](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. **소스 테이블에 대한 발행물 생성** - 다음 쿼리를 사용하여 소스 DB 인스턴스의 테이블에 대한 발행물을 만들 수 있습니다.

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

   SELECT 쿼리를 사용하여 소스 DB 인스턴스와 물리적 읽기 복제본 인스턴스 모두에서 생성된 발행의 세부 정보를 확인할 수 있습니다.

   ```
   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 DB 인스턴스를 논리적 복제 인스턴스로 하나 더 생성합니다. 이 논리적 복제본 인스턴스가 물리적 읽기 복제본 인스턴스에 액세스할 수 있도록 VPC가 올바르게 설정되어 있는지 확인하세요. 자세한 내용은 [Amazon VPC 및 Amazon RDS](USER_VPC.md) 섹션을 참조하세요. 소스 DB 인스턴스가 유휴 상태인 경우 연결 문제가 발생할 수 있으며 기본 인스턴스는 데이터를 스탠바이 인스턴스로 전송하지 않습니다.

   ```
   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. **논리적 복제 슬롯 상태 검사** - 소스 DB 인스턴스의 물리적 복제 슬롯만 볼 수 있습니다.

   ```
   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 DB 인스턴스에 오버헤드를 추가하지 않고도 읽기 전용 복제본 크기를 조정할 수 있습니다. 소스 DB 인스턴스에서는 WAL 로그에 업데이트된 내용을 각 읽기 전용 복제본으로 전송하지 않습니다. 대신 각 계단식 읽기 전용 복제본에서 WAL 로그 업데이트를 함께 구성된 다음 읽기 전용 복제본으로 보냅니다. 이렇게 하면 소스 DB 인스턴스에 가해지는 부담이 줄어듭니다.

계단식 읽기 전용 복제본을 사용하면 RDS for PostgreSQL DB 인스턴스가 WAL 데이터를 체인의 첫 번째 읽기 전용 복제본으로 전송합니다. 뒤이어 해당 읽기 전용 복제본이 WAL 데이터를 체인의 두 번째 복제본으로 전송하는 식으로 이루어집니다. 결과적으로 체인의 모든 읽기 전용 복제본이 소스 DB 인스턴스에만 오버헤드가 발생하는 일 없이 RDS for PostgreSQL DB 인스턴스에서 변경됩니다.

소스 RDS for PostgreSQL DB 인스턴스에서 체인에 최대 3개의 읽기 전용 복제본을 생성할 수 있습니다. 예를 들어 RDS for PostgreSQL 14.1 DB 인스턴스, `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 소스 DB 인스턴스부터 계단식 읽기 전용 복제본 체인의 마지막에 이르는 전체 인스턴스는 최대 4개의 DB 인스턴스로 구성될 수 있습니다.

읽기 전용 복제본을 계단식으로 실행하려면 RDS for PostgreSQL에서 자동 백업을 설정합니다. 먼저 읽기 전용 복제본을 생성한 다음 RDS for PostgreSQL DB 인스턴스에서 자동 백업을 켜면 됩니다. 이 프로세스는 다른 Amazon RDS DB 엔진에서와 동일합니다. 자세한 내용은 [읽기 전용 복제본 생성](USER_ReadRepl.Create.md)을 참조하세요.

모든 읽기 전용 복제본과 마찬가지로 계단식 구성에 포함된 읽기 전용 복제본을 승격할 수 있습니다. 읽기 전용 복제본 체인의 한 읽기 전용 복제본을 승격하면 체인에서 해당 복제본이 제거됩니다. 예를 들어 `rpg-db-main` DB 인스턴스의 일부 워크로드를 회계 부서에서만 사용할 수 있도록 새 인스턴스로 옮기려고 합니다. 이 예제에서 3개의 읽기 전용 복제본 체인이 있다고 가정하고 `read-replica-2`를 승격하기로 결정합니다. 체인은 다음과 같이 변화합니다.
+ `read-replica-2`를 승격하면 복제 체인에서 제거됩니다.
  + 이제 전체 읽기/쓰기 DB 인스턴스가 됩니다.
  + 승격 전과 마찬가지로 `read-replica-3`으로 계속 복제합니다.
+ `rpg-db-main`은 `read-replica-1`로 계속 복제를 진행합니다.

읽기 전용 복제본 승격에 대한 자세한 내용은 [읽기 전용 복제본을 독립 DB 인스턴스로 승격](USER_ReadRepl.Promote.md) 섹션을 참조하세요.

**참고**  
RDS for PostgreSQL은 계단식 복제본에 대한 메이저 버전 업그레이드를 지원하지 않습니다. 메이저 버전 업그레이드를 수행하기 전에 계단식 복제본을 제거해야 합니다. 소스 DB 인스턴스 및 1단계 복제본에서 업그레이드를 완료한 후 다시 만들 수 있습니다.
계단식 읽기 전용 복제본의 경우 RDS for PostgreSQL은 첫 번째 복제 수준에서 각 소스 DB 인스턴스에 대해 15개의 읽기 전용 복제본을 지원하고, 두 번째 및 세 번째 복제 수준에서 각 소스 DB 인스턴스에 대해 5개의 읽기 전용 복제본을 지원합니다.

# RDS for PostgreSQL로 교차 리전 계단식 읽기 복제본 생성
<a name="USER_PostgreSQL.Replication.ReadReplicas.Xregion"></a>

RDS for PostgreSQL은 교차 리전 계단식 읽기 복제본을 지원합니다. 소스 DB 인스턴스에서 교차 리전 복제본을 생성한 다음, 이 복제본에서 동일 리전 복제본을 생성할 수 있습니다. 소스 DB 인스턴스에서 동일한 리전 복제본을 생성한 다음, 이 복제본에서 교차 리전 복제본을 생성할 수 있습니다.

**교차 리전 복제본을 생성한 다음 동일 리전 복제본 생성**

버전 14.1 이상의 RDS for PostgreSQL DB 인스턴스, `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 DB 인스턴스, `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)을 생성합니다.

**교차 리전 읽기 복제본 생성의 제한 사항**
+ 데이터베이스 복제본의 교차 리전 캐스케이딩 체인은 최대 2개의 리전에 걸쳐 최대 4개의 레벨로 구성할 수 있습니다. 4가지 수준에는 데이터베이스 소스와 3개의 읽기 복제본이 포함됩니다.

**계단식 읽기 복제본 사용의 장점**
+ 읽기 확장성 향상 - 읽기 쿼리를 여러 복제본에 분산하여 캐스케이딩 복제를 통해 부하를 분산할 수 있습니다. 이렇게 하면 쓰기 데이터베이스의 부담을 줄여 특히 읽기가 많은 애플리케이션의 성능이 향상됩니다.
+ 지리적 분포 - 계단식 복제본은 서로 다른 지리적 위치에 위치할 수 있습니다. 이렇게 하면 기본 데이터베이스에서 멀리 떨어져 있는 사용자의 대기 시간이 줄어들고 로컬 읽기 복제본을 제공하여 성능과 사용자 경험이 향상됩니다.
+ 고가용성 및 재해 복구 - 기본 서버에 장애가 발생하면 복제본을 기본 서버로 승격하여 연속성을 보장할 수 있으며, 계단식 복제는 여러 계층의 장애 복구 옵션을 제공하여 시스템의 전반적인 복원력을 향상시킴으로써 이를 더욱 강화합니다.
+ 유연성 및 모듈식 성장 - 시스템이 성장함에 따라 기본 데이터베이스를 크게 재구성하지 않고도 다양한 수준에서 새로운 복제본을 추가할 수 있습니다. 이러한 모듈식 접근 방식을 통해 복제 설정을 확장하고 관리할 수 있습니다.

**교차 리전 읽기 복제본 사용 모범 사례**
+ 복제본을 승격하기 전에 추가 복제본을 생성하세요. 이렇게 하면 시간을 절약하고 워크로드를 효율적으로 처리할 수 있습니다.

# 서로 다른 RDS for PostgreSQL 버전에서 스트리밍 복제가 작동하는 방식
<a name="USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions"></a>

[PostgreSQL을 사용한 읽기 전용 복제본 구성](USER_PostgreSQL.Replication.ReadReplicas.Configuration.md)에서 설명한 바와 같이, RDS for PostgreSQL은 PostgreSQL의 기본 스트리밍 복제 프로토콜을 사용하여 소스 DB 인스턴스에서 WAL 데이터를 전송합니다. 소스 WAL 데이터를 리전 내 읽기 전용 복제본과 교차 리전 읽기 전용 복제본으로 전송합니다. 버전 9.4에서는 PostgreSQL에 복제 프로세스를 위한 지원 메커니즘으로 물리적 복제 슬롯이 도입되었습니다.

*물리적 복제 슬롯*은 소스 DB 인스턴스가 모든 읽기 전용 복제본에서 WAL 데이터를 사용하기 전에 WAL 데이터를 제거하지 못하도록 합니다. 각 읽기 전용 복제본은 소스 DB 인스턴스에 자체 물리적 슬롯이 있습니다. 슬롯은 복제본에 필요할 수 있는 가장 오래된 WAL(논리 시퀀스 번호(LSN)별)을 추적합니다. 모든 슬롯과 DB 연결이 지정된 WAL(LSN) 이상으로 진행된 후에는 해당 LSN이 다음 체크포인트에서 제거할 수 있는 후보가 됩니다.

Amazon RDS는 Amazon S3를 사용하여 WAL 데이터를 아카이브합니다. 리전 내 읽기 전용 복제본의 경우 필요하다면 아카이브된 데이터를 사용하여 읽기 전용 복제본을 복구할 수 있습니다. 소스 DB와 읽기 전용 복제본 간의 연결이 어떤 이유로든 중단되는 경우에 복구가 필요할 수 있습니다.

다음 테이블에서는 PostgreSQL 버전과 RDS for PostgreSQL에서 사용하는 리전 내 및 교차 리전에 대한 지원 메커니즘 간의 차이점을 간략히 확인할 수 있습니다.


| 버전 | 리전 내 | 교차 리전 | 
| --- | --- | --- | 
| PostgreSQL 14.1 이상 버전 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/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/ko_kr/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.Mechanisms-versions.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/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>

다음 파라미터는 복제 프로세스에 영향을 미치며, 읽기 전용 복제본이 소스 DB 인스턴스의 최신 상태를 유지하는 정도를 결정합니다.

**max\$1wal\$1senders**  
`max_wal_senders` 파라미터는 스트리밍 복제 프로토콜을 통해 소스 DB 인스턴스가 동시에 지원할 수 있는 최대 연결 수를 지정합니다.  
기본값은 다음과 같이 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`는 변경 사항을 적용하려면 DB 인스턴스 재부팅이 필요한 정적 파라미터입니다.

**wal\$1keep\$1segments**  
`wal_keep_segments` 파라미터는 소스 DB 인스턴스에서 `pg_wal` 디렉터리에 보관하는 미리 쓰기 로그(WAL) 파일의 수를 지정합니다. 기본 설정은 32입니다.  
`wal_keep_segments`가 배포에 대해 충분히 큰 값으로 설정되지 않으면 읽기 전용 복제본이 따라잡지 못하면서 스트리밍 복제가 중지될 수 있습니다. 이 경우에는 Amazon RDS가 복제 오류를 생성하고 읽기 전용 복제본의 복구를 시작합니다. 이렇게 하려면 Amazon S3에서 소스 DB 인스턴스의 아카이브된 WAL 데이터를 재실행하면 됩니다. 이 복구 프로세스는 읽기 전용 복제본이 스트리밍 복제를 이어갈 만큼 충분히 따라잡을 때까지 계속됩니다. [예: 복제 중단에서 읽기 전용 복제본을 복구하는 방법예: 복제 중단에서 읽기 전용 복제본 복구](#USER_PostgreSQL.Replication.example-how-it-works)에서 이 프로세스가 PostgreSQL 로그에서 캡처된 대로 실행 중임을 확인할 수 있습니다.  
PostgreSQL 버전 13에서 `wal_keep_segments` 파라미터 이름은 `wal_keep_size`입니다. `wal_keep_segments`와 동일한 목적을 수행하지만, 기본값은 파일 수가 아닌 메가바이트(MB)(2,048MB)입니다. 자세한 내용은 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 DB 인스턴스가 슬롯을 제공하기 위해 `pg_wal` 디렉터리에 유지하는 WAL 데이터의 양을 제어합니다. 이 파라미터는 복제 슬롯을 사용하는 구성에 사용됩니다. 이 파라미터의 기본값은 `-1`입니다. 즉, 소스 DB 인스턴스에 보관되는 WAL 데이터의 양에는 제한이 없습니다. 복제 슬롯 모니터링에 대한 자세한 내용은 [RDS for PostgreSQL DB 인스턴스에 대한 복제 슬롯 모니터링](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>

다음 예제에서는 읽기 전용 복제본에 대한 복구 프로세스를 보여 주는 로그 세부 정보를 찾아볼 수 있습니다. 이 예제는 소스 DB와 같은 AWS 리전에서 PostgreSQL 버전 12.9를 실행하는 RDS for PostgreSQL DB 인스턴스에서 비롯되었으므로, 복제 슬롯이 사용되지 않습니다. 복구 프로세스는 리전 내 읽기 전용 복제본이 있는 14.1 이전 버전의 PostgreSQL을 실행하는 다른 RDS for PostgreSQL DB 인스턴스와 동일합니다.

읽기 전용 복제본과 소스 DB 인스턴스의 연결이 끊어졌을 때 Amazon RDS는 `ERROR: requested WAL segment ... has already been removed`와 함께 `FATAL: could not receive data from WAL stream` 메시지로 로그에 문제를 기록합니다. 굵은 줄에 나와 있는 것처럼 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 DB 인스턴스와 읽기 전용 복제본을 정기적으로 모니터링하는 것이 좋습니다. 읽기 전용 복제본이 소스 DB 인스턴스의 변경 사항을 따르도록 해야 합니다. Amazon RDS는 복제 프로세스가 중단될 때 읽기 전용 복제본을 명료하게 복구합니다. 그러나 복구할 필요가 아예 없도록 하는 것이 가장 좋습니다. 복제 슬롯을 사용하여 복구하는 것이 Amazon S3 아카이브를 사용하는 것보다 빠르지만, 복구 프로세스는 읽기 성능에 영향을 줄 수 있습니다.

다음을 수행하여 읽기 전용 복제본이 소스 DB 인스턴스를 얼마나 잘 따라잡는지 확인할 수 있습니다.
+ **소스 DB 인스턴스와 복제본 간 `ReplicaLag`의 양을 확인합니다** *복제본 지연*은 읽기 전용 복제본이 소스 DB 인스턴스보다 지연되는 시간(초)입니다. 이 지표는 다음 쿼리 결과를 보고합니다.

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

  복제본 지연은 읽기 전용 복제본이 소스 DB 인스턴스를 얼마나 잘 따라잡는지 나타냅니다. 이는 소스 DB 인스턴스와 특정 읽기 전용 인스턴스 간의 지연 시간입니다. 복제본 지연 값이 높으면 소스 DB 인스턴스와 해당 읽기 전용 복제본이 사용하는 DB 인스턴스 클래스나 스토리지 유형(또는 둘 다) 간에 불일치가 있다는 의미일 수 있습니다. DB 소스 인스턴스와 모든 읽기 전용 복제본의 DB 인스턴스 클래스 및 스토리지 유형은 동일해야 합니다.

  복제본 지연은 간헐적인 연결 문제의 결과로 나타날 수도 있습니다. Amazon CloudWatch에서 Amazon RDS `ReplicaLag` 지표를 보고 복제 지연을 모니터링할 수 있습니다. Amazon RDS의 `ReplicaLag` 및 기타 지표에 대한 자세한 내용은 [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를 사용하여 복제 문제를 예측할 수 있는 지표를 모니터링합니다.** PostgreSQL 로그를 직접 분석하는 대신 Amazon CloudWatch를 사용하여 수집된 지표를 확인할 수 있습니다. 예를 들어 `TransactionLogsGeneration` 지표의 값을 확인하여 소스 DB 인스턴스에서 얼마나 많은 WAL 데이터를 생성 중인지 확인 가능합니다. DB 인스턴스의 워크로드로 인해 많은 양의 WAL 데이터가 생성되는 경우가 있습니다. 그렇다면 소스 DB 인스턴스와 읽기 전용 복제본의 DB 인스턴스 클래스를 변경해야 할 수 있습니다. 네트워크 성능이 높은(10Gbps) 인스턴스 클래스를 사용하면 복제본 지연이 줄어들 수 있습니다.

## RDS for PostgreSQL DB 인스턴스에 대한 복제 슬롯 모니터링
<a name="USER_PostgreSQL.Replication.ReadReplicas.Monitor-monitor-replication-slots"></a>

모든 RDS for PostgreSQL 버전은 교차 리전 읽기 전용 복제본의 복제 슬롯을 사용합니다. RDS for PostgreSQL 14.1 이상 버전은 리전 내 읽기 전용 복제본의 복제 슬롯을 사용합니다. 또한 리전 내 읽기 전용 복제본은 Amazon S3를 사용하여 WAL 데이터를 아카이브합니다. 즉, DB 인스턴스와 읽기 전용 복제본이 PostgreSQL 14.1 이상을 실행하는 경우 복제 슬롯과 Amazon S3 아카이브를 모두 사용하여 읽기 전용 복제본을 복구할 수 있습니다. 복제 슬롯을 사용하여 읽기 전용 복제본을 복구하는 것이 Amazon S3 아카이브에서 복구하는 것보다 빠릅니다. 따라서 복제 슬롯 및 관련 지표를 모니터링하는 것이 좋습니다.

다음과 같이 `pg_replication_slots` 보기를 쿼리하여 RDS for PostgreSQL DB 인스턴스의 복제 슬롯을 볼 수 있습니다.

```
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`** - 가장 지연된 복제본에서 사용하지 않은 소스의 Write-Ahead Log(WAL) 데이터의 양을 표시합니다.
+ **`TransactionLogsDiskUsage`** - WAL 데이터에 얼마나 많은 스토리지가 사용되고 있는지 보여줍니다. 읽기 전용 복제본이 크게 지연되면 이 지표의 값이 크게 증가할 수 있습니다.

Amazon CloudWatch와 RDS for PostgreSQL에 대한 해당 지표 사용에 대해 자세히 알아보려면 [Amazon CloudWatch로 Amazon RDS 지표 모니터링](monitoring-cloudwatch.md) 섹션을 참조하세요. RDS for PostgreSQL DB 인스턴스의 스트리밍 복제 모니터링에 대한 자세한 내용은 *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 버전

복제 프로세스에 시간 지연을 도입하면 전체 DB 클러스터에 영향을 미치기 전에 데이터 관련 인시던트를 감지하고 대응할 수 있는 기회를 얻을 수 있습니다. 지연 복제의 주요 이점은 다음과 같습니다.
+ 실수로 인한 삭제, 업데이트 또는 기타 논리적 실수로부터 복구할 수 있습니다.
+ DB 클러스터 간에 손상된 데이터가 분산되지 않도록 버퍼를 제공합니다.
+ 기존 백업 전략을 보완하는 추가 복구 시점 옵션을 제공합니다.
+ 조직의 특정 요구 사항 및 위험 허용치를 기반으로 지연 기간을 구성할 수 있습니다.

## 지연 복제 활성화 및 구성
<a name="enabling-rpg-delayed-replication"></a>

RDS for PostgreSQL 읽기 전용 복제본에서 지연 복제를 활성화하려면 다음 단계를 따르세요.

**참고**  
캐스케이드된 읽기 전용 복제본의 경우 아래 설명된 것과 동일한 `recovery_min_apply_delay` 파라미터와 단계를 사용합니다.

**지연 복제 활성화**

1. 사용자 지정 파라미터 그룹을 새로 생성하거나 기존 그룹을 수정합니다. 자세한 내용은 [Amazon RDS DB 인스턴스용 DB 파라미터 그룹](USER_WorkingWithDBInstanceParamGroups.md) 섹션을 참조하세요.

1. 파라미터 그룹에서 다음과 같이 `recovery_min_apply_delay` 파라미터를 구성합니다.
   + 값을 원하는 지연 시간으로 밀리초 단위로 설정합니다. 예를 들어 1시간 지연의 경우 3,600,000입니다.
   + 허용되는 범위: 0\$186,400,000ms(0\$124시간)
   + 기본값: 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 누적이 발생할 수 있습니다. 스토리지가 가득 차지 않도록 복제본의 복제 상태와 소스의 스토리지 사용량을 모니터링해야 합니다.
+ 지연된 읽기 전용 복제본에 시스템 이벤트(예: 재부팅 또는 재시작)가 발생하면 구성된 지연 기간이 만료될 때까지 WAL 수신기 프로세스가 비활성 상태로 유지되는 `REPLICATION_ERROR` 상태로 전환됩니다. 이 동작으로 인해 소스 인스턴스에 WAL이 누적되어 스토리지가 소진될 수 있습니다. 다음 예방 조치를 고려하세요.
  + 소스 인스턴스의 스토리지 사용률을 모니터링하도록 CloudWatch 경보를 구성합니다.
  + 스토리지 오토 스케일링을 활성화하여 예상치 못한 WAL 증가를 처리합니다.
  + 복제 슬롯당 WAL 보존을 제한하도록 소스 인스턴스의 `max_slot_wal_keep_size` 파라미터를 설정합니다.
  + 복제 지연 및 슬롯 상태를 정기적으로 모니터링합니다.
+ 지연 시간이 길어지면 복제본에 대한 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 다중 AZ 클러스터(인바운드 및 아웃바운드 복제 모두 포함)
  + 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 Optimized Reads로 RDS for PostgreSQL 쿼리 성능 개선
<a name="USER_PostgreSQL.optimizedreads"></a>

Amazon RDS Optimized Reads로 RDS for PostgreSQL의 쿼리 처리 속도를 높일 수 있습니다. RDS Optimized Reads를 사용하는 RDS for PostgreSQL DB 인스턴스 또는 다중 AZ DB 클러스터는 이를 사용하지 않는 것에 비해 쿼리 처리 속도가 최대 50% 더 빠릅니다.

**Topics**
+ [PostgreSQL의 RDS Optimized Reads 개요](#USER_PostgreSQL.optimizedreads-overview)
+ [RDS Optimized Reads 사용 사례](#USER_PostgreSQL.optimizedreads-use-cases)
+ [RDS Optimized Reads 모범 사례](#USER_PostgreSQL.optimizedreads-best-practices)
+ [RDS Optimized Reads 사용](#USER_PostgreSQL.optimizedreads-using)
+ [RDS Optimized Reads를 사용하는 DB 인스턴스 모니터링](#USER_PostgreSQL.optimizedreads-monitoring)
+ [PostgreSQL의 RDS Optimized Reads 제한 사항](#USER_PostgreSQL.optimizedreads-limitations)

## PostgreSQL의 RDS Optimized Reads 개요
<a name="USER_PostgreSQL.optimizedreads-overview"></a>

Optimized Reads는 NVMe 기반 DB 인스턴스 클래스를 사용하는 경우 RDS for PostgreSQL 버전 15.2 이상, 14.7 이상, 13.10 이상에서 기본적으로 사용할 수 있습니다. NVMe를 사용하는 인스턴스를 나타내는 하드웨어 사양은 [ DB 인스턴스 클래스의 하드웨어 사양](Concepts.DBInstanceClass.Summary.md) 섹션을 참조하세요.

RDS Optimized Reads가 켜져 있는 RDS for PostgreSQL DB 인스턴스 또는 다중 AZ DB 클러스터를 사용할 경우, Solid State Drive(SSD) 블록 수준 스토리지에 기반한 Non-Volatile Memory Express(NVMe)를 사용하여 최대 50% 더 빠른 쿼리 성능을 실현할 수 있습니다. PostgreSQL에서 생성된 임시 테이블을 로컬 스토리지에 배치하면 네트워크를 통해 EBS(Elastic Block Storage)로 향하는 트래픽을 줄여 쿼리 처리 속도를 높일 수 있습니다.

PostgreSQL에서 임시 객체는 세션 종료 시 자동으로 삭제되는 임시 네임스페이스에 할당됩니다. 삭제하는 동안 임시 네임스페이스는 테이블, 함수, 연산자 또는 확장 같은 스키마로 한정된 개체를 포함하여 세션에 종속된 모든 객체를 제거합니다.

RDS for PostgreSQL에서는 임시 객체가 저장되는 이 임시 작업 영역에 대해`temp_tablespaces` 파라미터가 구성됩니다.

다음 쿼리는 테이블스페이스의 이름과 위치를 반환합니다.

```
postgres=> show temp_tablespaces;
temp_tablespaces
---------------------
rds_temp_tablespace
(1 row)
```

`rds_temp_tablespace`는 NVMe 로컬 스토리지를 가리키는 RDS에서 구성한 테이블스페이스입니다. AWS Management Console을 사용하여 `rds_temp_tablespace` 이외의 테이블스페이스를 가리키도록 `Parameter group`에 있는 이 파라미터를 수정하면 Amazon EBS 스토리지로 언제든지 다시 전환할 수 있습니다. 자세한 내용은 [Amazon RDS에서 DB 파라미터 그룹의 파라미터 수정](USER_WorkingWithParamGroups.Modifying.md) 단원을 참조하십시오. SET 명령을 사용하여 세션 수준에서 `temp_tablespaces` 파라미터의 값을 `pg_default`로 수정할 수도 있습니다. 파라미터를 수정하면 임시 작업 영역이 Amazon EBS로 리디렉션됩니다. Amazon EBS로 다시 전환하면 RDS 인스턴스 또는 클러스터의 로컬 스토리지가 특정 SQL 작업을 수행하기에 충분한 용량이 아닐 때 도움이 됩니다.

```
postgres=> SET temp_tablespaces TO 'pg_default';
SET
```

```
postgres=> show temp_tablespaces;
            
 temp_tablespaces
------------------
 pg_default
```

## RDS Optimized Reads 사용 사례
<a name="USER_PostgreSQL.optimizedreads-use-cases"></a>

다음은 Optimized Reads가 도움이 될 수 있는 몇 가지 사용 사례입니다.
+ CTE(Common Table Expression), 파생된 테이블, 그룹화 작업을 포함하는 분석 쿼리.
+ 애플리케이션의 최적화되지 않은 쿼리를 처리하는 읽기 전용 복제본.
+ 항상 적절한 인덱스를 사용할 수 없는 GROUP BY 및 ORDER BY 같은 복잡한 작업이 포함된 온디맨드 또는 동적 보고 쿼리.
+ 내부 임시 테이블을 사용하는 기타 워크로드.
+ 정렬을 위한 `CREATE INDEX` 또는 `REINDEX` 작업입니다.

## RDS Optimized Reads 모범 사례
<a name="USER_PostgreSQL.optimizedreads-best-practices"></a>

RDS Optimized Reads에 대한 다음 모범 사례를 따릅니다.
+ 실행 중 인스턴스 스토어가 가득 차서 쿼리가 실패하는 경우에 대비하여 읽기 전용 쿼리의 재시도 로직을 추가합니다.
+ CloudWatch 지표 `FreeLocalStorage`를 사용하여 인스턴스 스토어에서 사용 가능한 스토리지 공간을 모니터링합니다. DB 인스턴스 또는 다중 AZ DB 클러스터의 워크로드로 인해 인스턴스 스토어가 한도에 도달하면 더 큰 DB 인스턴스 클래스를 사용하도록 수정하세요.

## RDS Optimized Reads 사용
<a name="USER_PostgreSQL.optimizedreads-using"></a>

단일 AZ DB 인스턴스 배포, 다중 AZ DB 인스턴스 배포 또는 다중 AZ DB 클러스터 배포에서 NVMe 기반 DB 인스턴스 클래스 중 하나를 사용하여 RDS for PostgreSQL DB 인스턴스를 프로비저닝하면 DB 인스턴스는 자동으로 RDS Optimized Reads를 사용합니다.

다중 AZ 배포에 대한 자세한 정보는 [Amazon RDS에 대한 다중 AZ 배포 구성 및 관리](Concepts.MultiAZ.md) 섹션을 참조하세요.

RDS Optimized Read를 켜려면 다음 중 하나를 수행합니다.
+ NVMe 기반 DB 인스턴스 클래스 중 하나를 사용하여 RDS for PostgreSQL DB 인스턴스 또는 다중 AZ DB 클러스터를 생성합니다. 자세한 내용은 [Amazon RDS DB 인스턴스 생성](USER_CreateDBInstance.md) 단원을 참조하십시오.
+ NVMe 기반 DB 인스턴스 클래스 중 하나를 사용하여 기존 RDS for PostgreSQL DB 인스턴스 또는 다중 AZ DB 클러스터를 수정합니다. 자세한 내용은 [Amazon RDS DB 인스턴스 수정](Overview.DBInstance.Modifying.md) 단원을 참조하십시오.

RDS Optimized Reads는 로컬 NVMe SSD 스토리지가 있는 DB 인스턴스 클래스 중 하나 이상이 지원되는 모든 AWS 리전에서 사용 가능합니다. 자세한 내용은 [DB 인스턴스 클래스](Concepts.DBInstanceClass.md) 단원을 참조하십시오.

최적화되지 않은 읽기 RDS 인스턴스로 다시 전환하려면 RDS 인스턴스 또는 클러스터의 DB 인스턴스 클래스를 데이터베이스 워크로드에 대해 EBS 스토리지만 지원하는 유사한 인스턴스 클래스로 수정하세요. 예를 들어, 현재 DB 인스턴스 클래스가 db.r6gd.4xlarge인 경우 db.r6g.4xlarge를 선택하여 다시 전환합니다. 자세한 내용은 [Amazon RDS DB 인스턴스 수정](Overview.DBInstance.Modifying.md) 단원을 참조하십시오.

## RDS Optimized Reads를 사용하는 DB 인스턴스 모니터링
<a name="USER_PostgreSQL.optimizedreads-monitoring"></a>

다음 CloudWatch 지표를 사용하여 RDS Optimized Reads를 사용하는 DB 인스턴스를 모니터링할 수 있습니다.
+ `FreeLocalStorage`
+ `ReadIOPSLocalStorage`
+ `ReadLatencyLocalStorage`
+ `ReadThroughputLocalStorage`
+ `WriteIOPSLocalStorage`
+ `WriteLatencyLocalStorage`
+ `WriteThroughputLocalStorage`

이러한 지표는 사용 가능한 인스턴스 스토어 스토리지, IOPS 및 처리량(throughput)에 대한 데이터를 제공합니다. 이러한 지표에 대한 자세한 내용은 [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 Optimized Reads 제한 사항
<a name="USER_PostgreSQL.optimizedreads-limitations"></a>

PostgreSQL의 RDS Optimized Reads에는 다음과 같은 제한 사항이 적용됩니다.
+ 인스턴스 스토어가 가득 차면 트랜잭션이 실패할 수 있습니다.

# Amazon RDS에서 PostgreSQL로 데이터 가져오기
<a name="PostgreSQL.Procedural.Importing"></a>

Amazon RDS로 이동하려는 기존 PostgreSQL 배포가 있다고 가정하세요. 작업의 복잡성은 데이터베이스의 크기와 전송하는 데이터베이스 객체 유형에 따라 다릅니다. 예를 들어 프로시저 및 트리거와 함께 기가바이트 규모의 데이터세트가 데이터베이스에 저장되어 있다고 가정하겠습니다. 이러한 데이터베이스는 트리거나 프로시저 없이 근소한 메가바이트 규모의 테스트 데이터가 저장된 데이터베이스보다 더욱 복잡할 가능성이 높습니다.

다음과 같은 경우에는 기본 PostgreSQL 데이터베이스 마이그레이션 도구를 사용하는 것이 좋습니다.
+ 같은 유형의 마이그레이션을 수행합니다. 이 경우 대상 데이터베이스와 동일한 데이터베이스 엔진으로 데이터베이스에서 마이그레이션합니다.
+ 전체 데이터베이스를 마이그레이션합니다.
+ 기본 도구를 사용하여 최소한의 가동 중지로 시스템을 마이그레이션할 수 있습니다.

대부분의 다른 경우에는 AWS Database Migration Service(AWS DMS)를 사용하여 데이터베이스 마이그레이션을 수행하는 것이 최선의 방식입니다. AWS DMS는 가동 중지 없이 데이터베이스를 마이그레이션할 수 있으며 대부분의 데이터베이스 엔진에서는 대상 데이터베이스로 전환할 준비가 될 때까지 지속적으로 복제를 계속할 수 있습니다. 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)를 참조하세요.

*가져오기에 대해서만* 다음 설정을 포함하도록 DB 파라미터 그룹을 수정합니다. 파라미터 설정을 테스트하여 DB 인스턴스 크기에 가장 효율적인 설정을 찾아야 합니다. 또한 가져오기가 완료된 후 이들 파라미터를 프로덕션 값으로 되돌려야 합니다.

DB 인스턴스 설정을 다음과 같이 수정합니다.
+ DB 인스턴스 백업 비활성화(backup\$1retention을 0으로 설정).
+ Multi-AZ 비활성화.

다음 설정을 포함하도록 DB 파라미터 그룹을 수정합니다. 이들 설정은 데이터를 가져올 때만 사용해야 합니다. 파라미터 설정을 테스트하여 DB 인스턴스 크기에 가장 효율적인 설정을 찾아야 합니다. 또한 가져오기가 완료된 후 이들 파라미터를 프로덕션 값으로 되돌려야 합니다.


| 파라미터 | 가져오기 시 권장 값 | 설명 | 
| --- | --- | --- | 
|  `maintenance_work_mem`  |  524288, 1048576, 2097152 또는 4194304(KB). 이들 설정은 512MB, 1GB, 2GB 및 4GB에 해당합니다.  |  이 설정의 값은 호스트 크기에 따라 달라집니다. 이 파라미터는 CREATE INDEX 문에서 사용되며 각 병렬 명령은 이 크기의 메모리를 사용할 수 있습니다. 이 값을 너무 높게 설정하여 메모리가 부족해지지 않도록 최선의 값을 계산합니다.  | 
|  `max_wal_size`  |  256(버전 9.6), 4096(버전 10 이상)  |  자동 체크포인트 중에 WAL이 증가할 수 있는 최대 크기입니다. 이 파라미터를 늘리면 충돌 복구에 소요되는 시간이 늘어날 수 있습니다. 이 파라미터는 PostgreSQL 9.6 이상에서 `checkpoint_segments`를 대체합니다. PostgreSQL 버전 9.6의 경우 이 값은 16MB 단위입니다. 이후 버전의 경우 이 값은 1MB 단위입니다. 예를 들어 버전 9.6에서 128은 각각 16MB 크기인 128개의 청크를 의미합니다. 버전 12.4에서 2048는 각각 1MB 크기인 2048개의 청크를 의미합니다.  | 
|  `checkpoint_timeout`  |  1800  |  이 설정의 값은 WAL 교체 빈도를 줄일 수 있습니다.  | 
|  `synchronous_commit`  |  Off  |  쓰기 속도를 높이려면 이 설정을 비활성화합니다. 이 파라미터를 끄면 서버 충돌 시 데이터 손실 위험이 증가합니다(FSYNC를 끄지 않음).  | 
|  `wal_buffers`  |   8192  |  이 값은 8KB 단위입니다. 이는 다시 WAL 생성 속도에 도움이 됩니다.  | 
|  `autovacuum`  |  0  |  리소스를 사용하지 않으므로 데이터를 로드하는 동안에는 PostgreSQL auto-vacuum 파라미터를 비활성화합니다.  | 

이런 설정과 함께 `pg_dump -Fc`(압축) 또는 `pg_restore -j`(병렬) 명령을 사용합니다.

**참고**  
PostgreSQL의 `pg_dumpall` 명령을 사용하려면 DB 인스턴스를 생성할 때 부여되지 않은 super\$1user 권한이 필요하며, 따라서 이 명령은 데이터 가져오기에 사용할 수 없습니다.

**Topics**
+ [Amazon EC2 인스턴스에서 PostgreSQL 데이터베이스 가져오기](PostgreSQL.Procedural.Importing.EC2.md)
+ [\$1copy 명령을 사용하여 PostgreSQL DB 인스턴스의 테이블로 데이터 가져오기](PostgreSQL.Procedural.Importing.Copy.md)
+ [PostgreSQL DB 인스턴스용 RDS로 Amazon S3 데이터 가져오기](USER_PostgreSQL.S3Import.md)
+ [DB 인스턴스 간에 PostgreSQL 데이터베이스 전송](PostgreSQL.TransportableDB.md)

# Amazon EC2 인스턴스에서 PostgreSQL 데이터베이스 가져오기
<a name="PostgreSQL.Procedural.Importing.EC2"></a>

Amazon EC2 인스턴스상의 PostgreSQL 서버에 데이터가 있는데 이를 PostgreSQL DB 인스턴스로 이동하려는 경우 다음 프로세스를 사용하여 데이터를 마이그레이션할 수 있습니다.

1. 로드할 데이터를 포함한 pg\$1dump를 사용하여 파일 만들기

1. 대상 DB 인스턴스 만들기

1. *psql*을 사용하여 DB 인스턴스에서 데이터베이스를 만들고 데이터 로드

1. DB 인스턴스의 DB 스냅샷 만들기

다음 섹션에서는 위에 나열된 각 단계에 대한 자세한 내용을 제공합니다.

## 1단계: 로드할 데이터를 포함하여 pg\$1dump로 파일 생성
<a name="PostgreSQL.Procedural.Importing.EC2.Step1"></a>

`pg_dump` 유틸리티는 COPY 명령을 사용하여 PostgreSQL 데이터베이스의 스키마와 데이터 덤프를 만듭니다. `pg_dump`에 의해 생성되는 덤프 스크립트는 같은 이름을 가진 데이터베이스로 데이터를 로드하고 테이블, 인덱스 및 외래 키를 다시 만듭니다. `pg_restore` 명령과 `-d` 파라미터를 사용하여 데이터를 다른 이름의 데이터베이스로 복원할 수 있습니다.

데이터 덤프를 만들기 전, 대상 DB 인스턴스에서 개수를 확인할 수 있도록 행 개수를 확인하기 위해 덤프할 테이블을 쿼리해야 합니다.

 다음 명령을 실행하면 mydb2라는 데이터베이스에 대해 mydb2dump.sql이라는 덤프 파일이 생성됩니다.

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

## 2단계: 대상 DB 인스턴스 만들기
<a name="PostgreSQL.Procedural.Importing.EC2.Step2"></a>

Amazon RDS 콘솔, AWS CLI 또는 API를 사용하여 대상 PostgreSQL DB 인스턴스를 만듭니다. 백업 보존 설정을 0으로 지정하여 인스턴스를 만들고 다중 AZ를 비활성화합니다. 그러면 데이터를 더 빠르게 가져올 수 있습니다. 데이터를 덤프하려면 먼저 인스턴스에 데이터베이스를 생성해야 합니다. 데이터베이스 이름은 덤프 데이터가 저장된 데이터베이스와 동일하게 지정할 수 있습니다. 그렇지 않으면 다른 이름으로 지정하는 것도 가능합니다. 이 경우에는 `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을 사용하여 DB 인스턴스에서 데이터베이스를 만들고 데이터 로드
<a name="PostgreSQL.Procedural.Importing.EC2.Step3"></a>

pg\$1dump 명령을 실행할 때 사용한 것과 같은 연결을 사용하여 대상 DB 인스턴스에 연결하고 데이터베이스를 다시 만들 수 있습니다. *psql*을 사용할 때는 마스터 사용자 이름과 마스터 암호를 사용하여 DB 인스턴스에 데이터베이스를 만들 수 있습니다.

다음 예제에서는 *psql*과 mydb2dump.sql이라는 덤프 파일을 사용하여 mypginstance라는 PostgreSQL DB 인스턴스에 mydb2라는 데이터베이스를 만듭니다.

대상 LinuxmacOS, 또는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단계: DB 인스턴스의 DB 스냅샷 만들기
<a name="PostgreSQL.Procedural.Importing.EC2.Step4"></a>

데이터가 DB 인스턴스로 로드된 것을 확인했으면, 대상 PostgreSQL DB 인스턴스의 DB 스냅샷을 만드는 것이 좋습니다. DB 스냅샷은 DB 인스턴스를 알려진 상태로 복원하는 데 사용할 수 있는 DB 인스턴스의 완전한 백업입니다. 로드 직후에 생성된 DB 스냅샷은 사고 발생 시 데이터를 다시 로드하지 않아도 됩니다. 또한 이러한 스냅샷을 사용하여 새 DB 인스턴스를 시드할 수 있습니다. DB 스냅샷 생성에 대한 정보는 [Amazon RDS의 단일 AZ DB 인스턴스에 대한 DB 스냅샷 생성](USER_CreateSnapshot.md) 단원을 참조하세요.

# \$1copy 명령을 사용하여 PostgreSQL DB 인스턴스의 테이블로 데이터 가져오기
<a name="PostgreSQL.Procedural.Importing.Copy"></a>

PostgreSQL `\copy` 명령은 `psql` 대화형 클라이언트 도구에서 사용할 수 있는 메타 명령입니다. `\copy`를 사용하여 RDS for PostgreSQL DB 인스턴스의 테이블로 데이터를 가져올 수 있습니다. `\copy` 명령을 사용하려면 먼저 `\copy`가 대상 DB 인스턴스에 복사할 데이터의 대상을 갖도록 테이블 구조를 생성해야 합니다.

`\copy`를 사용하여 클라이언트 워크스테이션으로 내보내고 저장된 파일과 같은 쉼표로 구분된 값(CSV) 파일에서 데이터를 로드할 수 있습니다.

CSV 데이터를 대상 RDS for PostgreSQL DB 인스턴스로 가져오려면 먼저 `psql`을 사용하여 대상 DB 인스턴스에 연결합니다.

```
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` 명령을 사용하여 데이터베이스 미리 보기 환경에서 새 DB 인스턴스를 생성합니다. 이 예제에서는 *source-table*을 원본 테이블 이름으로, *source-table.csv*를 .csv 파일로, *target-db*를 대상 데이터베이스로 사용합니다.

대상 LinuxmacOS, 또는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 설명서의 *메타 명령*(Meta-Commands) 섹션에서 [psql](http://www.postgresql.org/docs/current/static/app-psql.html) 페이지를 참조하세요.

# PostgreSQL DB 인스턴스용 RDS로 Amazon S3 데이터 가져오기
<a name="USER_PostgreSQL.S3Import"></a>

Amazon Simple Storage Service를 사용하여 저장된 데이터를 Aurora PostgreSQL DB 클러스터 인스턴스의 테이블로 가져올 수 있습니다. 이 작업을 수행하려면 먼저 RDS for PostgreSQL `aws_s3` 확장을 설치해야 합니다. 이 확장은 Amazon S3 버킷에서 데이터를 가져오는 데 사용하는 기능을 제공합니다. *버킷*은 객체 또는 파일에 대한 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 DB 인스턴스로 데이터 가져오기](USER_PostgreSQL.S3Import.FileFormats.md)
+ [함수 참조](USER_PostgreSQL.S3Import.Reference.md)

# aws\$1s3 확장 설치
<a name="USER_PostgreSQL.S3Import.InstallExtension"></a>

Amazon S3를 RDS for PostgreSQL DB 인스턴스와 함께 사용하려면 먼저 `aws_s3` 확장을 설치해야 합니다. 이 확장은 Amazon S3에서 데이터를 가져오기 위한 함수도 제공합니다. 또한 RDS for PostgreSQL DB 인스턴스에서 Amazon S3 버킷으로 데이터를 내보내는 기능도 제공합니다. 자세한 내용은 [RDS for PostgreSQL DB 인스턴스에서 Amazon S3로 데이터 내보내기](postgresql-s3-export.md) 단원을 참조하세요. `aws_s3` 확장은 필요할 때 자동으로 설치되는 `aws_commons` 확장의 일부 도우미 기능에 따라 다릅니다.

**`aws_s3` 확장을 설치하려면**

1. psql(또는 PGAdmin)을 사용하여 RDS for PostgreSQL DB 인스턴스에 `rds_superuser` 권한을 가진 사용자로 연결합니다. 설정 과정에서 기본 이름을 계속 사용했다면 `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 DB 인스턴스의 테이블 이름과 버킷 이름, 파일 경로, 파일 유형 및 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 버킷 및 가져올 데이터에 대한 세부 정보를 가져옵니다. 이 작업을 수행하려면 [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)에서 Amazon S3 콘손을 열고 **버킷**을 선택합니다. 목록에서 데이터가 포함된 버킷을 찾습니다. 버킷을 선택하고 객체 개요 페이지를 연 다음 속성을 선택합니다.

   버킷 이름, 경로, AWS 리전, 파일 형식을 적어 둡니다. IAM 역할을 통해 Amazon S3에 대한 액세스를 설정하는 Amazon 리소스 이름(ARN) 이 나중에 필요합니다. 자세한 내용은 [Amazon S3 버킷에 대한 액세스 권한 설정](USER_PostgreSQL.S3Import.AccessPermission.md) 단원을 참조하세요. 다음 그림에 예가 나와 있습니다.  
![\[Amazon S3 버킷에 있는 파일 객체의 이미지입니다.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/aws_s3_import-export_s3_bucket-info.png)

1. AWS CLI 명령 `aws s3 cp`를 사용하여 Amazon S3 버킷의 데이터 경로를 확인할 수 있습니다. 정보가 정확하면 이 명령이 Amazon S3 파일의 복사본을 다운로드합니다.

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

1. Amazon S3 버킷의 파일에 대한 액세스를 허용하도록 RDS for PostgreSQL DB 인스턴스에 대한 권한을 설정합니다. 이렇게 하려면 AWS Identity and Access Management(IAM) 역할 또는 보안 자격 증명을 사용합니다. 자세한 내용은 [Amazon S3 버킷에 대한 액세스 권한 설정](USER_PostgreSQL.S3Import.AccessPermission.md) 단원을 참조하세요.

1. 경로 및 수집된 기타 Amazon S3 객체 세부 정보(2단계 참조)를 `create_s3_uri` 함수에 제공하여 Amazon 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 DB 인스턴스로 데이터 가져오기](USER_PostgreSQL.S3Import.FileFormats.md) 섹션을 참조하세요.

# Amazon S3 버킷에 대한 액세스 권한 설정
<a name="USER_PostgreSQL.S3Import.AccessPermission"></a>

Amazon S3 파일에서 데이터를 가져오려면 RDS for PostgreSQL DB 인스턴스에 파일이 저장된 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 DB 인스턴스에 파일이 저장된 Amazon S3 버킷에 액세스할 수 있는 권한을 부여합니다. 그러면 추가 자격 증명 정보를 관리하거나 [aws\$1s3.table\$1import\$1from\$1s3](USER_PostgreSQL.S3Import.Reference.md#aws_s3.table_import_from_s3) 함수 호출에서 제공할 필요가 없습니다.

이렇게 하려면 Amazon S3 버킷에 대한 액세스 권한을 부여하는 IAM 정책을 생성합니다. IAM 역할을 생성하여 정책을 역할에 연결합니다. 그런 다음 IAM 역할을 DB 인스턴스에 할당합니다.

**IAM 역할을 통해 Amazon S3에 액세스할 수 있는 권한을 PostgreSQL DB 인스턴스용 RDS에 부여하려면**

1. IAM 정책을 생성합니다.

   이 정책은 RDS for PostgreSQL DB 인스턴스가 Amazon S3에 액세스할 수 있도록 허용하는 버킷 및 객체 권한을 부여합니다.

   정책에 다음과 같은 필수 작업을 포함하여 Amazon S3 버킷에서 Amazon RDS로의 파일 전송을 허용합니다.
   + `s3:GetObject` 
   + `s3:ListBucket` 

   정책에 다음 리소스를 포함하여 Amazon S3 버킷 및 그 안의 객체를 식별합니다. 다음은 Amazon S3에 액세스하기 위한 Amazon 리소스 이름(ARN) 형색입니다.
   + arn:aws:s3:::*amzn-s3-demo-bucket*
   + arn:aws:s3:::*amzn-s3-demo-bucket*/\$1

   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-import-policy`라는 IAM 정책을 만듭니다. *amzn-s3-demo-bucket*이라는 버킷에 대한 액세스 권한을 부여합니다.
**참고**  
이 명령에서 반환되는 정책 Amazon 리소스 이름(ARN)을 적어 둡니다. IAM 역할에 정책을 연결할 때 이후 단계에 ARN이 필요합니다.  
**Example**  

   대상 LinuxmacOS, 또는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**  

   대상 LinuxmacOS, 또는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**  

   대상 LinuxmacOS, 또는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 역할을 DB 인스턴스에 추가합니다.

   이렇게 하려면 다음에 설명한 대로 AWS Management Console 또는 AWS CLI를 사용합니다.

### 콘솔
<a name="collapsible-section-1"></a>

**콘솔을 사용하여 PostgreSQL DB 인스턴스에 대해 IAM 역할을 추가하려면**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 세부 정보를 표시하고자 하는 PostgreSQL DB 인스턴스 이름을 선택합니다.

1. **연결성 및 보안(Connectivity & security)** 탭에 있는 **IAM 역할 관리(Manage IAM roles)** 섹션의 **이 인스턴스에 IAM 역할 추가(Add IAM roles to this cluster/instance)**에서 추가할 역할을 선택합니다.

1. **기능**에서 **s3Import**를 선택합니다.

1. [**Add role**]을 선택합니다.

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

**CLI를 사용하여 PostgreSQL DB 인스턴스에 대해 IAM 역할을 추가하려면**
+ 다음 명령을 사용해 `my-db-instance`라는 PostgreSQL DB 인스턴스에 역할을 추가합니다. *`your-role-arn`*을 이전 단계에서 기록한 정책 ARN으로 교체합니다. `s3Import` 옵션의 값에 대해 `--feature-name`를 사용합니다.  
**Example**  

  대상 LinuxmacOS, 또는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 DB 인스턴스에 대한 IAM 역할을 추가하려면 [ AddRoleToDBInstance](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_AddRoleToDBInstance.html) 작업을 직접적으로 호출합니다.

## 보안 자격 증명을 사용해 Amazon S3 버킷에 액세스
<a name="USER_PostgreSQL.S3Import.Credentials"></a>

원할 경우 IAM 역할을 사용하는 대신 보안 자격 증명을 사용해 Amazon S3 버킷에 대한 액세스 권한을 부여여할 수 있습니다. [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 사용 설명서](https://docs.aws.amazon.com/AmazonS3/latest/userguide/troubleshooting.html)의 *Amazon S3 문제 해결*
+ *IAM 사용 설명서*의 [Amazon S3 문제 해결 및 IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_iam-s3.html)

# Amazon S3에서 RDS for PostgreSQL DB 인스턴스로 데이터 가져오기
<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) 단원을 참조하세요.

**참고**  
다음 예에서는 Amazon S3 버킷에 대한 액세스 권한을 허용하기 위해 IAM 역할 메서드를 사용합니다. 따라서 `aws_s3.table_import_from_s3` 함수 호출에는 자격 증명 파라미터가 포함되지 않습니다.

다음은 대표적인 예를 보여줍니다.

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

파라미터는 다음과 같습니다.
+ `t1` – 데이터를 복사할 PostgreSQL DB 인스턴스의 테이블에 지정된 이름입니다.
+ `''` – 데이터베이스 테이블의 열 목록입니다(선택 사항). 이 파라미터를 사용해 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>

다음 예에서는 gzip으로 압축된 Amazon S3에서 파일을 가져오는 방법을 보여줍니다. 가져오는 파일에 다음과 같은 Amazon S3 메타데이터가 있어야 합니다.
+ 키: `Content-Encoding`
+ 값: `gzip`

AWS Management Console을 사용하여 파일을 업로드하는 경우 일반적으로 시스템에서 메타데이터를 적용합니다. AWS Management Console, 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 파일을 PostgreSQL DB 인스턴스용 RDS로 가져옵니다.

```
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>

다음 예에서는 Windows-1252 인코딩이 있는 Amazon S3에서 파일을 가져오는 방법을 보여줍니다.

```
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 DB 인스턴스에 대해 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) 단원을 참조하십시오.

 *options*   
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 리전 이름 및 연결된 값의 목록은 [리전, 가용 영역 및 로컬 영역](Concepts.RegionsAndAvailabilityZones.md) 섹션을 참조하십시오.

 *credentials*   
가져오기 작업에 사용할 다음 자격 증명을 포함하는 `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 DB 인스턴스에 대해 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>

*버킷*  
파일이 들어 있는 Amazon S3 버킷의 이름이 포함된 텍스트 문자열입니다.

*file\$1path*  
파일 경로를 포함한 Amazon S3 파일 이름이 포함된 텍스트 문자열입니다.

*리전*  
파일의 AWS 리전 위치를 식별하는 텍스트 문자열입니다. AWS 리전 이름 및 연결된 값의 목록은 [리전, 가용 영역 및 로컬 영역](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>

Amazon S3 파일 정보를 저장할 `aws_commons._s3_uri_1` 구조를 생성합니다. `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>

*버킷*  
파일의 Amazon S3 버킷 이름이 포함된 필수 텍스트 문자열입니다.

*file\$1path*  
파일 경로를 포함한 Amazon S3 파일 이름이 포함된 필수 텍스트 문자열입니다.

*리전*  
파일이 위치한 AWS 리전이 포함된 필수 텍스트 문자열입니다. AWS 리전 이름 및 연결된 값의 목록은 [리전, 가용 영역 및 로컬 영역](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`을 제공하는 경우 임시 자격 증명을 사용할 수 있습니다.

# DB 인스턴스 간에 PostgreSQL 데이터베이스 전송
<a name="PostgreSQL.TransportableDB"></a>

Amazon RDS에 대해 PostgreSQL 전송 가능 데이터베이스를 사용하여 두 DB 인스턴스 간에 PostgreSQL 데이터베이스를 전송할 수 있습니다. 이 방법은 서로 다른 DB 인스턴스 간에 대규모 데이터베이스를 마이그레이션하는 매우 빠른 방법입니다. 이 방법을 사용하여 DB 인스턴스가 모두 동일한 메이저 버전의 PostgreSQL을 실행해야 합니다.

이 기능을 사용하려면 소스와 대상 DB 인스턴스 모두에 `pg_transport` 확장을 설치해야 합니다. `pg_transport` 확장은 최소한의 처리로 데이터베이스 파일을 이동하는 물리적 전송 메커니즘을 제공합니다. 이 메커니즘은 기존의 덤프 및 로드 프로세스보다 적은 가동 중지로 훨씬 빠르게 데이터를 이동합니다.

**참고**  
PostgreSQL 전송 가능 데이터베이스는 RDS for PostgreSQL 11.5 이상 및 RDS for PostgreSQL 버전 10.10 이상에서 사용할 수 있습니다.

RDS for PostgreSQL DB 인스턴스에서 다른 RDS로 PostgreSQL DB 인스턴스를 전송하려면 먼저 [ 전송을 위해 DB 인스턴스 설정](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 전송 가능 데이터베이스 기능은 소스 DB 인스턴스에서 대상으로 데이터베이스를 가져오는 풀링 모델을 사용합니다. `transport.import_from_server` 함수는 대상 DB 인스턴스에서 전송 중 데이터베이스를 생성합니다. 전송 기간 동안에는 대상 DB 인스턴스에서 전송 중 데이터베이스에 액세스할 수 없습니다.

전송이 시작되면 소스 데이터베이스의 모든 현재 세션이 종료됩니다. 소스 DB 인스턴스의 소스 데이터베이스 이외의 모든 데이터베이스는 전송의 영향을 받지 않습니다.

소스 데이터베이스는 특수한 읽기 전용 모드로 설정됩니다. 이 모드에 있는 동안 소스 데이터베이스에 연결하고 읽기 전용 쿼리를 실행할 수 있습니다. 그러나 쓰기 가능 쿼리 및 일부 다른 유형의 명령은 차단됩니다. 전송되는 특정 소스 데이터베이스만 이러한 제한의 영향을 받습니다.

전송 중에는 대상 DB 인스턴스를 특정 시점으로 복원할 수 없습니다. 전송은 트랜잭션이 아니며 PostgreSQL 미리 쓰기 로그를 사용하여 변경 사항을 기록하지 않기 때문입니다. 대상 DB 인스턴스에 자동 백업이 활성화되어 있으면 전송이 완료된 후 백업이 자동으로 수행됩니다. 특정 시점으로 복원은 백업이 완료된 *후* 일정 시간 동안 사용할 수 있습니다.

전송이 실패하면 `pg_transport` 확장은 소스 및 대상 DB 인스턴스에 대한 모든 변경을 취소하려고 시도합니다. 여기에는 대상에 부분적으로 전송된 데이터베이스 제거가 포함됩니다. 실패 유형에 따라 소스 데이터베이스는 쓰기 가능 쿼리를 계속 거부할 수 있습니다. 이 경우 다음 명령을 사용하여 쓰기 가능 쿼리를 허용하십시오.

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

## PostgreSQL 전송 가능 데이터베이스 사용에 대한 제한 사항
<a name="PostgreSQL.TransportableDB.Limits"></a>

전송 가능 데이터베이스에는 다음과 같은 제한 사항이 있습니다.
+ **읽기 전용 복제본** – 읽기 전용 복제본 또는 읽기 전용 복제본의 상위 인스턴스에서 전송 가능 데이터베이스를 사용할 수 없습니다.
+ **지원되지 않는 열 유형** – 이 방법으로 전송하려는 데이터베이스 테이블에서는 `reg` 데이터 유형을 사용할 수 없습니다. 이러한 유형은 전송 중에 자주 변경되는 시스템 카탈로그 객체 ID(OID)에 따라 다릅니다.
+ **테이블스페이스** – 모든 소스 데이터베이스 객체는 기본 `pg_default` 테이블스페이스에 있어야 합니다.
+ **호환성** – 소스 및 대상 DB 인스턴스는 모두 동일한 메이저 버전의 PostgreSQL을 실행해야 합니다.
+ **확장** - 소스 DB 인스턴스에는 `pg_transport`만 설치할 수 있습니다.
+ **역할 및 ACL** – 소스 데이터베이스의 액세스 권한 및 소유권 정보는 대상 데이터베이스로 전달되지 않습니다. 모든 데이터베이스 객체는 전송의 로컬 대상 사용자가 생성하고 소유합니다.
+ **동시 전송** - 작업자 프로세스가 올바르게 구성된 경우 단일 DB 인스턴스에서 가져오기와 내보내기를 포함하여 최대 32개의 동시 전송을 지원할 수 있습니다.
+ **RDS for PostgreSQL DB 인스턴스 전용** - RDS for PostgreSQL DB 인스턴스에 대해 PostgreSQL 전송 가능 데이터베이스만 지원할 수 있습니다. Amazon EC2에서 실행되는 온프레미스 데이터베이스 또는 데이터베이스에는 사용할 수 없습니다.

# PostgreSQL 데이터베이스를 전송하도록 설정
<a name="PostgreSQL.TransportableDB.Setup"></a>

시작하기 전에 RDS for PostgreSQL DB 인스턴스가 다음 요구 사항을 충족하는지 확인하세요.
+ 소스 및 대상 RDS for PostgreSQL DB 인스턴스는 동일한 버전의 PostgreSQL을 실행해야 합니다.
+ 대상 DB에는 전송할 소스 DB와 같은 이름의 데이터베이스를 가질 수 없습니다.
+ 전송을 실행하는 데 사용하는 계정은 소스 DB와 대상 DB 모두에 대한 `rds_superuser` 권한이 필요합니다.
+ 소스 DB 인스턴스의 보안 그룹은 대상 DB 인스턴스의 인바운드 액세스를 허용해야 합니다. 소스 및 대상 DB 인스턴스가 VPC에 있는 경우 이미 해당 경우일 수 있습니다. 보안 그룹에 대한 자세한 내용은 [보안 그룹을 통한 액세스 제어](Overview.RDSSecurityGroups.md)를(을) 참조하세요.

소스 DB 인스턴스에서 대상 DB 인스턴스로 데이터베이스를 전송하려면 각 인스턴스와 연결된 DB 파라미터 그룹을 몇 번 변경해야 합니다. 즉, 소스 DB 인스턴스에 대한 사용자 지정 DB 파라미터 그룹을 생성하고 대상 DB 인스턴스에 대한 사용자 지정 DB 파라미터 그룹을 생성해야 합니다.

**참고**  
DB 인스턴스가 이미 사용자 지정 DB 파라미터 그룹을 사용하여 구성된 경우 다음 절차의 2단계부터 시작할 수 있습니다.

**데이터베이스 전송을 위한 사용자 지정 DB 그룹 파라미터 구성**

다음 단계에서는 `rds_superuser` 권한을 가진 계정을 사용하세요.

1. 소스 및 대상 DB 인스턴스가 기본 DB 파라미터 그룹을 사용하는 경우 인스턴스에 적합한 버전을 사용하여 사용자 지정 DB 파라미터 그룹을 생성해야 합니다. 이렇게 하면 여러 파라미터의 값을 변경할 수 있습니다. 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 섹션을 참조하세요.

1. 사용자 지정 DB 파라미터 그룹에서 다음 파라미터 값을 변경합니다.
   + `shared_preload_libraries` - 라이브러리 목록에 `pg_transport`를 추가합니다.
   + `pg_transport.num_workers` - 기본값은 3입니다. 데이터베이스에 필요한 경우 이 값을 늘리거나 줄입니다. 200GB 데이터베이스의 경우 8이하의 값이 좋습니다. 이 파라미터의 기본값을 늘리면 `max_worker_processes` 값도 늘려야 합니다.
   + `pg_transport.work_mem` - 기본값은 PostgreSQL 버전에 따라 128MB 또는 256MB입니다. 기본 설정은 일반적으로 변경되지 않을 수 있습니다.
   + `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 DB 인스턴스 및 대상 인스턴스를 재부팅하면 파라미터 설정이 적용됩니다.

1. RDS for PostgreSQL 소스 DB 인스턴스에 연결합니다.

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

1. DB 인스턴스의 퍼블릭 스키마에서 불필요한 확장을 제거합니다. 실제 전송 작업 중에만 `pg_transport` 확장이 허용됩니다.

1. 다음과 같이 `pg_transport` 확장을 설치합니다.

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

1. RDS for PostgreSQL 대상 DB 인스턴스에 연결합니다. 불필요한 확장을 제거한 다음 `pg_transport` 확장을 설치합니다.

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

# PostgreSQL 데이터베이스를 소스에서 대상으로 전송
<a name="PostgreSQL.TransportableDB.Transporting"></a>

[PostgreSQL 데이터베이스를 전송하도록 설정](PostgreSQL.TransportableDB.Setup.md)에 설명된 프로세스를 완료한 후에는 전송을 시작할 수 있습니다. 이렇게 하려면 대상 DB 인스턴스에서 `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)
```

INFO 행은 `pg_transport.timing` 파라미터가 기본값인 `true`로 설정하므로 출력됩니다. 다음과 같이 명령을 실행하고 소스 데이터베이스를 대상으로 가져올 때 `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
```

"파일 데이터를 다운로드 실패" 오류 메시지는 작업자 프로세스 수가 데이터베이스 크기에 맞게 올바르게 설정되지 않았음을 나타냅니다. `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 데이터베이스를 소스 DB 인스턴스에서 대상 DB 인스턴스로 가져와서 전송합니다. 물리적 데이터베이스 연결 전송 메커니즘을 사용하여 이를 수행합니다.

전송을 시작하기 전에 이 함수는 소스 및 대상 DB 인스턴스가 동일한 버전이며 마이그레이션을 위해 호환되는지 확인합니다. 또한 대상 DB 인스턴스 소스에 충분한 공간이 있는지 확인합니다.

**구문**

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

**반환 값**

없음.

**Parameters**

다음 표에서 `transport.import_from_server` 함수 파라미터에 대한 설명을 확인할 수 있습니다.


****  

| 파라미터 | 설명 | 
| --- | --- | 
| host |  소스 DB 인스턴스의 엔드포인트입니다.  | 
| port | 소스 DB 인스턴스의 포트를 나타내는 정수입니다.PostgreSQL DB 인스턴스는 종종 포트 5432를 사용합니다. | 
| username |  소스 DB 인스턴스의 사용자입니다. 이 사용자는 `rds_superuser` 역할의 멤버여야 합니다.  | 
| password |  소스 DB 인스턴스의 사용자 암호입니다.  | 
| database |  전송할 소스 DB 인스턴스의 데이터베이스 이름입니다.  | 
| local\$1password |  대상 DB 인스턴스에 대한 현재 사용자의 로컬 암호입니다. 이 사용자는 `rds_superuser` 역할의 멤버여야 합니다.  | 
| dry\$1run | 모의 실습 수행 여부를 지정하는 선택적 부울 값입니다. 기본값은 `false`이며 이는 전송이 진행됨을 의미합니다.실제 전송을 수행하지 않고 소스와 대상 DB 인스턴스 간의 호환성을 확인하려면 dry\$1run을 true로 설정하십시오. | 

예****

관련 예제는 [PostgreSQL 데이터베이스를 소스에서 대상으로 전송](PostgreSQL.TransportableDB.Transporting.md) 섹션을 참조하세요

# 전송 가능한 데이터베이스 파라미터 참조
<a name="PostgreSQL.TransportableDB.Parameters"></a>

`pg_transport` 확장 동작을 제어하는 몇 가지 파라미터입니다. 다음에서 이러한 파라미터에 대한 설명을 확인할 수 있습니다.

**`pg_transport.num_workers`**  
전송 프로세스에 사용할 작업자 수입니다. 기본값은 3입니다. 유효한 값은 1 – 32입니다. 대용량 데이터베이스 전송에서도 일반적으로 8명 미만 작업자가 필요합니다. 전송 중에 대상 DB 인스턴스의 이 설정 값은 대상 및 소스 모두에서 사용됩니다.

**`pg_transport.timing` **  
전송 중 타이밍 정보를 보고할지 여부를 지정합니다. 기본값은 `true`로, 타이밍 정보가 보고됩니다. 이 파라미터는 설정은 `true`로 두어 진행 상황을 모니터링할 수 있을 것을 권장합니다. 예제 출력은 [PostgreSQL 데이터베이스를 소스에서 대상으로 전송](PostgreSQL.TransportableDB.Transporting.md)을 참조하세요.

**`pg_transport.work_mem`**  
각 작업자에게 할당할 최대 메모리 양입니다. 기본값은 PostgreSQL 버전에 따라 131072킬로바이트(KB) 또는 262144KB(256MB)입니다. 최소값은 64MB(65,536KB)입니다. 유효한 값은 이진 base-2 단위로 나타낸 킬로바이트(KB)입니다(1KB = 1024바이트).  
전송 시 이 파라미터에 지정된 것보다 적은 메모리를 사용할 수 있습니다. 대용량 데이터베이스 전송에서도 일반적으로 작업자당 256MB(262144KB) 미만의 메모리가 필요합니다.

# RDS for PostgreSQL DB 인스턴스에서 Amazon S3로 데이터 내보내기
<a name="postgresql-s3-export"></a>

RDS for PostgreSQL DB 인스턴스에서 데이터를 쿼리하여 Amazon S3 버킷에 저장된 파일로 직접 내보낼 수 있습니다. 이 작업을 수행하려면 먼저 RDS for PostgreSQL `aws_s3` 확장을 설치해야 합니다. 이 확장은 쿼리 결과를 Amazon S3로 내보내는 데 사용하는 기능을 제공합니다. 다음에서는 확장 프로그램을 설치하는 방법과 Amazon S3로 데이터를 내보내는 방법을 확인할 수 있습니다.

**참고**  
Amazon S3로 계정 간 내보내기는 지원되지 않습니다.

현재 사용 가능한 모든 RDS 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 Management Console, AWS CLI 또는 Amazon RDS API를 사용하여 DB 스냅샷 데이터를 Amazon S3에 저장할 수 있습니다. 자세한 내용은 [Amazon S3 for Amazon RDS로 DB 스냅샷 데이터 내보내기](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 DB 인스턴스와 함께 사용하려면 먼저 `aws_s3` 확장을 설치해야 합니다. 이 확장은 RDS for PostgreSQL DB 인스턴스의 라이터 인스턴스에서 Amazon S3 버킷으로 데이터를 내보내는 기능을 제공합니다. Amazon S3에서 데이터를 가져오기 위한 함수도 제공합니다. 자세한 내용은 [PostgreSQL DB 인스턴스용 RDS로 Amazon S3 데이터 가져오기](USER_PostgreSQL.S3Import.md) 단원을 참조하세요. `aws_s3` 확장은 필요할 때 자동으로 설치되는 `aws_commons` 확장의 일부 도우미 기능에 따라 다릅니다.

**`aws_s3` 확장을 설치하려면**

1. psql(또는 PGAdmin)을 사용하여 RDS for PostgreSQL DB 인스턴스에 `rds_superuser` 권한을 가진 사용자로 연결합니다. 설정 과정에서 기본 이름을 계속 사용했다면 `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 버킷으로 내보내려면 다음 절차를 따르세요.

**데이터를 S3로 내보내려면**

1. 데이터를 내보내는 데 사용할 Amazon S3 파일 경로를 식별합니다. 이 프로세스에 대한 자세한 내용은 [내보낼 Amazon S3 파일 경로 지정](#postgresql-s3-export-file) 단원을 참조하십시오.

1. Amazon S3 버킷에 액세스할 수 있는 권한을 부여합니다.

   Amazon S3 파일로 데이터를 내보내려면 RDS for PostgreSQL DB 인스턴스에 내보내기 시 스토리지에 사용할 Amazon S3 버킷에 액세스할 수 있는 권한을 부여합니다. 여기에는 다음 단계가 포함됩니다.

   1. 내보낼 Amazon S3 버킷에 대한 액세스를 제공하는 IAM 정책을 생성합니다.

   1. IAM 역할 생성.

   1. 생성한 정책을 생성한 역할에 연결하십시오.

   1. 이 IAM 역할을 DB 인스턴스에 추가합니다.

   이 프로세스에 대한 자세한 내용은 [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 사용 설명서*의 [Creating a bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html) 및 [Working with objects](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-downloading-objects.html)를 참조하세요.
+ 파일 경로 – 파일 경로는 내보낸 데이터가 Amazon S3 버킷에서 저장되는 위치를 식별합니다. 파일 경로는 다음과 같이 구성됩니다.
  + 가상 폴더 경로를 식별하는 선택적 경로 접두사입니다.
  + 저장할 하나 이상의 파일을 식별하는 파일 접두사입니다. 내보내는 데이터가 클 경우 각각 최대 크기가 약 6GB인 여러 파일에 저장됩니다. 추가 파일 이름의 파일 접두사도 동일하지만 `_partXX`가 추가됩니다. `XX`는 2, 3 등을 나타냅니다.

  예를 들어 `exports` 폴더와 `query-1-export` 파일 접두사가 있는 파일 경로는 `/exports/query-1-export`입니다.
+ AWS 리전(선택 사항) – Amazon S3 버킷이 위치한 AWS 리전입니다. AWS 리전 값을 지정하지 않으면 Amazon RDS는 DB 인스턴스 내보내기와 동일한 AWS 리전의 Amazon S3에 파일을 저장합니다.
**참고**  
현재 AWS 리전은 내보내는 DB 인스턴스의 리전과 동일해야 합니다.

  AWS 리전 이름 및 연결된 값의 목록은 [리전, 가용 영역 및 로컬 영역](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 DB 인스턴스에 파일이 저장될 Amazon S3 버킷에 액세스할 수 있는 권한을 부여합니다.

이렇게 하려면 다음 절차를 따르십시오.

**IAM 역할을 통해 PostgreSQL DB 인스턴스에 액세스할 수 있는 권한을 Amazon S3에 부여하려면**

1. IAM 정책을 생성합니다.

   이 정책은 PostgreSQL DB 인스턴스가 Amazon S3에 액세스할 수 있도록 허용하는 권한을 버킷 및 객체에 부여합니다.

   이 정책을 생성하는 과정에서 다음 단계를 수행하십시오.

   1. 다음과 같은 필수 작업을 정책에 포함하여 PostgreSQL DB 인스턴스에서 Amazon S3 버킷으로 파일 전송을 허용합니다.
      + `s3:PutObject`
      + `s3:AbortMultipartUpload`

   1. Amazon S3 버킷과 버킷의 객체를 식별하는 Amazon 리소스 이름(ARN)을 포함합니다. Amazon S3에 액세스하기 위한 ARN 형식은 `arn:aws:s3:::amzn-s3-demo-bucket/*`입니다.

   PostgreSQL용 Amazon RDS에 대한 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 내에 데이터베이스를 설정하는 것이 좋습니다. 자세한 내용은 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 리소스 이름(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**  

   대상 LinuxmacOS, 또는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 역할을 DB 인스턴스에 추가합니다. 이렇게 하려면 다음에 설명한 대로 AWS Management Console 또는 AWS CLI를 사용합니다.

## 콘솔
<a name="collapsible-section-1"></a>

**콘솔을 사용하여 PostgreSQL DB 인스턴스에 대해 IAM 역할을 추가하려면**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 세부 정보를 표시하고자 하는 PostgreSQL DB 인스턴스 이름을 선택합니다.

1. **Connectivity & security(연결성 및 보안)** 탭에 있는 **Manage IAM roles(IAM 역할 관리)** 섹션의 **이 인스턴스에 IAM 역할 추가**에서 추가할 역할을 선택합니다.

1. **기능**에서 **s3Export**를 선택합니다.

1. [**Add role**]을 선택합니다.

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

**CLI를 사용하여 PostgreSQL DB 인스턴스에 대해 IAM 역할을 추가하려면**
+ 다음 명령을 사용해 `my-db-instance`라는 PostgreSQL DB 인스턴스에 역할을 추가합니다. *`your-role-arn`*을 이전 단계에서 기록한 정책 ARN으로 교체합니다. `s3Export` 옵션의 값에 대해 `--feature-name`를 사용합니다.  
**Example**  

  대상 LinuxmacOS, 또는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` 함수를 사용하기 전에 다음 사전 조건을 충족해야 합니다.
+ [Amazon S3으로 데이터 내보내기 개요](postgresql-s3-export.md#postgresql-s3-export-overview)에 설명된 대로 필요한 PostgreSQL 확장을 설치합니다.
+ [내보낼 Amazon S3 파일 경로 지정](postgresql-s3-export.md#postgresql-s3-export-file)에 설명된 대로 데이터를 내보낼 Amazon S3 위치를 결정합니다.
+ [Amazon S3 버킷에 대한 액세스 권한 설정](postgresql-s3-export-access-bucket.md)에 설명된 대로 Amazon S3에 대한 내보내기 액세스 권한이 DB 인스턴스에 있는지 확인합니다.

다음 예제에서는 `sample_table`이라는 데이터베이스 테이블을 사용합니다. 이 예제에서는 *amzn-s3-demo-bucket*이라는 버킷으로 데이터를 내보냅니다. 예제 테이블과 데이터는 psql에서 다음 SQL 문을 사용하여 생성됩니다.

```
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
```

내보내는 데이터가 클 경우 각각 최대 크기가 약 6GB인 여러 파일에 저장됩니다. 추가 파일 이름의 파일 접두사도 동일하지만 `_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 리전 이름 및 연결된 값의 목록은 [리전, 가용 영역 및 로컬 영역](Concepts.RegionsAndAvailabilityZones.md) 섹션을 참조하십시오.

  현재, 이 값은 내보내는 DB 인스턴스의 AWS 리전과 동일해야 합니다. 기본값은 내보내는 DB 인스턴스의 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 text*  
데이터를 내보낼 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 파일 이름이 포함된 필수 텍스트 문자열입니다.

*리전*  
버킷이 있는 AWS 리전을 포함하는 선택적 텍스트 문자열입니다. AWS 리전 이름 및 연결된 값의 목록은 [리전, 가용 영역 및 로컬 영역](Concepts.RegionsAndAvailabilityZones.md) 섹션을 참조하십시오.  
현재, 이 값은 내보내는 DB 인스턴스의 AWS 리전과 동일해야 합니다. 기본값은 내보내는 DB 인스턴스의 AWS 리전입니다.

*options*  
PostgreSQL `COPY` 명령에 대한 인수를 포함하는 선택적 텍스트 문자열입니다. 이러한 인수는 내보낼 때 데이터를 복사하는 방법을 지정합니다. 자세한 내용은 [PostgreSQL COPY 설명서](https://www.postgresql.org/docs/current/sql-copy.html)를 참조하십시오.

*kms\$1key text*  
데이터를 내보낼 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에 업로드된 파일 수입니다. 파일은 약 6GB 크기로 생성됩니다. 생성된 각 추가 파일 이름에 `_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>

Amazon S3 파일 정보를 저장할 `aws_commons._s3_uri_1` 구조를 생성합니다. `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
)
```입력 파라미터

*버킷*  
파일의 Amazon S3 버킷 이름이 포함된 필수 텍스트 문자열입니다.

*file\$1path*  
파일 경로를 포함한 Amazon S3 파일 이름이 포함된 필수 텍스트 문자열입니다.

*리전*  
파일이 위치한 AWS 리전이 포함된 필수 텍스트 문자열입니다. AWS 리전 이름 및 연결된 값의 목록은 [리전, 가용 영역 및 로컬 영역](Concepts.RegionsAndAvailabilityZones.md) 섹션을 참조하십시오.

# Amazon S3 액세스 문제 해결
<a name="postgresql-s3-export-troubleshoot"></a>

데이터를 Amazon S3로 내보내려고 할 때 연결 문제가 발생하면 먼저 DB 인스턴스에 연결된 VPC 보안 그룹의 아웃바운드 액세스 규칙이 네트워크 연결을 허용하는지 확인합니다. 특히 보안 그룹에는 DB 인스턴스가 TCP 트래픽을 포트 443 및 IPv4 주소(0.0.0.0/0)로 보낼 수 있도록 허용하는 규칙이 있어야 합니다. 자세한 내용은 [보안 그룹을 생성하여 VPC 내부의 DB 인스턴스에 대한 액세스를 제공](CHAP_SettingUp.md#CHAP_SettingUp.SecurityGroup)을 참조하세요.

권장 사항은 다음을 참조하세요.
+ [Amazon RDS 자격 증명 및 액세스 문제 해결](security_iam_troubleshoot.md)
+ [Amazon Simple Storage Service 사용 설명서](https://docs.aws.amazon.com/AmazonS3/latest/userguide/troubleshooting.html)의 *Amazon S3 문제 해결*
+ *IAM 사용 설명서*의 [Amazon S3 문제 해결 및 IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_iam-s3.html)

# RDS for PostgreSQL DB 인스턴스에서 AWS Lambda 함수 호출
<a name="PostgreSQL-Lambda"></a>

AWS Lambda는 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 있는 이벤트 기반 컴퓨팅 서비스입니다. RDS for PostgreSQL을 비롯한 많은 AWS 서비스에서 사용할 수 있습니다. 예를 들어 Lambda 함수를 사용하여 데이터베이스의 이벤트 알림을 처리하거나 새 파일이 Amazon S3에 업로드될 때마다 파일에서 데이터를 로드할 수 있습니다. Lambda에 대한 자세한 내용은 AWS Lambda 개발자 안내서에서 [AWS Lambda란 무엇입니까?](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html)를 참조하세요.**

**참고**  
AWS Lambda 함수 호출은 다음 RDS for PostgreSQL 버전에서 지원됩니다.  
모든 PostgreSQL 18 버전
모든 PostgreSQL 17 버전
모든 PostgreSQL 16 버전
모든 PostgreSQL 15 버전
PostgreSQL 14.1 이상의 마이너 버전
PostgreSQL 13.2 이상의 마이너 버전
PostgreSQL 12.6 이상의 마이너 버전

Lambda 함수와 함께 작동하도록 RDS for PostgreSQL을 설정하는 것은 AWS Lambda, IAM, VPC, RDS for PostgreSQL DB 인스턴스를 포괄하는 다단계 프로세스입니다. 다음에서 필요한 단계에 대한 요약을 찾을 수 있습니다.

Lambda 함수에 대한 자세한 내용은 AWS Lambda 개발자 안내서의 [Lambda 시작하기](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html)와 [AWS Lambda 기본](https://docs.aws.amazon.com/lambda/latest/dg/lambda-foundation.html)을 참조하세요.**

**Topics**
+ [1단계: AWS Lambda에 대한 아웃바운드 연결을 위해 RDS for PostgreSQL DB 인스턴스 구성](#PostgreSQL-Lambda-network)
+ [2단계: RDS for PostgreSQL DB 인스턴스 및 AWS Lambda에 대한 IAM 구성](#PostgreSQL-Lambda-access)
+ [3단계: RDS for PostgreSQL DB 인스턴스용 `aws_lambda` 확장 설치](#PostgreSQL-Lambda-install-extension)
+ [4단계: RDS for PostgreSQL DB 인스턴스와 함께 Lambda 도우미 함수 사용(선택 사항)](#PostgreSQL-Lambda-specify-function)
+ [5단계: RDS for PostgreSQL DB 인스턴스에서 Lambda 함수 호출](#PostgreSQL-Lambda-invoke)
+ [6단계: 다른 사용자에게 Lambda 함수를 호출할 수 있는 권한 부여](#PostgreSQL-Lambda-grant-users-permissions)
+ [예제: RDS for PostgreSQL DB 인스턴스에서 Lambda 함수 호출](PostgreSQL-Lambda-examples.md)
+ [Lambda 함수 오류 메시지](PostgreSQL-Lambda-errors.md)
+ [AWS Lambda 함수 및 파라미터 참조](PostgreSQL-Lambda-functions.md)

## 1단계: AWS Lambda에 대한 아웃바운드 연결을 위해 RDS for PostgreSQL DB 인스턴스 구성
<a name="PostgreSQL-Lambda-network"></a>

Lambda 함수는 항상 AWS Lambda 서비스가 소유한 Amazon VPC 내에서 실행됩니다. Lambda는 이 VPC에 네트워크 액세스 및 보안 규칙을 적용하고 VPC를 자동으로 유지 관리 및 모니터링합니다. RDS for PostgreSQL DB 인스턴스는 네트워크 트래픽을 Lambda 서비스의 VPC로 전송합니다. 이를 구성하는 방법은 DB 인스턴스가 퍼블릭인지 프라이빗인지에 따라 다릅니다.
+ **퍼블릭 RDS for PostgreSQL DB 인스턴스** – DB 인스턴스는 VPC의 퍼블릭 서브넷에 있고 인스턴스의 "PubliclyAccessible" 속성이 `true`인 경우 퍼블릭입니다. 이 속성의 값을 찾으려면 [describe-db-instances](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-instances.html) AWS CLI 명령을 사용합니다. 또는 AWS Management Console을 사용하여 **연결 및 보안** 탭을 열고 **퍼블릭 액세스 가능**이 **예**인지 확인할 수 있습니다. 인스턴스가 VPC의 퍼블릭 서브넷에 있는지 확인하려면 AWS Management Console 또는 AWS CLI를 사용할 수 있습니다.

  Lambda에 대한 액세스를 설정하려면 AWS Management Console 또는AWS CLI를 사용하여 VPC의 보안 그룹에 대한 아웃바운드 규칙을 생성합니다. 아웃바운드 규칙은 TCP가 포트 443을 사용하여 IPv4 주소(0.0.0.0/0)로 패킷을 보낼 수 있도록 지정합니다.
+ **프라이빗 RDS for PostgreSQL DB 인스턴스** – 이 경우 인스턴스의 "PubliclyAccessible" 속성은 `false`이거나 프라이빗 서브넷에 있습니다. 인스턴스가 Lambda와 함께 작동하도록 허용하려면 Network Address Translation)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 DB 인스턴스의 Lambda 함수 호출에 대한 응답을 반환합니다. VPC 엔드포인트는 자체 프라이빗 DNS 확인을 사용합니다. RDS for PostgreSQL은 `rds.custom_dns_resolution` 값을 기본값 0(사용 설정되지 않음)에서 1로 변경할 때까지 Lambda VPC 엔드포인트를 사용할 수 없습니다. 그렇게 하려면 다음을 수행하세요.
  + 사용자 지정 DB 파라미터 그룹을 생성합니다.
  + `rds.custom_dns_resolution` 파라미터 값을 기본값인 `0`에서 `1`로 변경합니다.
  + 사용자 정의 DB 파라미터 그룹을 사용하도록 DB 인스턴스를 수정합니다.
  + 수정된 파라미터가 적용되도록 인스턴스를 재부팅합니다.

이제 VPC가 네트워크 수준에서 AWS Lambda VPC와 상호 작용할 수 있습니다. 다음으로 IAM을 사용하여 권한을 구성합니다.

## 2단계: RDS for PostgreSQL DB 인스턴스 및 AWS Lambda에 대한 IAM 구성
<a name="PostgreSQL-Lambda-access"></a>

RDS for PostgreSQL DB 인스턴스에서 Lambda 함수를 호출하려면 특정 권한이 필요합니다. 필요한 권한을 구성하려면 Lambda 함수 호출을 허용하는 IAM 정책을 생성하고 해당 정책을 역할에 할당한 다음 DB 인스턴스에 그 역할을 적용하는 것이 좋습니다. 이 접근 방식은 DB 인스턴스에 사용자를 대신하여 지정된 Lambda 함수를 호출할 수 있는 권한을 부여합니다. 다음 단계에서는 AWS CLI를 사용하여 이를 수행하는 방법을 보여줍니다.

**Lambda와 함께 Amazon RDS 인스턴스를 사용하기 위한 IAM 권한 구성**

1. [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) AWS CLI 명령을 사용하여 RDS for PostgreSQL DB 인스턴스가 지정된 Lambda 함수를 간접적으로 호출하도록 허용하는 IAM 정책을 생성합니다. 문 ID(Sid)는 정책 문에 대한 선택적 설명이며 사용량에 영향을 미치지 않습니다. 이 정책은  DB 인스턴스에 지정된 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 DB 인스턴스에 역할을 적용합니다. 이 마지막 단계를 통해 DB 인스턴스의 데이터베이스 사용자가 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 DB 인스턴스의 기능에 아무 것도 추가하지 않습니다.

## 3단계: RDS for PostgreSQL DB 인스턴스용 `aws_lambda` 확장 설치
<a name="PostgreSQL-Lambda-install-extension"></a>

AWS Lambda을 RDS for PostgreSQL DB 인스턴스와 사용하려면 RDS for PostgreSQL DB 인스턴스에 `aws_lambda` PostgreSQL 확장을 추가합니다. 이 확장은 RDS for PostgreSQL DB 인스턴스에 PostgreSQL에서 Lambda 함수를 호출할 수 있는 기능을 제공합니다.

**RDS for PostgreSQL DB 인스턴스에 `aws_lambda` 확장 설치**

PostgreSQL `psql` 명령줄 또는 pgAdmin 도구를 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

1. `rds_superuser` 권한이 있는 사용자로 RDS for PostgreSQL DB 인스턴스에 연결합니다. 기본 `postgres` 사용자가 예제에 표시됩니다.

   ```
   psql -h instance.444455556666.aws-region.rds.amazonaws.com -U postgres -p 5432
   ```

1. `aws_lambda` 확장을 설치합니다. `aws_commons` 확장도 필요합니다. 이 확장은 `aws_lambda` 및 기타 여러 PostgreSQL용 Aurora 확장에 대한 도우미 함수를 제공합니다. RDS for PostgreSQLDB 인스턴스에 아직 없는 경우 다음과 같이 `aws_lambda`와 함께 설치됩니다.

   ```
   CREATE EXTENSION IF NOT EXISTS aws_lambda CASCADE;
   NOTICE:  installing required extension "aws_commons"
   CREATE EXTENSION
   ```

`aws_lambda` 확장이 DB 인스턴스에 설치됩니다. 이제 Lambda 함수를 호출하기 위한 편의 구조를 생성할 수 있습니다.

## 4단계: RDS for PostgreSQL DB 인스턴스와 함께 Lambda 도우미 함수 사용(선택 사항)
<a name="PostgreSQL-Lambda-specify-function"></a>

`aws_commons` 확장의 도우미 함수를 사용하여 PostgreSQL에서 보다 쉽게 호출할 수 있는 엔터티를 준비할 수 있습니다. 이렇게 하려면 Lambda 함수에 대한 다음 정보가 필요합니다.
+ **함수 이름(Function name)** – Lambda 함수의 이름, Amazon 리소스 이름(ARN), 버전 또는 별칭입니다. [2단계: 인스턴스 및 Lambda에 대한 IAM 구성](#PostgreSQL-Lambda-access)에서 생성한 IAM 정책에는 ARN이 필요하므로 함수의 ARN을 사용하는 것이 좋습니다.
+ **AWS 리전** – (선택 사항) RDS for PostgreSQL DB 인스턴스와 동일한 리전에 있지 않은 경우 Lambda 함수가 있는 AWS 리전입니다.

Lambda 함수 이름 정보를 보관하려면 [aws\$1commons.create\$1lambda\$1function\$1arn](PostgreSQL-Lambda-functions.md#aws_commons.create_lambda_function_arn) 함수를 사용합니다. 이 도우미 함수는 호출 함수에 필요한 세부 정보를 사용하여 `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 DB 인스턴스에서 Lambda 함수 호출](#PostgreSQL-Lambda-invoke) 섹션을 참조하세요.

## 5단계: RDS for PostgreSQL DB 인스턴스에서 Lambda 함수 호출
<a name="PostgreSQL-Lambda-invoke"></a>

`aws_lambda.invoke` 함수는 `invocation_type`에 따라 동기식 또는 비동기식으로 작동합니다. 이 파라미터에 대한 두 가지 대안은 다음과 같이 `RequestResponse`(기본값) 및 `Event`입니다.
+ **`RequestResponse`** - 이 호출 유형은 *동기식*이며, 호출 유형을 지정하지 않고 호출할 때의 기본 동작입니다. 응답 페이로드에는 `aws_lambda.invoke` 함수의 결과가 포함됩니다. 워크플로가 진행하기 전에 Lambda 함수에서 결과를 수신해야 하는 경우 이 호출 유형을 사용합니다.
+ **`Event`** - 이 호출 유형은 *비동기식*이며, 응답에 결과가 포함된 페이로드가 포함되지 않습니다. 워크플로에서 처리를 계속하기 위해 Lambda 함수의 결과가 필요하지 않은 경우 이 호출 유형을 사용합니다.

설정에 대한 간단한 테스트로 `psql`을 사용하여 DB 인스턴스에 연결하고 명령줄에서 예제 함수를 호출할 수 있습니다. 다음 스크린샷에 표시된 간단한 Python 함수와 같이 Lambda 서비스에 기본 함수 중 하나가 설정되어 있다고 가정합니다.

![\[AWS Lambda에 대해 AWS CLI에 표시된 예제 Lambda 함수\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/lambda_simple_function.png)


**예제 함수 호출**

1. `psql` 또는 pgAdmin을 사용하여 DB 인스턴스에 연결합니다.

   ```
   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을 사용하여 DB 인스턴스에 연결합니다.

   ```
   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 DB 인스턴스에서 Lambda 함수 호출
<a name="PostgreSQL-Lambda-examples"></a>

다음에서 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 함수를 호출하는 몇 가지 예를 찾을 수 있습니다. 예제 대부분은 [4단계: RDS for PostgreSQL DB 인스턴스와 함께 Lambda 도우미 함수 사용(선택 사항)](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'` - 이 파라미터는 [4단계: RDS for PostgreSQL DB 인스턴스와 함께 Lambda 도우미 함수 사용(선택 사항)](PostgreSQL-Lambda.md#PostgreSQL-Lambda-specify-function)에서 생성된 복합 구조를 `aws_commons.create_lambda_function_arn` 도우미 함수와 함께 식별합니다. 다음과 같이 `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` 파라미터를 사용하여 함수 응답에 실행 로그의 마지막 4KB를 포함할 수 있습니다. 기본적으로 이 파라미터는 `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');
```

클라이언트 컨텍스트를 포함하려면 [aws\$1lambda.invoke](PostgreSQL-Lambda-functions.md#aws_lambda.invoke) 함수의 `context` 파라미터에 JSON 객체를 사용하세요.

`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 함수 한정자를 제공할 수도 있습니다.

```
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가 Lambda VPC에 연결할 수 있도록 VPC 보안 그룹의 포트 443에서 TCP에 대한 아웃바운드 규칙이 열려 있는지 확인합니다.

  DB 인스턴스가 프라이빗인 경우 VPC에 대한 프라이빗 DNS 설정을 확인합니다. [1단계: AWS Lambda에 대한 아웃바운드 연결을 위해 RDS for PostgreSQL DB 인스턴스 구성](PostgreSQL-Lambda.md#PostgreSQL-Lambda-network)에 설명된 대로 `rds.custom_dns_resolution` 파라미터를 1로 설정하고 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 DB 인스턴스에 대해 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)을 참조하십시오.

*region*  
(선택 사항) 함수의 Lambda 리전입니다. 기본적으로 RDS는 `function_name`의 전체 ARN에서 AWS 리전을 확인하거나 RDS for PostgreSQL DB 인스턴스 리전을 사용합니다. 이 리전 값이 `function_name` ARN에 제공된 값과 충돌하면 오류가 발생합니다.

*invocation\$1type*  
Lambda 함수의 호출 유형입니다. 값은 대소문자를 구분합니다. 가능한 값은 다음을 포함합니다.  
+ `RequestResponse` – 기본값입니다. Lambda 함수에 대한 이러한 유형의 호출은 동시에 발생하며 결과에 응답 페이로드를 돌려보냅니다. 워크플로가 Lambda 함수 결과 수신에 즉시 의존하는 경우 `RequestResponse` 호출 유형을 사용합니다.
+ `Event` – Lambda 함수에 대한 이러한 유형의 호출은 비동기식이며 반환된 페이로드없이 즉시 반환됩니다. 워크플로를 이동하기 전에 Lambda 함수 결과가 필요하지 않은 경우 `Event` 호출 유형을 사용합니다.
+ `DryRun` – 이 유형의 호출은 Lambda 함수를 실행하지 않고 액세스를 테스트합니다.

*log\$1type*  
`log_result` 출력 파라미터에 반환할 Lambda 로그의 유형입니다. 값은 대소문자를 구분합니다. 가능한 값은 다음을 포함합니다.  
+ – 추적 반환된 `log_result` 출력 파라미터에는 실행 로그의 마지막 4KB가 포함됩니다.
+ – 없음 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*  
Lambda 함수가 호출 될 때 `log_type` 값이 `Tail` 인 경우 반환된 실행 로그 정보입니다. 결과에는 Base64로 인코딩된 실행 로그의 마지막 4KB가 포함됩니다.

## aws\$1commons.create\$1lambda\$1function\$1arn
<a name="aws_commons.create_lambda_function_arn"></a>

Lambda 파일 정보를 저장할 `aws_commons._lambda_function_arn_1` 구조를 생성합니다. 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일 수 있습니다.

*region*  
Lambda 함수가 있는 AWS 리전을 포함하는 선택적 텍스트 문자열입니다. 리전 이름 및 연결된 값의 목록은 섹션을 참조하십시오[리전, 가용 영역 및 로컬 영역](Concepts.RegionsAndAvailabilityZones.md)

## aws\$1lambda 파라미터
<a name="aws_lambda.parameters"></a>

이 표에서는 `aws_lambda` 함수와 관련된 파라미터를 찾아볼 수 있습니다.


| 파라미터 | 설명 | 
| --- | --- | 
| `aws_lambda.connect_timeout_ms` | 이는 동적 파라미터이며 AWS Lambda에 연결하는 동안 최대 대기 시간을 설정합니다. 기본값은 `1000`입니다. 이 파라미터에 허용되는 값은 1\$1900,000입니다. | 
| `aws_lambda.request_timeout_ms` | 이는 동적 파라미터이며 AWS Lambda의 응답을 기다리는 동안 최대 대기 시간을 설정합니다. 기본값은 `3000`입니다. 이 파라미터에 허용되는 값은 1\$1900,000입니다. | 
| `aws_lambda.endpoint_override` | AWS Lambda에 연결하는 데 사용할 수 있는 엔드포인트를 지정합니다. 빈 문자열은 해당 리전의 기본 AWS Lambda 엔드포인트를 선택합니다. 이 정적 파라미터 변경을 적용하려면 데이터베이스를 다시 시작해야 합니다. | 

# Amazon RDS for PostgreSQL의 일반적인 DBA 태스크
<a name="Appendix.PostgreSQL.CommonDBATasks"></a>

데이터베이스 관리자(DBA)는 Amazon RDS for PostgreSQL DB 인스턴스를 관리할 때 다양한 작업을 수행합니다. PostgreSQL을 이미 익숙하게 사용하는 DBA라면 하드웨어에서 PostgreSQL을 실행하는 것과 RDS for PostgreSQL을 실행하는 것 사이의 중요한 차이점을 알고 있어야 합니다. 예를 들어 이는 관리형 서비스이므로, Amazon RDS에서 DB 인스턴스에 대한 shell 액세스를 허용하지 않습니다. 즉, `pg_hba.conf` 및 다른 구성 파일에 직접 액세스할 수 없습니다. RDS for PostgreSQL의 경우 일반적으로 온프레미스 인스턴스의 PostgreSQL 구성 파일을 변경하면 RDS for PostgreSQL DB 인스턴스와 연결된 사용자 지정 DB 파라미터 그룹도 변경됩니다. 자세한 내용은 [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의 일반적인 DBA 태스크 일부입니다.

**Topics**
+ [RDS for PostgreSQL에서 지원되는 데이터 정렬입니다.](PostgreSQL-Collations.md)
+ [PostgreSQL 역할 및 권한 이해](Appendix.PostgreSQL.CommonDBATasks.Roles.md)
+ [PostgreSQL에서 연결 중단 처리](Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.md)
+ [Amazon RDS for PostgreSQL에서 PostgreSQL 자동 정리 사용](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 DB 인스턴스에 파라미터로 작업](Appendix.PostgreSQL.CommonDBATasks.Parameters.md)

# RDS for PostgreSQL에서 지원되는 데이터 정렬입니다.
<a name="PostgreSQL-Collations"></a>

데이터 정렬은 데이터베이스에 저장된 문자열을 정렬하고 비교하는 방법을 결정하는 일련의 규칙입니다. 데이터 정렬은 컴퓨터 시스템에서 기본적인 역할을 하며 운영 체제의 일부로 포함됩니다. 새 문자가 언어에 추가되거나 순서 지정 규칙이 변경되면 시간이 지남에 따라 데이터 정렬이 변경됩니다.

데이터 정렬 라이브러리는 데이터 정렬에 대한 특정 규칙 및 알고리즘을 정의합니다. PostgreSQL에서 가장 많이 사용되는 데이터 정렬 라이브러리는 GNU C(glibc) 및 유니코드용 국제화 구성 요소(ICU)입니다. 기본적으로 RDS for PostgreSQL은 멀티바이트 문자 시퀀스에 대한 유니코드 문자 정렬 순서를 포함하는 glibc 데이터 정렬을 사용합니다.

새로운 RDS for PostgreSQL의 DB 인스턴스를 만들면 운영 체제에서 사용 가능한 데이터 정렬을 확인합니다. `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 Management Console을 사용하여 RDS for PostgreSQL DB 인스턴스를 만들면 관리자 계정이 동시에 생성됩니다. 기본적으로 해당 이름은 다음 스크린샷에 나와 있는 것처럼 `postgres`입니다.

![\[데이터베이스 생성(Create database) 페이지의 보안 인증에 대한 기본 로그인 ID는 postgres입니다.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/default-login-identity-apg-rpg.png)


기본값(`postgres`)을 그대로 사용하지 않고 다른 이름을 선택할 수 있습니다. 이 경우 선택한 이름은 문자로 시작해야 하며 영숫자 1\$116자 사이어야 합니다. 단순하게 하기 위해 이 안내서 전체에서 기본 사용자 계정을 기본값(`postgres`)으로 참조합니다.

AWS Management Console 대신 `create-db-instance` AWS CLI를 사용하는 경우 명령에서 `master-username` 파라미터로 이름을 전달하여 이름을 생성합니다. 자세한 내용은 [Amazon RDS DB 인스턴스 생성](USER_CreateDBInstance.md) 단원을 참조하세요. 

AWS Management Console, 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 for PostgreSQL 암호 암호화 사용](PostgreSQL_Password_Encryption_configuration.md)

# rds\$1superuser 역할 이해
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser"></a>

PostgreSQL에서는 *역할*로 데이터베이스의 다양한 객체에 대해 그룹 또는 사용자에게 부여된 사용자, 그룹 또는 특정 권한 집합을 정의할 수 있습니다. `CREATE USER` 및 `CREATE GROUP`에 대한 PostgreSQL 명령은 데이터베이스 사용자를 구분하기 위한 특정 속성을 가진 보다 일반적인 `CREATE ROLE`로 대체되었습니다. 데이터베이스 사용자는 LOGIN 권한을 가진 역할로 간주할 수 있습니다.

**참고**  
`CREATE USER` 및 `CREATE GROUP` 명령을 계속 사용할 수 있습니다. 자세한 내용은 PostgreSQL 설명서에서 [데이터베이스 역할](https://www.postgresql.org/docs/current/user-manag.html)을 참조하세요.

`postgres` 사용자는 RDS for PostgreSQL DB 인스턴스에서 가장 높은 권한을 지닌 데이터베이스 사용자입니다. 이는 다음 `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은 관리형 서비스이므로 호스트 OS에 액세스할 수 없으며, PostgreSQL `superuser` 계정을 사용하여 연결할 수 없습니다. 독립 실행형 PostgreSQL에 대한 `superuser` 액세스 권한이 필요한 대부분의 태스크는 Amazon RDS에서 자동으로 관리됩니다.

권한 부여에 대한 자세한 내용은 PostgreSQL 설명서에서 [GRANT](http://www.postgresql.org/docs/current/sql-grant.html)를 참조하세요.

`rds_superuser` 역할은 에서 *미리 정의된* 여러 역할 중 하나입니다. RDS for PostgreSQL DB 인스턴스 

**참고**  
PostgreSQL 13 및 이전 릴리스에서는 *미리 정의된* 역할을 *기본* 역할이라고 합니다.

다음 목록에서 새로운 에 대해 자동으로 생성되는 미리 정의된 다른 역할 중 일부를 확인할 수 있습니다. RDS for PostgreSQL DB 인스턴스 미리 정의된 역할 및 권한은 변경할 수 없습니다. 미리 정의된 역할에 대한 권한은 삭제하거나 이름을 바꾸거나 수정할 수 없습니다. 이를 시도할 시에는 오류가 발생합니다.
+ **rds\$1password** - 데이터베이스 사용자를 대상으로 암호를 변경하고 암호 제약 조건을 설정할 수 있는 역할입니다. `rds_superuser` 역할에는 기본적으로 이 역할이 부여되며, 이 역할을 통해 데이터베이스 사용자에게 역할을 부여할 수 있습니다. 자세한 내용은 [PostgreSQL 데이터베이스에 대한 사용자 액세스 제어PostgreSQL에 대한 사용자 액세스 제어](Appendix.PostgreSQL.CommonDBATasks.Access.md) 섹션을 참조하세요.
  + 14 이전의 RDS for PostgreSQL 버전에서 `rds_password` 역할은 암호를 변경하고 데이터베이스 사용자와 `rds_superuser` 역할이 있는 사용자에 대해 암호 제한을 설정할 수 있습니다. 14 이후의 RDS for PostgreSQL 버전에서 `rds_password` 역할은 데이터베이스 사용자에 대해서만 암호를 변경하고 암호 제약 조건을 설정할 수 있습니다. `rds_superuser` 역할이 있는 사용자만 `rds_superuser` 역할을 가진 다른 사용자에게 이러한 작업을 수행할 수 있습니다.
+ **rdsadmin** - `superuser` 권한이 있는 관리자가 독립 실행형 PostgreSQL 데이터베이스에서 수행할 수 있는 많은 관리 태스크를 처리하기 위해 생성된 역할입니다. 이 역할은 RDS for PostgreSQL에서 다양한 관리 태스크에 내부적으로 사용됩니다.
+ **rdstopmgr** - 다중 AZ 배포를 지원하기 위해 Amazon RDS에서 내부적으로 사용하는 역할입니다.
+ **rds\$1reserved** – Amazon RDS에서 데이터베이스 연결을 예약하는 데 내부적으로 사용하는 역할입니다.

# 역할 및 해당 권한 보기
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles.View"></a>

PostgreSQL 버전에 따라 서로 다른 명령을 사용하여 RDS for PostgreSQL DB 인스턴스에서 사전 정의된 역할과 해당 권한을 볼 수 있습니다. 사전 정의된 모든 역할을 보려면 RDS for PostgreSQL DB 인스턴스에 연결하고 `psql`을 사용하여 다음 명령을 실행할 수 있습니다.

**`psql` 15 이하 버전의 경우**

RDS for PostgreSQL DB 인스턴스에 연결하고 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 DB 인스턴스 에 생성한 데이터베이스 인스턴스에 액세스할 수 있는 사용자 권한을 보다 효과적으로 제어하려면 이러한 기본 `public` 권한을 회수하는 것이 좋습니다. 이렇게 하고 나서 다음 절차에 표시된 것처럼 데이터베이스 사용자에게 보다 세분화된 구체적인 권한을 부여하면 됩니다.

**새 데이터베이스 인스턴스에 대한 역할 및 권한을 설정하는 방법**

새로 생성한 RDS for PostgreSQL DB 인스턴스에 데이터베이스를 설정하여 여러 연구자가 사용할 수 있도록 하고, 이들 모두 데이터베이스에 대한 읽기-쓰기 액세스 권한이 필요하다고 가정합니다.

1. 다음과 같이 `psql` 또는 pgAdmin을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

   ```
   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 DB 인스턴스가 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 DB 인스턴스를 재부팅해야 설정이 적용됩니다.

이 기능을 활성화하면 다음 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_superuser` 권한이 없는 데이터베이스 사용자에게 `rds_password` 권한을 부여할 경우 `CREATEROLE` 속성도 부여해야 합니다.

만료 및 클라이언트 측에 필요한 복잡성 등의 암호 요구 사항을 확인해야 합니다. 암호 관련 변경 사항에 대해 자체 클라이언트 측 유틸리티를 사용하는 경우 유틸리티가 `rds_password`의 멤버여야 하며 `CREATE ROLE` 권한을 가져야 합니다.

# SCRAM for PostgreSQL 암호 암호화 사용
<a name="PostgreSQL_Password_Encryption_configuration"></a>

*Salted Challenge Response Authentication Mechanism(SCRAM)*은 암호를 암호화하는 데 사용하는 PostgreSQL의 기본 메시지 다이제스트(MD5) 알고리즘을 대체합니다. SCRAM 인증 메커니즘은 MD5보다 더 안전한 것으로 간주됩니다. 이러한 2가지 암호 보호 방법에 대한 자세한 내용은 PostgreSQL 설명서의 [암호 인증](https://www.postgresql.org/docs/14/auth-password.html)을 참조하세요.

MD5가 아닌 SCRAM을 의 암호 암호화 체계로 사용하는 것이 좋습니다. RDS for PostgreSQL DB 인스턴스  이는 암호 인증 및 암호화에 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을 지원합니다. 또한 다음 절차에 설명된 대로 이러한 버전을 사용하여 DB 인스턴스를 SCRAM이 필요하도록 구성할 수 있습니다.

## SCRAM이 필요하도록 RDS for PostgreSQL DB 인스턴스 설정
<a name="PostgreSQL_Password_Encryption_configuration.preliminary"></a>

 RDS for PostgreSQL DB 인스턴스가 scram-sha-256 알고리즘을 사용하는 암호만 수락하도록 요구할 수 있습니다.

**중요**  
PostgreSQL 데이터베이스를 사용하는 기존 RDS 프록시의 경우, `SCRAM`만 사용하도록 데이터베이스 인증을 수정하면 최대 60초 동안 프록시를 사용할 수 없게 됩니다. 문제를 방지하려면 다음 중 하나를 수행합니다.  
데이터베이스에서 `SCRAM` 및 `MD5` 인증이 모두 허용되는지 확인합니다.
`SCRAM` 인증만 사용하려면 새 프록시를 생성하고, 애플리케이션 트래픽을 새 프록시로 마이그레이션한 다음 이전에 데이터베이스와 연결된 프록시를 삭제합니다.

시스템을 변경하기 전에 다음과 같이 전체 프로세스를 이해해야 합니다.
+ 모든 데이터베이스 사용자에 대한 전체 역할 및 암호 암호화에 대한 정보를 가져옵니다.
+ 암호 암호화를 제어하는 파라미터에 대해 RDS for PostgreSQL DB 인스턴스의 파라미터 설정을 다시 확인합니다.
+  RDS for PostgreSQL DB 인스턴스에서 기본 파라미터 그룹을 사용한다면 필요한 경우 파라미터를 수정할 수 있도록 사용자 지정 DB 파라미터 그룹을 생성하고, 이를 RDS for PostgreSQL DB 인스턴스에 적용해야 합니다. RDS for PostgreSQL DB 인스턴스에서 사용자 지정 파라미터 그룹을 사용하는 경우 필요에 따라 과정 후반부에서 필요한 파라미터를 수정할 수 있습니다.
+ `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 DB 인스턴스에서 SCRAM을 사용하도록 준비
<a name="PostgreSQL_Password_Encryption_configuration.getting-ready"></a>

 RDS for PostgreSQL DB 인스턴스를 변경하기에 모든 기존 데이터베이스 사용자 계정을 확인해야 합니다. 또한 암호에 사용되는 암호화 유형도 확인하세요. `rds_tools` 확장을 사용하여 이러한 작업을 수행할 수 있습니다. `rds_tools`를 지원하는 PostgreSQL 버전을 확인하려면 [Amazon RDS for PostgreSQL의 확장 버전](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)을 참조하세요.

**데이터베이스 사용자(역할) 및 암호 암호화 방법 목록을 가져오려면**

1. 다음과 같이 `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

   ```
   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)
   ```

### 사용자 지정 DB 파라미터 그룹 생성
<a name="PostgreSQL_Password_Encryption_configuration.custom-parameter-group"></a>

**참고**  
 RDS for PostgreSQL DB 인스턴스에서 이미 사용자 지정 파라미터 그룹을 사용하는 경우 새로 만들 필요가 없습니다.

Amazon RDS 파라미터 그룹에 대한 개요는 [RDS for PostgreSQL DB 인스턴스에 파라미터로 작업](Appendix.PostgreSQL.CommonDBATasks.Parameters.md) 섹션을 참조하세요.

암호에 사용되는 암호 암호화 유형은 하나의 파라미터 `password_encryption`으로 설정됩니다. RDS for PostgreSQL DB 인스턴스에서 허용하는 암호화는 다른 파라미터인 `rds.accepted_password_auth_method`로 설정됩니다. 이러한 값 중 하나를 기본값에서 변경하려면 사용자 지정 DB 파라미터 그룹을 생성하여 인스턴스에 적용해야 합니다.

AWS Management Console 또는 RDS API를 사용하여 사용자 지정 DB 파라미터 그룹을 생성할 수도 있습니다. 자세한 내용은 단원을 참조하세요.

DB 파라미터 그룹을 DB 인스턴스에 연결합니다.

**사용자 지정 DB 파라미터 그룹을 생성하려면**

1. `[create-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-parameter-group.html) ` CLI 명령을 사용하여 사용자 지정 DB 파라미터 그룹을 생성합니다. 이 예에서는 `postgres13`을 사용자 지정 파라미터 그룹의 소스로 사용합니다.

   대상 LinuxmacOS, 또는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. `[modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html)` CLI 명령을 사용하여 다음과 같이 사용자 지정 파라미터 그룹을 RDS for PostgreSQL DB 클러스터에 적용합니다.

   대상 LinuxmacOS, 또는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
   ```

   사용자 지정 DB 파라미터 그룹이 포함된 RDS for PostgreSQL DB 인스턴스를 다시 동기화하려면 클러스터의 프라이머리 및 기타 모든 인스턴스를 재부팅합니다. 사용자에게 미치는 영향을 최소화하기 위해 정기 유지 관리 기간 동안 진행되도록 예약합니다.

### SCRAM을 사용하도록 암호 암호화 구성
<a name="PostgreSQL_Password_Encryption_configuration.configure-password-encryption"></a>

 RDS for PostgreSQL DB 인스턴스에서 사용하는 암호 암호화 메커니즘은 DB 파라미터 그룹에 `password_encryption` 파라미터로 설정되어 있습니다. 허용되는 값은 설정하지 않거나 `md5` 또는 `scram-sha-256`입니다. 기본값은 다음과 같이 RDS for PostgreSQL 버전에 따라 달라집니다.
+ RDS for PostgreSQL 14 이상 – 기본값은 `scram-sha-256`입니다.
+ RDS for PostgreSQL 13 – 기본값은 `md5`입니다.

사용자 지정 DB 파라미터 그룹이 RDS for PostgreSQL DB 인스턴스에 연결되어 있으면 암호 암호화 파라미터 값을 변경할 수 있습니다.

![\[RDS 콘솔에 RDS for PostgreSQL의 password_encryption 파라미터에 대한 기본값이 표시됩니다.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/rpg-pwd-encryption-md5-scram-1.png)


**암호의 암호화 설정을 scram-sha-256으로 변경하려면**
+ 다음과 같이 암호 암호화 값을 scram-sha-256으로 변경합니다. 파라미터가 동적이기 때문에 변경 사항을 즉시 적용할 수 있으므로 변경 사항을 적용하려고 재시작하지 않아도 됩니다.

  대상 LinuxmacOS, 또는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 DB 인스턴스의 `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 DB 인스턴스  

### SCRAM이 필요하도록 파라미터 변경
<a name="PostgreSQL_Password_Encryption_configuration.require-scram"></a>

과정의 마지막 단계입니다. 다음 절차에서 변경한 후에도 암호에 `md5` 암호화를 계속 사용하는 모든 사용자 계정(역할)은 에 로그인할 수 없습니다. RDS for PostgreSQL DB 인스턴스  

`rds.accepted_password_auth_method`는 로그인하는 동안 RDS for PostgreSQL DB 인스턴스가 사용자 암호에 대해 허용하는 암호화 방법을 지정합니다. 기본값은 `md5+scram`이므로, 두 방법 중 하나를 사용할 수 있습니다. 다음 이미지에서는 이 파라미터에 대한 기본 설정을 찾을 수 있습니다.

![\[RDS 콘솔에서 rds.accepted_password_auth_method 파라미터에 대한 기본 값과 허용된 값을 표시합니다.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/pwd-encryption-md5-scram-2.png)


이 파라미터에 허용되는 값은 `md5+scram` 또는 `scram`입니다. 이 파라미터 값을 `scram`으로 변경하여 필수로 설정합니다.

**암호에 SCRAM 인증을 요구하도록 파라미터 값을 변경하려면**

1.  RDS for PostgreSQL DB 인스턴스의 모든 데이터베이스에 대한 전체 데이터베이스 사용자 암호가 암호 암호화에 `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. 의 모든 DB 인스턴스에서 쿼리를 반복합니다. RDS for PostgreSQL DB 인스턴스  

   모든 암호가 scram-sha-256을 사용하는 경우 그대로 진행하면 됩니다.

1. 다음과 같이 허용된 암호 인증의 값을 scram-sha-256으로 변경합니다.

   대상 LinuxmacOS, 또는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 킵얼라이브 이해](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Understanding)
+ [RDS for PostgreSQL의 주요 TCP 킵얼라이브 파라미터](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Parameters)
+ [TCP 킵얼라이브 설정 사용 사례](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases)
+ [모범 사례](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.BestPractices)

## TCP 킵얼라이브 이해
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Understanding"></a>

TCP 킵얼라이브는 연결 무결성을 유지하고 확인하는 데 도움이 되는 프로토콜 수준 메커니즘입니다. 각 TCP 연결은 킵얼라이브 동작을 제어하는 커널 수준 설정을 유지 관리합니다. 킵얼라이브 타이머가 만료되면 시스템은 다음을 수행합니다.
+ 데이터 및 ACK 플래그 세트가 없는 프로브 패킷을 전송합니다.
+ TCP/IP 사양에 따라 원격 엔드포인트에서 응답을 예상합니다.
+ 응답 또는 응답 없음을 기반으로 연결 상태를 관리합니다.

## RDS for PostgreSQL의 주요 TCP 킵얼라이브 파라미터
<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 킵얼라이브 설정 사용 사례
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases"></a>

### 유휴 세션 연결 유지
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases.KeepingAlive"></a>

활동이 없어 방화벽 또는 라우터에 의해 유휴 연결이 종료되지 않도록 하는 방법:
+ 정기적으로 킵얼라이브 패킷을 전송하도록 `tcp_keepalives_idle`을 구성합니다.

### 연결 중단 감지
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases.DetectingDead"></a>

연결 중단을 즉시 감지하는 방법:
+ `tcp_keepalives_idle`, `tcp_keepalives_interval` 및 `tcp_keepalives_count`를 조정합니다. 예를 들어 Aurora PostgreSQL 기본값을 사용하면 연결 중단을 감지하는 데 약 1분(프로브 2개 × 30초)이 걸립니다. 이러한 값을 낮추면 감지 속도가 빨라질 수 있습니다.
+ `tcp_user_timeout`을 사용하여 확인의 최대 대기 시간을 지정합니다.

TCP 킵얼라이브 설정은 커널이 연결 중단을 감지하는 데 도움이 되지만 소켓을 사용할 때까지 PostgreSQL이 작동하지 않을 수 있습니다. 세션이 긴 쿼리를 실행하는 경우 쿼리가 완료된 후에야 연결 중단이 감지될 수 있습니다. PostgreSQL 14 이상 버전에서는 `client_connection_check_interval`이 쿼리 실행 중에 소켓을 주기적으로 폴링하여 연결 중단 감지를 가속화할 수 있습니다.

## 모범 사례
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.BestPractices"></a>
+ **적절한 킵얼라이브 간격 설정:** `tcp_user_timeout`, `tcp_keepalives_idle`, `tcp_keepalives_count` 및 `tcp_keepalives_interval`을 조정하여 감지 속도와 리소스 사용의 균형을 맞춥니다.
+ **환경에 최적화:** 네트워크 동작, 방화벽 정책 및 세션 요구 사항에 맞게 설정을 조정합니다.
+ **PostgreSQL 기능 활용:** 효율적인 연결 확인을 위해 PostgreSQL 14 이상 버전에서 `client_connection_check_interval`을 사용합니다.

# Amazon RDS for PostgreSQL에서 PostgreSQL 자동 정리 사용
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum"></a>

자동 정리 기능을 사용하여 PostgreSQL DB 인스턴스의 상태를 유지 관리하는 것이 좋습니다. Autovacuum은 VACUUM 및 ANALYZE 명령의 시작을 자동화합니다. Autovacuum은 삽입되고 업데이트되거나 삭제된 튜플 수가 많은 테이블이 있는지 확인합니다. 확인이 끝나면 Autovacuum은 PostgreSQL 데이터베이스에서 폐기된 데이터 또는 튜플을 제거하여 스토리지를 회수합니다.

기본적으로 자동 정리는 기본 PostgreSQL DB 파라미터 그룹을 사용하여 만든 RDS for PostgreSQL DB 인스턴스에서 켜져 있습니다. 자동 정리 기능과 관련된 다른 구성 파라미터도 기본적으로 설정됩니다. 이러한 기본값은 다소 일반적이기 때문에 특정 워크로드에 대해 자동 정리 기능과 관련된 일부 파라미터를 조정하면 도움이 될 수 있습니다.

다음에서 자동 정리에 대한 자세한 정보와 RDS for PostgreSQL DB 인스턴스에 대한 파라미터를 조정하는 방법을 확인할 수 있습니다. 더욱 개괄적인 수준의 정보는 [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 freeze 수행](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에서 공격적인 vacuum 블로커 식별 및 해결](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)을 사용하며, 보다 대상화된 수동 `VACUUM` 작업을 위해 `SET` 명령을 사용하여 세션 수준에서 조정할 수도 있습니다.

`autovacuum_work_mem`는 인덱스 vacuum용 데드 튜플(`pg_stat_all_tables.n_dead_tup`)의 ID를 저장하기 위한 autovacuum 메모리를 결정합니다.

`autovacuum_work_mem` 파라미터 값을 결정하기 위해 계산할 때는 다음 사항에 유의하세요.
+ 파라미터를 너무 낮게 설정하면 vacuum 프로세스가 테이블을 여러 번 스캔해야 작업이 완료될 수 있습니다. 이러한 다중 스캔은 성능에 부정적인 영향을 줄 수 있습니다. 더 큰 인스턴스의 경우 `maintenance_work_mem` 또는 `autovacuum_work_mem`을 최소 1GB로 설정하면 데드 튜플 수가 많은 테이블을 vacuum하는 성능이 향상될 수 있습니다. 그러나 PostgreSQL 버전 16 이하에서는 vacuum 메모리 사용량이 1GB로 제한되므로 한 번의 전달로 약 1억 7,900만 개의 데드 튜플을 처리하기에 충분합니다. 테이블에 이보다 더 많은 데드 튜플이 있는 경우 vacuum은 테이블의 인덱스를 여러 번 전달해야 하므로 필요한 시간이 크게 늘어납니다. PostgreSQL 버전 17부터는 1GB의 제한이 없으며, autovacuum은 radix 트리를 사용하여 1억 7,900만 개 이상의 튜플을 처리할 수 있습니다.

  튜플 식별자의 크기는 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`을 더 적게 할당합니다. 큰 테이블이 많이 있는 경우(100GB 이상)에는 메모리를 더 많이 할당하고 작업자 프로세스를 더 적게 할당합니다. 가장 큰 테이블에서 성공적으로 작업을 수행하려면 충분한 메모리를 할당해 두어야 합니다. 따라서 작업자 프로세스와 메모리를 합한 양이 할당하려는 전체 메모리 양과 같아야 합니다.

## 트랜잭션 ID 랩어라운드의 가능성 감소
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming"></a>

경우에 따라 Autovacuum과 관련된 파라미터 그룹 설정이 트랜잭션 ID 랩어라운드를 방지하기에 충분히 공격적이지 않을 수 있습니다. 이를 해결하기 위해 RDS for PostgreSQL은 자동 정리 파라미터 값을 자동으로 조정하는 메커니즘을 제공합니다. *적응형 자동 정리*는 RDS for PostgreSQL의 기능입니다. [TransactionID wraparound](https://www.postgresql.org/docs/current/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)에 대한 자세한 설명은 PostgreSQL 설명서에 나와 있습니다.

동적 파라미터 `rds.adaptive_autovacuum`이 켜짐으로 설정된 RDS for PostgreSQL 인스턴스의 경우 적응형 자동 정리가 기본적으로 켜져 있습니다. 이 설정을 항상 활성화해 놓는 것이 좋습니다. 그러나 적응형 Autovacuum 파라미터 튜닝을 끄려면 `rds.adaptive_autovacuum` 파라미터를 0 또는 OFF로 설정합니다.

Amazon RDS Amazon RDS가 자동 정리 파라미터를 조정하더라도 트랜잭션 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/) 게시물을 참조하세요.

적응형 자동 정리 파라미터 튜닝을 사용 설정한 경우 Amazon RDS는 CloudWatch 지표 `MaximumUsedTransactionIDs`가 `autovacuum_freeze_max_age` 파라미터 값 또는 500,000,000 중 큰 값에 도달하면 자동 정리 파라미터를 조정하기 시작합니다.

테이블이 계속 트랜잭션 ID 랩어라운드 방향으로 향하면 Amazon RDS는 Autovacuum의 파라미터를 계속 조정합니다. 이러한 각각의 조정은 랩어라운드를 피하기 위해 Autovacuum에 더 많은 리소스를 할애합니다. Amazon RDS는 다음 자동 정리 관련 파라미터를 업데이트합니다.
+ [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) 

RDS는 새 값이 Autovacuum을 보다 공격적으로 만드는 경우에만 이러한 파라미터를 수정합니다. 파라미터는 DB 인스턴스의 메모리에서 수정됩니다. 파라미터 그룹의 값은 변경되지 않습니다. 현재 인 메모리 설정을 보려면 PostgreSQL [SHOW](https://www.postgresql.org/docs/current/sql-show.html) SQL 명령을 사용하십시오.

Amazon RDS가 이러한 Autovacuum 파라미터를 수정하면 영향받은 DB 인스턴스에 대한 이벤트를 생성합니다. 이 이벤트는 AWS Management Console 및 Amazon RDS API에서 볼 수 있습니다. `MaximumUsedTransactionIDs` CloudWatch 지표가 임계값 미만의 값을 반환하면 Amazon RDS는 메모리의 자동 정리 관련 파라미터를 파라미터 그룹에 지정된 값으로 다시 설정합니다. 그런 다음 이 변경에 해당하는 다른 이벤트를 생성합니다.

# 데이터베이스의 테이블을 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은 트랜잭션 수명을 200,000,000([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 데이터베이스 블로그 게시물 [Amazon 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을 사용하는 것 이외에 유지 관리 기간 동안 수동 vacuum freeze를 정기적으로 수행합니다. 수동 vacuum freeze 수행에 대한 자세한 내용은 [수동 vacuum freeze 수행](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이 현재 실행 중인지 확인합니다. 실행 중이면 더 효율적으로 실행되도록 파라미터를 수정하거나 VACUUM을 수동으로 실행할 수 있도록 일시적으로 autovacuum을 종료해야 합니다.

다음 쿼리를 사용하여 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 freeze 수행
<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 freeze를 수동으로 수행하려면**

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. 세션 2에서 이 작업에 필요한 메모리 양을 계산합니다. 이 예제에서는 이 작업에 메모리를 최대 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)을 2GB로 설정합니다.

   ```
   SET maintenance_work_mem='2 GB';
   SET
   ```

1. 세션 2에서 테이블에 대한 `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. 세션 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. 세션 2에서 `vacuum freeze verbose` 명령을 시작한 다음 세션 1에서 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. 세션 2에서 reindex 명령을 실행합니다.

   ```
   \timing on
   Timing is on.
   reindex index pgbench_branches_test_index;
   REINDEX
     Time: 9.966 ms
   ```

1. 세션 1에서 autovacuum이 프로세스를 차단한 경우 `pg_stat_activity`에서 vacuum 세션에 대한 대기를 나타내는 "T"를 확인할 수 있습니다. 이 경우에는 autovacuum 프로세스를 종료합니다.

   ```
   SELECT pg_terminate_backend('the_pid');
   ```

   이때 세션이 시작됩니다. 이 테이블이 작업 목록에서 가장 상위에 있을 것이므로 autovacuum이 즉시 다시 시작된다는 점을 알아 두어야 합니다.

1. 세션 2에서 명령을 시작한 다음 세션 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)
```

**참고**  
이러한 통계는 통계가 재설정된 시점부터 증분됩니다. 사업 분기 말에만 사용되거나 특정 보고서에만 사용되는 인덱스가 있는 경우를 가정해 보겠습니다. 통계가 재설정된 이후로 이 인덱스가 사용되지 않았을 수 있습니다. 자세한 내용은 [Statistics Functions](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 이상**

대형 테이블에 인덱스가 너무 많으면 DB 인스턴스가 트랜잭션 ID 랩어라운드(XID)에 가까워질 수 있는데, 이때 XID 카운터가 0으로 래핑됩니다. 이 옵션을 선택하지 않으면 데이터가 손실될 수 있습니다. 그러나 인덱스를 정리하지 않고도 테이블에 신속하게 vacuum을 실행할 수 있습니다. RDS for PostgreSQL 12에서는 [https://www.postgresql.org/docs/current/sql-vacuum.html](https://www.postgresql.org/docs/current/sql-vacuum.html) 절과 함께 VACUUM을 사용할 수 있습니다.

```
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 freeze 수행에 대한 자세한 내용은 [수동 vacuum freeze 수행](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md) 섹션을 참조하세요.

**참고**  
주기적인 인덱스 정리를 건너뛰면 인덱스 팽창이 발생하여 스캔 성능이 다운그레이드될 수 있습니다. 인덱스는 데드 행을 유지하고 테이블은 데드 라인 포인터를 유지합니다. 따라서 `pg_stat_all_tables.n_dead_tup`는 인덱스 정리가 포함된 수동 VACUUM 또는 autovacuum이 실행될 때까지 증가합니다. 가장 좋은 방법은 이 프로시저만 사용하여 트랜잭션 ID 랩어라운드를 방지하는 것입니다.

**RDS for PostgreSQL 11 이상**

그러나 RDS for PostgreSQL 11 이하 버전에서 vacuum을 더 신속하게 완료할 수 있는 유일한 방법은 테이블의 인덱스 수를 줄이는 것입니다. 인덱스를 삭제하면 쿼리 계획에 영향을 미칠 수 있습니다. 사용하지 않는 인덱스를 먼저 삭제한 다음, XID 랩어라운드가 매우 가까워졌을 때 인덱스를 삭제하는 것이 좋습니다. vacuum 프로세스가 완료되면 이러한 인덱스를 다시 생성할 수 있습니다.

# Autovacuum에 영향을 주는 기타 파라미터
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.OtherParms"></a>

이 쿼리를 사용하면 autovacuum 및 해당 동작에 직접 영향을 주는 일부 파라미터 값이 표시됩니다. [autovacuum 파라미터](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html)는 PostgreSQL 설명서에 자세히 설명되어 있습니다.

```
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 테이블 하나와 1GB 미만의 테이블 30개가 있다고 가정하십시오. 이 경우 더 큰 테이블에 특정 파라미터를 설정하여 전체 시스템의 동작이 변경되지 않도록 할 수 있습니다.

```
ALTER TABLE mytable set (autovacuum_vacuum_cost_delay=0);
```

이렇게 하면 시스템의 리소스를 더 많이 사용하는 대신 이 테이블의 비용에 따른 autovacuum 지연이 비활성화됩니다. 일반적으로 매시간 `autovacuum_cost_limit`에 도달한 `autovacuum_vacuum_cost_delay`의 autovacuum이 일시 중지됩니다. 자세한 내용은 [비용에 따른 vacuum 수행](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST)에 대한 PostgreSQL 설명서에서 확인할 수 있습니다.

# autovacuum 및 vacuum 활동 로그
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging"></a>

autovacuum 활동에 대한 정보는 `rds.force_autovacuum_logging_level` 파라미터에 지정된 레벨을 기반으로 `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까지의 값으로 설정하는 것이 좋습니다. 5,000밀리초 이상 걸리는 5000개의 기록 활동 설정. -1을 제외한 모든 설정은 충돌하는 잠금 또는 동시에 삭제된 관계로 인해 autovacuum 작업을 건너뛴 경우에도 메시지를 기록합니다. 자세한 내용은 PostgreSQL 설명서의 [자동 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>

 DROP DATABASE 작업 도중에 중단된 데이터베이스를 유효하지 않은 것으로 나타내는 새 `-2` 값이 `pg_database` 카탈로그의 `datconnlimit` 열에 도입되었습니다.

 이 새 값은 다음과 같은 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;
```

이 쿼리를 사용하면 PostgreSQL 환경 전체의 트랜잭션 ID 사용 기간을 정확하게 반영하여 유효한 데이터베이스만 `age(datfrozenxid)` 계산에 고려합니다.

## 잘못된 데이터베이스 문제 해결
<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에서 공격적인 vacuum 블로커 식별 및 해결
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring"></a>

PostgreSQL에서는 vacuum 작업이 스토리지를 회수하고 [트랜잭션 ID 랩어라운드](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND) 문제를 방지하기 때문에 데이터베이스의 좋은 상태를 위해 vacuum 작업이 중요합니다. 그러나 vacuum 작업이 원하는 대로 작동하지 않게 되는 경우가 있어 성능이 저하되고, 스토리지가 팽창하고, 트랜잭션 ID 랩어라운드로 인해 DB 인스턴스의 가용성이 영향을 받을 수 있습니다. 따라서 최적의 데이터베이스 성능과 가용성을 위해서는 이러한 문제를 식별하고 해결하는 것이 필수적입니다. Autovacuum에 대해 자세히 알아보려면 [Understanding autovacuum in Amazon RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)를 읽어보세요.

`postgres_get_av_diag()` 함수는 공격적 vacuum 진행 상황을 방지하거나 지연시키는 문제를 식별하는 데 도움이 됩니다. 제안이 제공되며, 여기에는 문제를 식별할 수 있는 경우 문제 해결을 위한 명령이, 문제를 식별할 수 없는 경우 추가 진단을 위한 지침이 포함될 수 있습니다. 공격적 vacuum 블로커는 연령이 RDS의 [적응형 autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming) 임곗값인 트랜잭션 ID 5억 개를 초과할 때 보고됩니다.

**트랜잭션 ID의 연령이란 무엇인가요?**

트랜잭션 ID에 대한 `age()` 함수는 데이터베이스(`pg_database.datfrozenxid`) 또는 테이블(`pg_class.relfrozenxid`)에 대해 가장 오래된 고정되지 않은 트랜잭션 ID 이후 발생한 트랜잭션 수를 계산합니다. 이 값은 마지막 공격적 vacuum 작업 이후의 데이터베이스 활동을 나타내며 향후 VACUUM 프로세스에 대해 가능한 워크로드를 강조합니다.

**공격적 vacuum이란 무엇인가요?**

공격적인 VACUUM 작업은 일반적인 VACUUM에서는 대개 건너 뛰는 페이지를 포함하여 테이블 내에 있는 모든 페이지에 대한 종합적인 스캔을 수행합니다. 이 철저한 스캔의 목표는 최대 연령에 근접한 트랜잭션 ID를 '고정'하여 [트랜잭션 ID 랩어라운드](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)라고 하는 상황을 효과적으로 방지하는 것을 목표로 합니다.

`postgres_get_av_diag()`가 블로커를 보고하려면 블로커의 연령이 최소 5억 개의 트랜잭션이어야 합니다.

**Topics**
+ [RDS for PostgreSQL에 자동 정리 모니터링 및 진단 도구 설치](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)
+ [RDS for PostgreSQL의 postgres\$1get\$1av\$1diag() 기능](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions.md)
+ [RDS for PostgreSQL에서 식별 가능한 vacuum 블로커 해결](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md)
+ [RDS for PostgreSQL에서 식별 불가능한 vacuum 블로커 해결](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers.md)
+ [RDS for PostgreSQL의 vacuum 성능 문제 해결](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md)
+ [RDS for PostgreSQL의 NOTICE 메시지 설명](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)

# RDS for PostgreSQL에 자동 정리 모니터링 및 진단 도구 설치
<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 데이터베이스에서 차단하거나 지연되는 자동 정리 프로세스에 대한 진단 정보를 검색합니다. 정확한 결과를 얻으려면 가장 오래된 트랜잭션 ID로 데이터베이스에서 쿼리를 실행해야 합니다. 가장 오래된 트랜잭션 ID로 데이터베이스를 사용하는 방법에 대한 자세한 내용은 [Not connected to the database with the age of oldest transaction 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**  
Vacuum을 차단하는 데이터베이스 활동의 범주를 보여줍니다.  
+ [활성 문](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)

**데이터베이스**  
적용 가능하고 지원되는 경우 데이터베이스의 이름을 보여줍니다. 활동이 진행 중이고 autovacuum을 차단 중이거나 차단할 데이터베이스입니다. 연결하고 조치를 취해야 하는 데이터베이스입니다.

**blocker\$1identifier**  
Autovacuum을 차단 중이거나 차단할 활동의 식별자를 보여줍니다. 식별자는 SQL 문, 준비된 트랜잭션, 읽기 전용 복제본의 IP 주소, 논리적 또는 물리적 복제 슬롯의 이름과 함께 프로세스 ID일 수 있습니다.

**wait\$1event**  
차단 세션의 [대기 이벤트](PostgreSQL.Tuning.md) 를 지정하고 다음 블로커에 적용할 수 있습니다.  
+ 활성 문
+ 트랜잭션의 유휴 상태

**autovacum\$1lagging\$1by**  
범주당 백로그 작업에서 autovacuum이 지연되는 트랜잭션 수를 보여줍니다.

**suggestion**  
블로커를 해결하기 위한 제안을 보여줍니다. 이러한 지침에는 해당하는 경우 활동이 존재하는 데이터베이스의 이름, 해당하는 경우 세션의 프로세스 ID(PID) 및 수행할 작업이 포함됩니다.

**suggested\$1action**  
블로커를 해결하기 위해 수행해야 하는 작업을 제안합니다.

# RDS for PostgreSQL에서 식별 가능한 vacuum 블로커 해결
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers"></a>

Autovacuum은 공격적인 vacuum을 수행하고 트랜잭션 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의 [적응형 autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming) 임곗값인 트랜잭션 ID 5억 개를 초과할 때만 공격적 vacuum 블로커를 확인합니다. `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`) 변경 사항을 취소합니다. 요구 사항에 따라 문을 다시 실행할 수 있습니다. 그러나 autovacuum 프로세스가 공격적인 vacuum 작업을 완료한 후에만 다시 실행하는 것이 좋습니다.

## 트랜잭션의 유휴 상태
<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`) 변경 사항을 취소합니다. 요구 사항에 따라 문을 다시 실행할 수 있습니다. 그러나 autovacuum 프로세스가 공격적인 vacuum 작업을 완료한 후에만 다시 실행하는 것이 좋습니다.

## 준비된 트랜잭션
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction"></a>

PostgreSQL은 [준비된 트랜잭션](https://www.postgresql.org/docs/current/sql-prepare-transaction.html)이라고 하는 두 단계 커밋 전략의 일부인 트랜잭션을 허용합니다. `max_prepared_transactions` 파라미터를 0이 아닌 값으로 설정하면 활성화됩니다. 준비된 트랜잭션은 데이터베이스 충돌, 재시작 또는 클라이언트 연결 해제 후에도 트랜잭션이 내구성을 유지하고 계속 가능하도록 하기 위해 설계되었습니다. 일반 트랜잭션과 마찬가지로 트랜잭션 ID가 할당되며 autovacuum에 영향을 미칠 수 있습니다. 준비된 상태로 두면 autovacuum이 고정을 수행할 수 없으며 트랜잭션 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 정보를 덮어쓰지 않도록 시스템이 보존해야 하므로 디스크 사용량이 증가하고 특히 autovacuum이 내부 카탈로그 테이블을 정리하지 못하게 됩니다. 해결하지 않으면 카탈로그 팽창, 성능 저하 및 랩어라운드 vacuum 위험 증가로 이어질 수 있으며 이로 인해 트랜잭션 가동 중지 시간이 발생할 수도 있습니다.

**활성이지만 느린 논리적 복제 슬롯**

논리적 복제의 성능 저하로 인해 카탈로그의 데드 튜플 제거가 지연되는 경우가 있습니다. 이러한 복제 지연으로 인해 `catalog_xmin`의 업데이트 속도가 느려지고 카탈로그 팽창 및 랩어라운드 vacuum이 발생할 수 있습니다.

`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 DB 관련 문제를 해결하려면 어떻게 해야 하나요?](https://repost.aws/knowledge-center/rds-incompatible-network)
+ 데이터베이스 또는 DB 인스턴스를 사용할 수 없는 이유는 다음과 같습니다.
  + 복제본 인스턴스의 스토리지가 부족함 - 스토리지 추가에 대한 자세한 내용은 [Amazon RDS DB instances run out of storage](https://repost.aws/knowledge-center/rds-out-of-storage)를 검토하세요.
  + 호환되지 않는 파라미터 - 문제를 해결하는 방법에 대한 자세한 내용은 [호환되지 않는 파라미터 상태에서 멈춘 Amazon RDS DB 인스턴스를 해결하려면 어떻게 해야 하나요?](https://repost.aws/knowledge-center/rds-incompatible-parameters)를 검토하세요.

인스턴스가 AWS 네트워크 외부 또는 AWS EC2에 있는 경우 관리자에게 가용성 또는 인프라 관련 문제를 해결하는 방법을 문의하세요.

**비활성 슬롯 삭제**

**주의**  
주의: 복제 슬롯을 삭제하기 전에 복제가 진행 중이지 않고 비활성 상태이며 복구할 수 없는 상태인지 주의 깊게 확인합니다. 슬롯을 성급히 삭제하면 복제가 중단되거나 데이터가 손실될 수 있습니다.

복제 슬롯이 더 이상 필요하지 않음을 확인한 후 autovacuum이 계속되도록 슬롯을 삭제합니다. `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` 설정이 활성화된 경우 기본 데이터베이스의 autovacuum이 읽기 전용 복제본에서 실행되는 쿼리에 여전히 필요할 수 있는 데드 행을 제거하는 것을 방지합니다. 이는 복제 슬롯을 사용하거나 사용하지 않고 관리되는 복제본을 포함하여 모든 유형의 물리적 읽기 전용 복제본에 영향을 미칩니다. 대기 복제본에서 실행되는 쿼리가 [쿼리 충돌](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT) 및 취소를 방지하면서 기본에서 해당 행을 계속 사용 가능하도록 요구하기 때문에 이 동작이 필요합니다.

**물리적 복제 슬롯을 사용하는 읽기 전용 복제본**  
물리적 복제 슬롯을 사용하는 읽기 전용 복제본은 RDS for PostgreSQL에서 복제의 신뢰성과 안정성을 크게 향상시킵니다. 이러한 슬롯은 복제본이 처리할 때까지 기본 데이터베이스가 필수 Write-Ahead Log 파일을 유지하여 네트워크 중단 중에도 데이터 일관성을 유지하도록 합니다.

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` 열에서 권장하는 대로 이러한 옵션을 주의 깊게 검토하여 autovacuum 차단을 해제합니다.
+ **쿼리 종료** - 제안 열의 지침에 따라 suggested\$1action 열에 지정된 대로 읽기 전용 복제본에 연결할 수 있습니다. 세션을 종료하는 옵션을 주의 깊게 검토하는 것이 좋습니다. 종료가 안전한 것으로 간주되는 경우 `pg_terminate_backend()` 함수를 사용하여 세션을 종료할 수 있습니다. 이 작업은 관리자(예: RDS 마스터 계정) 또는 필요한 pg\$1terminate\$1backend() 권한이 있는 사용자가 수행할 수 있습니다.

  읽기 전용 복제본에서 다음 SQL 명령을 실행하여 기본의 vacuum이 오래된 행을 정리하지 못하게 하는 쿼리를 종료할 수 있습니다. `backend_xmin`의 값은 함수의 출력에 보고됩니다.

  ```
  SELECT
      pg_terminate_backend(pid)
  FROM
      pg_catalog.pg_stat_activity
  WHERE
      backend_xmin::text::bigint = backend_xmin;
  ```
+ **상시 대기 피드백 비활성화** - `hot_standby_feedback` 파라미터가 심각한 vacuum 지연을 일으키는 경우 해당 파라미터를 비활성화하는 것을 고려합니다.

  `hot_standby_feedback` 파라미터를 사용하면 읽기 전용 복제본이 기본에 쿼리 활동을 알려 기본이 대기에서 사용 중인 테이블이나 행을 정리하지 못하도록 할 수 있습니다. 이렇게 하면 대기의 쿼리 안정성이 보장되지만 기본의 vacuum이 크게 지연될 수 있습니다. 이 기능을 비활성화하면 대기가 따라잡기를 기다리지 않고 기본이 vacuum 작업을 진행할 수 있습니다. 그러나 기본이 정리한 행에 대기가 액세스하려고 하면 대기에서 쿼리 취소 또는 실패가 발생할 수 있습니다.
+ **필요하지 않은 경우 읽기 전용 복제본 삭제** - 읽기 전용 복제본이 더 이상 필요하지 않은 경우 삭제할 수 있습니다. 이렇게 하면 연결된 복제 오버헤드가 제거되고 기본이 복제본에 의해 지연되지 않고 트랜잭션 로그를 재활용할 수 있습니다.

## 임시 테이블
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables"></a>

`TEMPORARY` 키워드를 사용하여 만든 [임시 테이블](https://www.postgresql.org/docs/current/sql-createtable.html)은 pg\$1temp\$1xxx와 같은 임시 스키마에 상주하며 해당 테이블을 만든 세션에서만 액세스할 수 있습니다. 세션이 종료되면 임시 테이블이 삭제됩니다. 그러나 이러한 테이블은 PostgreSQL의 autovacuum 프로세스에는 보이지 않으며 테이블을 만든 세션에서 수동으로 vacuum 처리해야 합니다. 다른 세션에서 임시 테이블을 정리하려고 해도 아무런 효과가 없습니다.

비정상적인 상황에서는 임시 테이블이 활성 세션 없이 존재합니다. 치명적인 충돌, 네트워크 문제 또는 유사한 이벤트로 인해 소유 세션이 예기치 않게 종료되는 경우 임시 테이블이 정리되지 않아 '고립된' 테이블로 남겨질 수 있습니다. PostgreSQL autovacuum 프로세스가 고립된 임시 테이블을 감지하면 다음 메시지를 로깅합니다.

```
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` 열에 제공된 지침에 따라 autovacuum 실행을 막는 임시 테이블을 식별하고 제거합니다. 다음 명령을 사용하여 `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에서 식별 불가능한 vacuum 블로커 해결
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers"></a>

이 섹션에서는 vacuum 작업이 진행되지 않는 다른 이유를 살펴봅니다. 이러한 문제는 현재 `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이 해당 페이지에 액세스하는 동안 페이지의 체크섬에서 불일치를 감지할 때 발생합니다. 내용을 읽을 수 없어 autovacuum이 튜플을 고정시킬 수 없습니다. 이로 인해 정리 프로세스가 중지됩니다. 다음 오류가 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'은 `pg_database` 시스템 카탈로그에서 조회할 수 있는 데이터베이스 OID입니다.
+ '186752608'은 `pg_class` 시스템 카탈로그에서 스키마 및 객체 이름을 조회하는 데 사용할 수 있는 `relfilenode`입니다.

영향을 받는 데이터베이스에서 다음 쿼리의 출력을 확인하여 객체 유형을 확인할 수 있습니다. 다음 쿼리는 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 이상에서 사용할 수 있습니다.

  인덱스를 우회하면 일관되지 않은 인덱스의 vacuum 프로세스를 건너뛰고 랩어라운드 문제를 완화할 수 있습니다. 그러나 이렇게 해도 기본 유효하지 않은 페이지 문제는 해결되지 않습니다. 유효하지 않은 페이지 문제를 완전히 해결하려면 인덱스를 다시 구축해야 합니다.

**객체 유형이 구체화된 뷰인 경우:**

구체화된 뷰에서 유효하지 않은 페이지 오류가 발생하면 영향을 받는 데이터베이스에 로그인하고 새로 고쳐 유효하지 않은 페이지를 해결합니다.

구체화된 뷰를 새로 고침:

```
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 Support에 문의하세요.

## 인덱스 불일치
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency"></a>

논리적으로 일치하지 않는 인덱스는 autovacuum이 진행되는 것을 방지할 수 있습니다. 다음 오류 또는 유사한 오류는 인덱스의 vacuum 단계 동안 또는 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 이상에서 사용할 수 있습니다.

  인덱스를 우회하면 일관되지 않은 인덱스의 vacuum 프로세스를 건너뛰고 랩어라운드 문제를 완화할 수 있습니다. 그러나 이렇게 해도 기본 유효하지 않은 페이지 문제는 해결되지 않습니다. 유효하지 않은 페이지 문제를 완전히 해결하려면 인덱스를 다시 구축해야 합니다.

## 매우 높은 트랜잭션 속도
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate"></a>

PostgreSQL에서 높은 트랜잭션 속도는 autovacuum의 성능에 상당한 영향을 미쳐 데드 튜플의 정리가 느려지고 트랜잭션 ID 랩어라운드 위험이 증가할 수 있습니다. 두 기간의 `max(age(datfrozenxid))` 차이(일반적으로 초당)를 측정하여 트랜잭션 속도를 모니터링할 수 있습니다. 또한 RDS 성능 개선 도우미의 다음 카운터 지표를 사용하여 총 트랜잭션 수인 트랜잭션 속도(xact\$1commit과 xact\$1rollback의 합계)를 측정할 수 있습니다.


|  카운터  |  유형  |  Unit  |  지표  | 
| --- | --- | --- | --- | 
|  xact\$1commit  |  트랜잭션  |  초당 커밋 수  |  db.Transactions.xact\$1commit  | 
|  xact\$1rollback  |  트랜잭션  |  초당 롤백 수  |  db.Transactions.xact\$1rollback  | 

빠른 증가는 트랜잭션 로드가 높음을 나타내며, 이는 autovacuum에 부담을 주어 팽창, 잠금 경합 및 잠재적 성능 문제를 일으킬 수 있습니다. 이는 다음과 같은 몇 가지 방법으로 autovacuum 프로세스에 부정적인 영향을 미칠 수 있습니다.
+ **테이블 활동:** Vacuum 처리 중인 특정 테이블에 대량의 트랜잭션이 발생하여 지연이 발생할 수 있습니다.
+ **시스템 리소스:** 전체 시스템에 과부하가 발생하여 autovacuum이 효율적으로 작동하는 데 필요한 리소스에 액세스하기 어려울 수 있습니다.

Autovacuum이 더 효과적으로 작동하고 작업을 따라잡을 수 있도록 하려면 다음 전략을 고려하세요.

1. 가능하면 트랜잭션 속도를 줄입니다. 가능한 경우 유사한 트랜잭션을 배치 처리하거나 그룹화하는 것을 고려합니다.

1. 사용량이 적은 시간에 야간, 주간 또는 격주로 수동 `VACUUM FREEZE` 작업을 사용하여 자주 업데이트되는 테이블을 타게팅합니다.

1. 인스턴스 클래스를 스케일 업하여 높은 트랜잭션 볼륨과 autovacuum을 처리할 수 있도록 더 많은 시스템 리소스를 할당하는 것을 고려합니다.

# RDS for PostgreSQL의 vacuum 성능 문제 해결
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance"></a>

이 섹션에서는 느린 vacuum 성능에 영향을 미치는 요인과 이러한 문제를 해결하는 방법을 설명합니다.

**Topics**
+ [큰 인덱스 vacuum](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes)
+ [테이블 또는 데이터베이스가 너무 많아 vacuum 작업을 할 수 없음](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables)
+ [공격적 vacuum(랩어라운드 방지용) 실행 중](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)

## 큰 인덱스 vacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes"></a>

VACUUM은 초기화, 힙 스캔, 인덱스 및 힙 vacuum, 인덱스 정리, 힙 잘라내기 및 최종 정리와 같은 순차적 단계를 거칩니다. 힙 스캔 중에 프로세스는 페이지를 정리하고 조각 모음을 하여 고정합니다. 힙 스캔이 완료되면 VACUUM은 인덱스를 정리하고 빈 페이지를 운영 체제로 반환하며 빈 공간 맵 vacuum 및 통계 업데이트와 같은 최종 정리 작업을 수행합니다.

인덱스를 vacuum할 때 `maintenance_work_mem`(또는 `autovacuum_work_mem`)이 인덱스를 처리하기에 충분하지 않은 경우 여러 번 전달해야 할 수 있습니다. PostgreSQL 16 이하에서는 데드 튜플 ID 저장을 위한 1GB 메모리 제한이 있어 큰 인덱스에서는 여러 번의 전달이 강제될 때가 많았습니다. PostgreSQL 17에는 단일 할당 배열을 사용하는 대신 메모리를 동적으로 할당하는 `TidStore`가 도입되었습니다. 이렇게 하면 1GB 제약이 제거되고, 메모리를 더 효율적으로 사용하며, 인덱스당 여러 인덱스 스캔의 필요성이 줄어듭니다.

사용 가능한 메모리가 전체 인덱스 처리를 한 번에 수용할 수 없는 경우에도 큰 인덱스는 PostgreSQL 17에서 여러 번 전달해야 할 수 있습니다. 일반적으로 큰 인덱스에는 여러 번 전달해야 하는 데드 튜플이 더 많이 포함되어 있습니다.

**느린 vacuum 작업 탐지**

`postgres_get_av_diag()` 함수는 메모리 부족으로 인해 vacuum 작업이 느리게 실행되는 시기를 탐지할 수 있습니다. 이 함수에 대한 자세한 내용은 [RDS for PostgreSQL에 자동 정리 모니터링 및 진단 도구 설치](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md) 단원을 참조하십시오.

사용 가능한 메모리가 단일 패스에서 인덱스 vacuuming을 완료하기에 충분하지 않은 경우 `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()` 함수는 인덱스 vacuum 작업에 필요한 메모리의 양을 추정하기 위해 `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`를 사용해 다음 해결 방법을 적용하여 테이블 고정의 속도를 높일 수 있습니다.

**Vacuum 작업을 위한 메모리 증가**

`postgres_get_av_diag()` 함수에서 제안한 대로 인스턴스 수준에서 잠재적 메모리 제약을 해결하기 위해 `autovacuum_work_mem` 파라미터를 늘리는 것이 좋습니다. `autovacuum_work_mem`은 동적 파라미터이지만 새 메모리 설정이 적용되려면 autovacuum 대몬이 작업자를 다시 시작해야 합니다. 이를 수행하는 방법은 다음과 같습니다.

1. 새 설정이 있는지 확인합니다.

1. 현재 autovacuum을 실행 중인 프로세스를 종료합니다.

이 접근 방식을 사용하면 조정된 메모리 할당이 새 autovacuum 작업에 적용됩니다.

보다 즉각적인 결과를 얻으려면 세션 내에서 `maintenance_work_mem` 설정이 증가된 `VACUUM FREEZE` 작업을 수동으로 수행하는 것을 고려하세요.

```
SET maintenance_work_mem TO '1GB';
VACUUM FREEZE VERBOSE table_name;
```

Amazon RDS를 사용하고 있고 `maintenance_work_mem` 또는 `autovacuum_work_mem`에 대해 더 높은 값을 지원하는 데 추가 메모리가 필요한 경우 메모리가 더 많은 인스턴스 클래스로 업그레이드하는 것을 고려해 보세요. 이를 통해 수동 및 자동 vacuum 작업을 모두 개선하는 데 필요한 리소스를 제공하여 전반적인 vacuum 및 데이터베이스 성능을 개선할 수 있습니다.

**INDEX\$1CLEANUP 비활성화**

PostgreSQL 버전 12 이상의 수동 `VACUUM`에서는 인덱스 정리 단계를 건너뛸 수 있고, PostgreSQL 버전 14 이상의 긴급 autovacuum에서는 [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) 파라미터를 기반으로 자동으로 이 작업을 수행합니다.

**주의**  
인덱스 정리를 건너뛰면 인덱스 팽창이 발생하여 쿼리 성능에 부정적인 영향을 미칠 수 있습니다. 이를 완화하려면 영향을 받는 인덱스를 유지 관리 기간 동안 다시 인덱싱하거나 vacuum하는 것이 좋습니다.

큰 인덱스 처리에 대한 추가 지침은 [대용량 인덱스를 사용하여 autovacuum 관리](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md)의 설명서를 참조하세요.

**병렬 인덱스 vacuum 작업**

PostgreSQL 13부터 인덱스는 각 인덱스에 하나의 vacuum 작업자 프로세스가 할당된 수동 `VACUUM`을 사용하여 기본적으로 병렬로 vacuum 및 정리가 가능합니다. 그러나 vacuum 작업이 병렬 실행에 적합한지 PostgreSQL이 확인하려면 다음과 같은 특정 기준을 충족해야 합니다.
+ 인덱스가 최소 2개 있어야 합니다.
+ `max_parallel_maintenance_workers` 파라미터 값을 최소 2로 설정합니다.
+ 인덱스 크기는 `min_parallel_index_scan_size` 한도를 초과해야 하며, 기본값은 512KB입니다.

Amazon RDS 인스턴스에서 사용할 수 vCPU의 수와 테이블의 인덱스 수에 따라 `max_parallel_maintenance_workers` 설정을 조정하여 vacuum 작업 처리 시간을 최적화할 수 있습니다.

자세한 내용은 [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/)을 참조하세요.

## 테이블 또는 데이터베이스가 너무 많아 vacuum 작업을 할 수 없음
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables"></a>

PostgreSQL의 [The Autovacuum Daemon](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM') 설명서에서 언급한 것처럼 autovacuum 대몬은 여러 프로세스를 통해 작동합니다. 여기에는 시스템 내 각 데이터베이스에 대해 autovacuum 작업자 프로세스를 시작하는 영구 autovacuum 런처가 포함됩니다. 런처는 데이터베이스당 약 `autovacuum_naptime`초마다 이러한 작업자가 시작하도록 일정을 예약합니다.

데이터베이스가 'N'개이면 새 작업자가 대략 [`autovacuum_naptime`/N초]마다 시작합니다. 그러나 총 동시 작업자 수는 `autovacuum_max_workers` 설정에 따라 제한됩니다. Vacuum 작업이 필요한 데이터베이스 또는 테이블 수가 이 한도를 초과하는 경우 작업자를 사용할 수 있게 되는 즉시 다음 데이터베이스 또는 테이블이 처리됩니다.

많은 대형 테이블 또는 데이터베이스에서 동시에 vacuum 작업이 필요한 경우 사용 가능한 모든 autovacuum 작업자가 장기간 점유되어 다른 테이블 및 데이터베이스에 대한 유지 관리가 지연될 수 있습니다. 트랜잭션 속도가 높은 환경에서는 이 병목 현상이 빠르게 에스컬레이션되어 Amazon RDS 인스턴스 내에서 vacuum 랩어라운드 문제가 발생할 수 있습니다.

`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 증가**

Vacuum 작업의 속도를 높이기 위해 더 많은 동시 autovacuum 작업자를 허용하도록 `autovacuum_max_workers` 파라미터를 조정하는 것이 좋습니다. 성능 병목 현상이 지속되면 Amazon RDS 인스턴스를 더 많은 vCPU가 있는 클래스로 스케일 업하는 것이 좋습니다. 이렇게 하면 병렬 처리 기능을 더욱 개선할 수 있습니다.

## 공격적 vacuum(랩어라운드 방지용) 실행 중
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum"></a>

PostgreSQL의 데이터베이스(MaximumUsedTransactionIDs) 연령은 공격적 vacuum(랩어라운드 방지용)이 성공적으로 완료될 때만 감소합니다. 이 vacuum 작업이 완료될 때까지 트랜잭션 속도에 따라 연령이 계속 증가합니다.

`postgres_get_av_diag()` 함수는 공격적인 vacuum을 감지하면 다음 `NOTICE`를 생성합니다. 그러나 vacuum의 활성 상태가 최소 2분간 지속된 후에만 이 출력이 트리거됩니다.

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```

공격적 vacuum에 대한 자세한 내용은 [When an aggressive vacuum is already running](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md) 섹션을 참조하세요.

다음 쿼리를 사용하여 공격적인 vacuum이 진행 중인지 확인할 수 있습니다.

```
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;
```

출력의 쿼리 열을 확인하여 공격적인 vacuum(랩어라운드 방지용)인지 확인할 수 있습니다. '랩어라운드 방지용'이라는 문구는 공격적인 vacuum임을 나타냅니다.

```
query                  | autovacuum: VACUUM public.t3 (to prevent wraparound)
```

예를 들어, 트랜잭션 연령이 10억인 블로커가 있고 동일한 트랜잭션 연령에서 랩어라운드 방지용으로 공격적인 vacuum이 필요한 테이블이 있다고 가정해 보겠습니다. 또한 트랜잭션 연령이 7억 5,000만인 또 다른 블로커가 있습니다. 트랜잭션 연령이 1억인 블로커를 정리한 후에 트랜잭션 연령이 7억 5,000만으로 즉시 줄어들지 않습니다. 공격적인 vacuum이 필요한 테이블 또는 연령이 7억 5,000만이 넘는 트랜잭션이 완료될 때까지 트랜잭션 연령이 높게 유지됩니다. 이 기간 동안 PostgreSQL 클러스터의 트랜잭션 연령이 계속 증가합니다. Vacuum 프로세스가 완료되면 트랜잭션 연령이 7억 5,000만으로 감소하지만 추가 vacuum 작업이 완료될 때까지 다시 증가하기 시작합니다. 이 주기는 이러한 조건이 지속되는 한, 트랜잭션 연령이 결국 `autovacuum_freeze_max_age`에서 지정된 Amazon RDS 인스턴스에 대해 구성된 수준으로 떨어질 때까지 계속됩니다.

# RDS for PostgreSQL의 NOTICE 메시지 설명
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE"></a>

 `postgres_get_av_diag()` 함수는 다음 NOTICE 메시지를 제공합니다.

**연령이 모니터링 임곗값에 아직 도달하지 않은 경우**  
`postgres_get_av_diag()`가 블로커를 식별하기 위한 모니터링 임곗값은 기본적으로 5억 개의 트랜잭션입니다. `postgres_get_av_diag()`가 다음 NOTICE를 생성하면 트랜잭션 연령이 아직이 임곗값에 도달하지 않았음을 나타냅니다.  

```
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를 가진 데이터베이스에 연결되지 않음**  
`postgres_get_av_diag()` 함수는 연령이 가장 많은 트랜잭션 ID를 가진 데이터베이스에 연결할 때 가장 정확한 출력을 제공합니다. `postgres_get_av_diag()`에서 보고한 연령이 가장 많은 트랜잭션 ID를 가진 데이터베이스는 사용자의 경우 'my\$1database'와 다릅니다. 올바른 데이터베이스에 연결되지 않은 경우 다 NOTICE가 생성됩니다.  

```
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.
```
연령이 가장 많은 트랜잭션을 가진 데이터베이스에 연결하는 것은 다음과 같은 이유로 중요합니다.  
+ **임시 테이블 블로커 식별:** 임시 테이블의 메타데이터는 각 데이터베이스마다 다르기 때문에 일반적으로 테이블이 만들어진 데이터베이스에서 찾을 수 있습니다. 그러나 임시 테이블이 최상위 블로커이고 수명이 가장 많은 트랜잭션을 가진 데이터베이스에 있는 경우 이는 오해의 소지가 있을 수 있습니다. 올바른 데이터베이스에 연결하면 임시 테이블 블로커를 정확하게 식별할 수 있습니다.
+ **느린 vacuum 진단:** 인덱스 메타데이터 및 테이블 수 정보는 데이터베이스별로 다르며 느린 vacuum 문제를 진단하는 데 필요합니다.

**연령을 기준으로 가장 오래된 트랜잭션을 가진 데이터베이스가 rdsadmin 또는 template0 데이터베이스임**  
경우에 따라 `rdsadmin` 또는 `template0` 데이터베이스가 연령이 가장 많은 트랜잭션 ID를 가진 데이터베이스로 식별될 수 있습니다. 이 경우 `postgres_get_av_diag()`는 다음 NOTICE를 발행합니다.  

```
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` 데이터베이스가 최상위 블로커를 포함할 가능성은 매우 낮습니다.

**공격적 vacuum이 이미 실행 중인 경우**  
`postgres_get_av_diag()` 함수는 공격적인 vacuum 프로세스가 실행 중일 때 보고하도록 설계되었지만, vacuum이 최소 1분 동안 활성 상태인 경우에만 이 출력을 트리거합니다. 이러한 의도적인 지연은 오탐지의 가능성을 줄이는 데 도움이 됩니다. 이 함수는 대기함으로써 효과적이고 중요한 vacuum만 보고되도록 하므로 vacuum 활동을 보다 정확하고 안정적으로 모니터링할 수 있습니다.  
`postgres_get_av_diag()` 함수는 진행 중인 공격적인 vacuum이 하나 이상인 것을 감지하면 다음 NOTICE를 생성합니다.  

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```
NOTICE에 표시된 대로 vacuum의 성능을 계속 모니터링합니다. 공격적 vacuum에 대한 자세한 내용은 [공격적 vacuum(랩어라운드 방지용) 실행 중](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum) 섹션을 참조하세요.

**Autovacuum이 꺼져 있는 경우**  
데이터베이스 인스턴스에서 autovacuum이 비활성화된 경우 `postgres_get_av_diag()` 함수는 다음 NOTICE를 생성합니다.  

```
NOTICE: Autovacuum is OFF, we strongly recommend to enable it, no restart is necessary.
```
자동 정리는 원활한 데이터베이스 작업을 보장하는 RDS for PostgreSQL DB 인스턴스의 중요한 기능입니다. 오래된 행 버전을 자동으로 제거하고, 스토리지 공간을 회수하고, 테이블 팽창을 방지하여 테이블과 인덱스를 효율적으로 유지함으로써 최적의 성능을 발휘하도록 합니다. 또한 Amazon RDS 인스턴스에서 트랜잭션을 중지할 수 있는 트랜잭션 ID 랩어라운드를 방지합니다. Autovacuum을 비활성화하면 데이터베이스 성능과 안정성이 장기적으로 저하될 수 있습니다. 항상 켜두는 것이 좋습니다. 자세한 내용은 [Understanding autovacuum in RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)를 참조하세요.  
Autovacuum을 끄더라도 공격적인 vacuum이 중지되지 않습니다. 테이블이 `autovacuum_freeze_max_age` 임곗값에 도달하면 여전히 공격적 vacuum이 발생합니다.

**남은 트랜잭션 수가 매우 적음**  
`postgres_get_av_diag()` 함수는 랩어라운드 vacuum이 임박하면 다음 NOTICE를 생성합니다. 이 NOTICE는 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 작업을 면밀히 모니터링하고 영향을 받는 데이터베이스에서 `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 유틸리티](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` 잠금이 필요합니다. 즉, 작업이 완료될 때까지 다른 쿼리는 액세스할 수 없습니다.

**영향: 파일 설명자 소진**  
오류: "파일 설명자 부족: 시스템에 열려 있는 파일이 너무 많습니다. 릴리스 및 재시도하세요." PostgreSQL 파라미터 `max_files_per_process`는 각 프로세스가 열 수 있는 파일 수를 결정합니다. 많은 수의 테이블을 조인하는 연결 수가 많은 경우 이 제한에 도달할 수 있습니다.  
**권장 조치:**  
+ 파라미터 `max_files_per_process`의 값을 낮추면 이 오류를 완화하는 데 도움이 될 수 있습니다. 각 프로세스 및 하위 프로세스(예: 병렬 쿼리)는 이 수의 파일을 열 수 있으며 쿼리가 여러 테이블을 조인하는 경우 이 제한이 소진될 수 있습니다.
+ 전체 연결 수를 줄이고 [Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)와 같은 연결 풀러 또는 PgBouncer와 같은 기타 솔루션을 사용합니다. 자세히 알아보려면 [PgBouncer](https://www.pgbouncer.org/) 웹 사이트를 참조하세요.

**영향: Inode 소진**  
“디바이스에 남은 공간 없음” 오류가 표시됩니다. 스토리지 여유 공간이 많은데 이러한 현상이 관찰되었다면 inode가 부족해지고 있기 때문입니다. [Amazon RDS Enhanced Monitoring](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)은 사용 중인 inode에 대한 가시성과 호스트에 사용할 수 있는 최대 수를 제공합니다.

**대략적인 임계값:** [수백만](#PostgreSQL.HighObjectCount.Note)

## 임시 테이블
<a name="PostgreSQL.HighObjectCount.TempTables"></a>

임시 테이블 사용은 테스트 데이터 또는 중간 결과에 유용하며 많은 데이터베이스 엔진에서 볼 수 있는 일반적인 패턴입니다. 일부 위험을 방지하려면 PostgreSQL에서 과도한 사용의 영향을 이해해야 합니다. 각 임시 테이블 생성 및 삭제는 시스템 카탈로그 테이블에 행을 추가하며, 테이블이 팽창하면 일반적인 성능 문제가 발생합니다.

**영향: Autovacuum이 뒤처짐**  
임시 테이블은 autovacuum에 의해 vacuum되지 않지만, 존재하는 동안 트랜잭션 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을 사용하여 변경 사항을 캡처하고 전송하기 때문에 로깅되지 않은 테이블은 일반적으로 논리적 복제에 포함되지 않습니다. 

  


**영향: 복구 중 가동 중지 시간 연장**  
장애 조치를 사용한 다중 AZ 재부팅, Amazon RDS 특정 시점 복구, Amazon RDS 메이저 버전 업그레이드와 같은 데이터베이스 충돌 복구와 관련된 데이터베이스 상태 중에는 로깅되지 않은 테이블을 잘라내는 직렬화된 작업이 발생합니다. 이로 인해 가동 중지 시간이 예상보다 훨씬 길어질 수 있습니다.  
**권장 조치:**  
+ 데이터베이스 충돌 복구 작업 중에 손실될 수 있는 데이터로만 로깅되지 않은 테이블의 사용을 최소화합니다.
+ 로깅되지 않은 테이블을 현재 직렬 잘라내기 동작으로 사용하는 것을 최소화하면 데이터베이스 시작에 상당한 시간이 걸릴 수 있습니다.

**일반 모범 사례:**
+ 로깅되지 않은 테이블은 충돌에 안전하지 않습니다. 충돌 복구를 수반하는 특정 시점으로 복구를 시작하는 것은 각 테이블을 잘라내는 직렬 프로세스이므로 PostgreSQL에서 상당한 시간이 걸립니다.

**대략적인 임계값:** [수천](#PostgreSQL.HighObjectCount.Note)

## 파티션
<a name="PostgreSQL.HighObjectCount.Partitions"></a>

파티셔닝은 쿼리 성능을 높이고 데이터의 논리적 구성을 제공할 수 있습니다. 이상적인 시나리오에서는 파티셔닝이 구성되어 쿼리 계획 및 실행 중에 파티션 정리를 사용할 수 있습니다. 파티션을 너무 많이 사용하면 쿼리 성능 및 데이터베이스 유지 관리에 부정적인 영향을 미칠 수 있습니다. 잘못된 설계로 인해 쿼리 계획 및 실행 성능이 부정적인 영향을 받을 수 있으므로 테이블을 분할하는 방법을 신중하게 선택해야 합니다. 파티셔닝에 대한 자세한 내용은 [PostgreSQL 설명서](https://www.postgresql.org/docs/current/ddl-partitioning.html)를 참조하세요.

**영향: 일반 성능 저하**  
간혹 시간 계획 오버헤드가 증가하고 쿼리에 대한 계획이 더 복잡해져 튜닝 기회를 식별하기가 어려워집니다. PostgreSQL 18 이전 버전의 경우 워크로드가 많은 여러 파티션에 `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)를 참조하세요. 워크로드에서 이러한 파일을 다수 생성하면 여러 가지 영향이 있을 수 있습니다.

  


**영향: 파일 설명자 소진**  
오류: "파일 설명자 부족: 시스템에 열려 있는 파일이 너무 많습니다. 릴리스 및 재시도하세요." PostgreSQL 파라미터 `max_files_per_process`는 각 프로세스가 열 수 있는 파일 수를 결정합니다. 많은 수의 테이블을 조인하는 연결 수가 많은 경우 이 제한에 도달할 수 있습니다.  
**권장 조치:**  
+ 파라미터 `max_files_per_process`의 값을 낮추면 이 오류를 완화하는 데 도움이 될 수 있습니다. 각 프로세스 및 하위 프로세스(예: 병렬 쿼리)는 이 수의 파일을 열 수 있으며 쿼리가 여러 테이블을 조인하는 경우 이 제한이 소진될 수 있습니다.
+ 전체 연결 수를 줄이고 [Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)와 같은 연결 풀러 또는 PgBouncer와 같은 기타 솔루션을 사용합니다. 자세히 알아보려면 [PgBouncer](https://www.pgbouncer.org/) 웹 사이트를 참조하세요.

**영향: Inode 소진**  
“디바이스에 남은 공간 없음” 오류가 표시됩니다. 스토리지 여유 공간이 많은데 이러한 현상이 관찰되었다면 inode가 부족해지고 있기 때문입니다. [Amazon RDS 향상된 모니터링](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)은 사용 중인 inode에 대한 가시성과 호스트에 사용할 수 있는 최대 수를 제공합니다.

**일반 모범 사례:**
+ [성능 개선 도우미](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PerfInsights.html)를 사용하여 임시 파일 사용량을 모니터링합니다.
+ 중요한 임시 파일을 생성하는 쿼리를 조정하여 임시 파일의 총 수를 줄일 수 있는지 확인합니다.

**대략적인 임계값:** [수천](#PostgreSQL.HighObjectCount.Note)

## 시퀀스
<a name="PostgreSQL.HighObjectCount.Sequences"></a>

시퀀스는 PostgreSQL에서 열을 자동 증분하는 데 사용되는 기본 객체이며 데이터의 고유성과 키를 제공합니다. 논리적 복제를 제외하고 정상 작업 중에는 결과 없이 개별 테이블에서 사용할 수 있습니다.

PostgreSQL에서 논리적 복제는 현재 시퀀스의 현재 값을 구독자에게 복제하지 않습니다. 자세한 내용은 [PostgreSQL 설명서의 등록 페이지](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 설명서의 등록 페이지](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(Oversized-Attribute Storage Technique)는 일반적인 8KB 데이터베이스 블록 크기를 초과하는 큰 데이터 값을 처리하도록 설계된 PostgreSQL 기능입니다. PostgreSQL은 물리적 행이 여러 블록에 걸쳐 있는 것을 허용하지 않습니다. 블록 크기는 행 크기에 대한 상한 역할을 합니다. TOAST는 큰 필드 값을 더 작은 청크로 분할하여 이러한 제한을 극복합니다. 기본 테이블에 연결된 전용 TOAST 테이블에 별도로 저장합니다. 자세한 내용은 [PostgreSQL TOAST 스토리지 메커니즘 및 구현 설명서](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 테이블의 해당 행을 참조하기 위해 TOAST 값 ID와 관계 ID를 페이지에 저장합니다. 이를 통해 PostgreSQL은 이러한 TOAST 청크를 효율적으로 찾고 관리할 수 있습니다. 그러나 TOAST 테이블이 증가함에 따라, 시스템에서 사용 가능한 OID가 소진되어 성능 저하와 OID 고갈로 인한 잠재적 가동 중지 시간이 발생할 위험이 있습니다.

### TOAST의 객체 식별자
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.ObjectIdentifiers"></a>

객체 식별자(OID)는 PostgreSQL에서 테이블, 인덱스 및 함수와 같은 데이터베이스 객체를 참조하는 데 사용하는 시스템 전체의 고유 식별자입니다. 이러한 식별자는 PostgreSQL의 내부 작업에서 중요한 역할을 하므로 데이터베이스가 객체를 효율적으로 찾고 관리할 수 있습니다.

토스팅에 적합한 데이터 세트가 있는 테이블의 경우 PostgreSQL은 OID를 할당하여 연결된 TOAST 테이블에 저장된 크기 초과 데이터의 각 청크를 고유하게 식별합니다. 시스템은 각 청크를 `chunk_id`와 연결하므로 PostgreSQL이 TOAST 테이블 내에서 이러한 청크를 효율적으로 구성하고 찾을 수 있습니다.

## 성능 문제 식별
<a name="Appendix.PostgreSQL.CommonDBATasks.TOAST_OID.PerformanceChallenges"></a>

PostgreSQL의 OID 관리는 40억 개의 고유 값을 생성한 후 래핑되도록 글로벌 32비트 카운터를 사용합니다. 데이터베이스 클러스터가 이 카운터를 공유하는 동안 OID 할당에는 TOAST 작업 중 두 단계가 포함됩니다.
+ **할당을 위한 글로벌 카운터** - 글로벌 카운터는 클러스터 전체에 새 OID를 할당합니다.
+ **로컬 충돌 검색** - TOAST 테이블은 새 OID가 해당 특정 테이블에 이미 사용된 기존 OID와 충돌하지 않도록 합니다.

성능 저하는 다음과 같은 경우에 발생할 수 있습니다.
+ TOAST 테이블의 조각화 수준이 높거나 OID 사용량이 밀집되어 OID 할당이 지연됩니다.
+ 시스템은 TOAST를 광범위하게 사용하는 데이터 이탈이 높거나 넓은 테이블이 있는 환경에서 OID를 자주 할당하고 재사용합니다.

자세한 내용은 [PostgreSQL TOAST 테이블 크기 제한 및 OID 할당 설명서](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` 문에만 발생합니다.
+ 시스템이 TOAST 테이블에서 사용 가능한 OID를 찾는 데 어려움을 겪으면 PostgreSQL 로그에 다음 로그 항목이 나타납니다.

  ```
  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.
  ```
+ Performance Insights는 `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>

대기 이벤트 `LWLock:buffer_io` 및 `LWLock:OidGenLock`은 새 객체 식별자(OID)를 할당해야 하는 작업 중에 Performance Insights에 표시됩니다. 이러한 이벤트에 대한 높은 평균 활성 세션(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 대기 이벤트 문제 해결 가이드](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 DB 인스턴스에 발생하는 기록 활동을 설정할 수 있는 파라미터, 확장 및 기타 구성 항목이 몇 가지 있습니다. 여기에는 다음이 포함됩니다.
+ `log_statement` 파라미터는 PostgreSQL 데이터베이스에서 사용자 활동 로그에 사용할 수 있습니다. RDS for PostgreSQL 로깅 및 로그를 모니터링하는 방법에 대한 자세한 내용은 [ RDS for PostgreSQL 데이터베이스 로그 파일](USER_LogAccess.Concepts.PostgreSQL.md) 섹션을 참조하세요.
+ `rds.force_admin_logging_level` 파라미터는 Amazon RDS 내부 사용자(rdsadmin)가 DB 인스턴스의 데이터베이스에서 수행한 작업을 기록합니다. PostgreSQL 오류 로그에 출력을 기록합니다. 허용되는 값은 `disabled`, `debug5`, `debug4`, `debug3`, `debug2`, `debug1`, `info`, `notice`, `warning`, `error`, 로그, `fatal` 및 `panic`입니다. 기본값은 `disabled`입니다.
+ PostgreSQL 오류 로그에서 다양한 autovacuum 작업을 캡처하도록 `rds.force_autovacuum_logging_level` 파라미터를 설정할 수 있습니다. 자세한 내용은 [autovacuum 및 vacuum 활동 로그](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging.md) 섹션을 참조하세요.
+ PostgreSQL Audit(pgAudit) 확장 프로그램은 세션 수준 또는 객체 수준에서 활동을 캡처하도록 설치 및 구성할 수 있습니다. 자세한 내용은 [pgAudit를 사용하여 데이터베이스 활동 로깅](Appendix.PostgreSQL.CommonDBATasks.pgaudit.md) 섹션을 참조하세요.
+ `log_fdw` 확장을 통해 SQL을 사용하여 데이터베이스 엔진 로그에 액세스할 수 있습니다. 자세한 정보는 [log\$1fdw 확장으로 SQL을 사용하여 DB 로그에 액세스](CHAP_PostgreSQL.Extensions.log_fdw.md)의 내용을 참조하세요.
+ `pg_stat_statements` 라이브러리가 RDS for PostgreSQL 버전 10 이상의 `shared_preload_libraries` 파라미터에 대한 기본값으로 지정됩니다. 실행 중인 쿼리를 분석할 때 사용할 수 있는 라이브러리입니다. `pg_stat_statements`가 DB 파라미터 그룹에 설정되는 것을 확인하세요. 이 라이브러리에서 제공하는 정보를 사용하여 RDS for PostgreSQL DB 인스턴스를 모니터링하는 방법에 대한 자세한 내용은 [RDS PostgreSQL에 대한 SQL 통계](USER_PerfInsights.UsingDashboard.AnalyzeDBLoad.AdditionalMetrics.PostgreSQL.md) 섹션을 참조하세요.
+ `log_hostname` 파라미터는 각 클라이언트 연결의 호스트 이름을 로그에 캡처합니다. RDS for PostgreSQL 버전 12 이상에서 이 파라미터는 기본적으로 `off`로 설정됩니다. 이 파라미터를 켰다면 세션 연결 시간을 모니터링해야 합니다. 이 파라미터를 켜면 서비스는 도메인 이름 시스템(DNS) 역방향 조회 요청을 사용하여, 연결할 클라이언트의 호스트 이름을 얻은 다음 PostgreSQL 로그에 추가합니다. 이렇게 되면 세션 연결 중에 상당한 영향이 발생합니다. 이 파라미터는 문제를 해결해야 할 때만 켜는 것이 좋습니다.

일반적으로 로깅의 목적은 DBA가 성능을 모니터링하고 튜닝하고 문제를 해결할 수 있도록 하는 것입니다. 대부분의 로그가 Amazon CloudWatch 또는 성능 개선 도우미로 자동 업로드됩니다. 여기서 로그는 DB 인스턴스에 대한 전체 지표를 제공하기 위해 정렬되고 그룹화됩니다. 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 DB 인스턴스 스토리지](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)를 참조하세요. CloudWatch에 게시되는 `FreeStorageSpace` 지표를 계속 모니터링하여 DB 인스턴스에 충분한 스토리지 여유 공간이 있는지 확인합니다. 자세한 내용은 [https://repost.aws/knowledge-center/storage-full-rds-cloudwatch-alarm](https://repost.aws/knowledge-center/storage-full-rds-cloudwatch-alarm) 단원을 참조하세요. 

임시 파일 사용량을 늘리는 다중 동시 쿼리가 포함된 워크로드에서는 Amazon RDS 최적화된 읽기 인스턴스를 사용하는 것이 좋습니다. 이러한 인스턴스는 SSD(Solid State Drive) 블록 스토리지에 기반한 NVMe(Non-Volatile Memory Express)를 사용하여 임시 파일을 배치할 수 있습니다. 자세한 내용은 [Amazon RDS Optimized Reads로 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\$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`에 대해 표시된 쿼리와 결합하면 쿼리 워크로드의 문제를 해결하고, 분석하고, 변경 사항을 확인할 수 있습니다.

  성능 개선 도우미를 사용하여 지표를 분석하고 쿼리를 분석하는 방법에 대한 자세한 내용은 [성능 개선 도우미 대시보드를 사용한 지표 분석](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/ko_kr/AmazonRDS/latest/UserGuide/images/rpg_mantempfiles_metrics.png)

1. **상위 SQL** 탭에서 **기본 설정** 아이콘을 선택합니다.

1. **기본 설정** 창에서 **상위 SQL** 탭에 표시할 다음 통계를 켜고 **계속**을 선택합니다.
   + 임시 쓰기/초
   + 임시 읽기/초
   + 임시 대량 쓰기/호출
   + 임시 대량 읽기/호출

1. 다음 예제에 나온 것처럼, 임시 파일은 `pg_ls_tmpdir`에 대해 표시된 쿼리와 함께 통합될 때 분할됩니다.  
![\[임시 파일 사용량을 표시하는 쿼리.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/rpg_mantempfiles_query.png)

`IO:BufFileRead` 및 `IO:BufFileWrite` 이벤트는 대개 워크로드의 상위 쿼리에서 임시 파일이 생성될 때 발생합니다. 데이터베이스 부하 및 상위 SQL 섹션의 AAS(상위 활성 세션)를 검토하여 `IO:BufFileRead` 및 `IO:BufFileWrite`에서 대기 중인 상위 쿼리를 식별하는 데 성능 개선 도우미를 사용할 수 있습니다.

![\[그래프에 IO:BufFileRead 및 IO:BufFileWrite가 표시되어 있습니다.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/perfinsights_IOBufFile.png)


성능 개선 도우미를 사용하여 상위 쿼리와 대기 이벤트에서 부하를 분석하는 방법에 대한 자세한 내용은 [상위 SQL(Top 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 성능 관련 통계 및 지표의 주기적인 수집을 지원할 수 있습니다. 자세한 내용은 [Monitor Amazon RDS for PostgreSQL performance using PGSnapper](https://aws.amazon.com/blogs/database/monitor-amazon-rds-for-postgresql-and-amazon-aurora-postgresql-performance-using-pgsnapper/)(PGSnapper를 사용하여 Amazon RDS for PostgreSQL 성능 모니터링)를 참조하세요.

# 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 for PostgreSQL DB 인스턴스에 `rds_superuser`로 연결하고 다음 명령을 실행합니다.

```
CREATE EXTENSION IF NOT EXISTS rds_casts;
```

## 지원되는 캐스트
<a name="PostgreSQL.CustomCasts.Supported"></a>

사용자 지정 캐스트를 사용하려는 각 데이터베이스에서 확장을 생성합니다. 확장을 생성한 후 다음 명령을 사용하여 사용 가능한 모든 캐스트를 봅니다.

```
SELECT * FROM rds_casts.list_supported_casts();
```

이 함수는 사용 가능한 캐스트 조합(소스 유형, 대상 유형, 강제 컨텍스트 및 캐스트 함수)을 나열합니다. 예를 들어 `implicit` 캐스트로 `text`에서 `numeric`으로의 변환을 생성하려는 경우 다음 쿼리를 사용하여 캐스트를 생성할 수 있는지 확인할 수 있습니다.

```
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 함수* - 변환 오류를 방지하기 위해 빈 문자열을 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` 열에는 EXPLICIT을 나타내는 `e`, ASSIGNMENT를 나타내는 `a`, IMPLICIT을 나타내는 `i`가 표시됩니다.

### 캐스트 삭제
<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 시스템의 경우 자동 병렬 쿼리 실행을 비활성화하는 것이 좋습니다. 병렬 처리는 분석 또는 보고 워크로드의 대규모 데이터 세트에 대한 쿼리를 가속화할 수 있지만, 사용량이 많은 프로덕션 환경에서는 이점을 능가하는 상당한 위험을 초래하는 경우가 자주 있습니다.

병렬 실행에도 상당한 오버헤드가 발생합니다. 각 병렬 작업자는 프로세스 포크(메모리 구조 복사 및 프로세스 상태 초기화) 및 인증(`max_connections` 제한에서 연결 슬롯 사용)이 필요한 전체 PostgreSQL 백엔드 프로세스입니다. 또한 각 작업자는 쿼리당 여러 작업자가 있는 정렬 및 해싱 작업의 `work_mem`을 포함하여 자체 메모리를 사용합니다. 메모리 사용량은 빠르게 증가합니다(예: 작업자 4명 × 쿼리당 64MB `work_mem` = 256MB). 따라서 병렬 쿼리는 단일 프로세스 쿼리보다 훨씬 더 많은 시스템 리소스를 사용할 수 있습니다. 제대로 조정하지 않으면 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가 많을수록 DB 인스턴스를 더 큰 컴퓨팅 크기로 확장하면 사용 가능한 최대 병렬 작업자 수가 자동으로 증가합니다. 따라서 이전에 직렬로 실행되었거나 병렬 처리가 제한된 쿼리는 스케일 업 작업 후 갑자기 더 많은 병렬 작업자를 활용하여 연결 사용량, 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 Database Insights](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 DB 인스턴스에 파라미터로 작업
<a name="Appendix.PostgreSQL.CommonDBATasks.Parameters"></a>

일부 경우, 사용자 정의 파라미터 그룹을 지정하지 않고 RDS for PostgreSQL DB 인스턴스를 생성할 수 있습니다. 이 경우 선택한 PostgreSQL 버전에 대한 기본 파라미터 그룹을 사용하여 DB 인스턴스가 생성됩니다. 예를 들어, PostgreSQL 13.3을 사용하여 RDS for PostgreSQL DB 인스턴스를 생성한다고 가정해 보겠습니다. 이 경우 DB 인스턴스는 PostgreSQL 13 릴리스용 파라미터 그룹(`default.postgres13`)의 값을 사용하여 생성됩니다.

사용자 지정 DB 파라미터 그룹을 생성할 수도 있습니다. RDS for PostgreSQL DB 인스턴스용 설정을 기본값에서 수정하려면 이 작업을 수행해야 합니다. 자세한 방법은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md)을 참조하세요.

RDS for PostgreSQL DB 인스턴스에서 설정을 여러 가지 방법으로 추적할 수 있습니다. AWS Management Console, 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 DB 인스턴스에서 `max_connections` 및 `shared_buffers`에 대한 설정을 변경할 때 특히 주의해야 합니다. 예를 들어 `max_connections` 또는 `shared_buffers`에 대한 설정을 수정해서 실제 워크로드에 비해 너무 높은 값을 사용한다고 가정하겠습니다. 이 경우 RDS for PostgreSQL DB 인스턴스는 시작되지 않습니다. 이 경우 `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.
```

그러나 PostgreSQL DB 파라미터 그룹의 기본 RDS에 포함된 설정 값은 변경할 수 없습니다. 파라미터에 대한 설정을 변경하려면 먼저 사용자 지정 DB 파라미터 그룹을 생성합니다. 그런 다음 해당 사용자 정의 그룹의 설정을 변경한 다음 사용자 정의 파라미터 그룹을 RDS for PostgreSQL DB 인스턴스에 적용합니다. 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md)를 참조하세요.

RDS for PostgreSQL에는 두 가지 유형의 파라미터가 있습니다.
+ **정적 파라미터** - 정적 파라미터를 사용하려면 변경 후 RDS for PostgreSQL DB 인스턴스를 재부팅해야 새 값이 적용됩니다.
+ **동적 파라미터** - 동적 파라미터는 설정을 변경한 후 재부팅할 필요가 없습니다.

**참고**  
RDS for PostgreSQL DB 인스턴스가 자체 사용자 정의 DB 파라미터 그룹을 사용하는 경우, 실행 중인 DB 인스턴스에서 동적 파라미터 값을 변경할 수 있습니다. AWS Management Console, AWS CLI 또는 Amazon RDS API를 사용하여 이 작업을 수행할 수 있습니다.

권한이 있는 경우 `ALTER DATABASE`, `ALTER ROLE` 및 `SET` 명령을 사용하여 파라미터 값을 변경할 수도 있습니다.

## RDS for PostgreSQL DB 인스턴스 파라미터 목록
<a name="Appendix.PostgreSQL.CommonDBATasks.Parameters.parameters-list"></a>

다음 표에는 RDS for PostgreSQL DB 인스턴스에서 사용할 수 있는 일부 파라미터가 나와 있습니다. 사용 가능한 모든 파라미터를 보려면 [describe-db-parameters](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-parameters.html) AWS CLI 명령을 사용하세요. 예를 들어 RDS for PostgreSQL 버전 13의 기본 파라미터 그룹에서 사용할 수 있는 모든 파라미터 목록을 가져오려면 다음을 실행합니다.

```
aws rds describe-db-parameters --db-parameter-group-name default.postgres13
```

콘솔을 사용할 수도 있습니다. Amazon RDS 메뉴에서 **파라미터 그룹**을 선택한 다음 AWS 리전에서 사용 가능한 파라미터 그룹 중에서 파라미터 그룹을 선택합니다.


|  파라미터 이름  |  적용 유형  |  설명  | 
| --- | --- | --- | 
|  `application_name`  | 동적 | 애플리케이션 이름이 통계 및 로그에 표시되도록 설정합니다. | 
|  `archive_command`  | 동적 | WAL 파일을 보관하기 위해 호출할 셸 명령을 설정합니다. | 
|  `array_nulls`  | 동적 | 어레이의 NULL 요소 입력을 활성화합니다. | 
|  `authentication_timeout`  | 동적 | 클라이언트 인증 완료를 위한 최대 허용 시간을 설정합니다. | 
|  `autovacuum`  | 동적 | autovacuum 서브프로세스를 시작합니다. | 
|  `autovacuum_analyze_scale_factor`  | 동적 | 분석 전 삽입, 업데이트 또는 삭제되는 튜플 수를 reltuples 분수 값으로 지정합니다. | 
|  `autovacuum_analyze_threshold`  | 동적 | 분석 전 삽입, 업데이트 또는 삭제되는 튜플의 최소 수를 지정합니다. | 
|  `autovacuum_freeze_max_age`  | 정적 | 트랜잭션 ID 랩어라운드를 방지하기 위한 테이블의 autovacuum 기간을 지정합니다. | 
|  `autovacuum_naptime`  | 동적 | autovacuum 실행 간 절전 시간을 지정합니다. | 
|  `autovacuum_max_workers`  | 정적 | autovacuum 작업자 프로세스를 동시에 실행할 수 있는 최대 수를 설정합니다. | 
|  `autovacuum_vacuum_cost_delay`  | 동적 | autovacuum에서 vacuum 코스트 지연 시간(밀리초)을 지정합니다. | 
|  `autovacuum_vacuum_cost_limit`  | 동적 | autovacuum에서 지연 시간 이전에 이용 가능한 vacuum 코스트 값을 지정합니다. | 
|  `autovacuum_vacuum_scale_factor`  | 동적 | vacuum 전 업데이트 또는 삭제되는 튜플 수를 reltuples 분수 값으로 지정합니다. | 
|  `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`  | 동적 | 로그 세그먼트에서 자동 write-ahead log(WAL) 체크포인트의 최대 간격을 설정합니다. | 
|  `checkpoint_timeout`  | 동적 | 자동 WAL 체크포인트 사이의 최대 시간을 설정합니다. | 
|  `checkpoint_warning`  | 동적 | 체크포인트 세그먼트가 이 파라미터 값보다 더 빨리 채워지는 경우 경고를 활성화합니다. | 
|  `client_connection_check_interval`  | 동적 |  쿼리를 실행하는 동안 연결 끊김 검사 사이의 시간 간격을 설정합니다. | 
|  `client_encoding`  | 동적 | 클라이언트 문자 세트 인코딩을 설정합니다. | 
|  `client_min_messages`  | 동적 | 클라이언트에게 보여지는 메시지 수준을 설정합니다. | 
|  `commit_delay`  | 동적 | 트랜잭션 커밋부터 디스크에 대한 WAL 플러시까지 지연 시간(밀리초)을 설정합니다. | 
|  `commit_siblings`  | 동적 | commit\$1delay 실행 전에 동시에 열려 있는 트랜잭션 최소 개수를 설정합니다. | 
|  `constraint_exclusion`  | 동적 | planner가 제약 조건을 사용하여 쿼리를 최적화하도록 활성화합니다. | 
|  `cpu_index_tuple_cost`  | 동적 | 인덱스 스캔 중 각 인덱스 항목을 처리하는 데 따른 planner의 예상 코스트를 설정합니다. | 
|  `cpu_operator_cost`  | 동적 | 각 연산자 또는 함수 호출을 처리하는 데 따른 planner의 예상 코스트를 설정합니다. | 
|  `cpu_tuple_cost`  | 동적 | 각 튜플(행)을 처리하는 데 따른 planner의 예상 코스트를 설정합니다. | 
|  `cursor_tuple_fraction`  | 동적 | planner가 예상하는 검색할 커서 행의 분수 값을 설정합니다. | 
|  `datestyle`  | 동적 | 날짜와 시간 값에 대한 표시 형식을 설정합니다. | 
|  `deadlock_timeout`  | 동적 | 교착 상태 여부를 확인하기 이전 잠금 대기 시간을 설정합니다. | 
|  `debug_pretty_print`  | 동적 | 구문과 실행 계획 트리를 들여쓰기 하여 표시합니다. | 
|  `debug_print_parse`  | 동적 | 각 쿼리의 구문 분석 트리를 기록합니다. | 
|  `debug_print_plan`  | 동적 | 각 쿼리의 실행 계획을 기록합니다. | 
|  `debug_print_rewritten`  | 동적 | 각 쿼리에서 재작성된 구문 분석 트리를 기록합니다. | 
|  `default_statistics_target`  | 동적 | 기본 통계 대상을 설정합니다. | 
|  `default_tablespace`  | 동적 | 테이블과 인덱스를 생성할 기본 테이블스페이스를 설정합니다. | 
|  `default_transaction_deferrable`  | 동적 | 새로운 트랜잭션의 기본 deferrable 상태를 설정합니다. | 
|  `default_transaction_isolation`  | 동적 | 새로운 트랜잭션마다 트랜잭션 격리 수준을 설정합니다. | 
|  `default_transaction_read_only`  | 동적 | 새로운 트랜잭션의 기본 읽기 전용 상태를 설정합니다. | 
|  `default_with_oids`  | 동적 | 새로운 테이블을 생성할 때 객체 ID(OID)가 기본적으로 포함됩니다. | 
|  `effective_cache_size`  | 동적 | 디스크 캐시 크기에 대한 planner의 가정을 설정합니다. | 
|  `effective_io_concurrency`  | 동적 | 디스크 하위 시스템에서 효율적으로 동시에 처리할 수 있는 요청 수를 지정합니다. | 
|  `enable_bitmapscan`  | 동적 | planner가 비트맵 스캔 계획을 사용할 수 있도록 활성화합니다. | 
|  `enable_hashagg`  | 동적 | planner가 해시된 집계 계획을 사용할 수 있도록 활성화합니다. | 
|  `enable_hashjoin`  | 동적 | planner가 해시 조인 계획을 사용할 수 있도록 활성화합니다. | 
|  `enable_indexscan`  | 동적 | planner가 인덱스 스캔 계획을 사용할 수 있도록 활성화합니다. | 
|  `enable_material`  | 동적 | planner가 구체화를 사용할 수 있도록 활성화합니다. | 
|  `enable_mergejoin`  | 동적 | planner가 병합 조인 계획을 사용할 수 있도록 활성화합니다. | 
|  `enable_nestloop`  | 동적 | planner가 중첩 루프 조인 계획을 사용할 수 있도록 활성화합니다. | 
|  `enable_seqscan`  | 동적 | planner가 순차적 스캔 계획을 사용할 수 있도록 활성화합니다. | 
|  `enable_sort`  | 동적 | planner가 명시적 정렬 단계를 사용할 수 있도록 활성화합니다. | 
|  `enable_tidscan`  | 동적 | planner가 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: 무작위 경로 선택을 위한 시드(seed)를 지정합니다. | 
|  `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 이상 버전에서는 이 파라미터가 기본적으로 '해제' 상태입니다. 이 파라미터를 켜면 연결은 DNS 역방향 조회를 사용하여 연결 로그에 캡처되는 호스트 이름을 가져옵니다. 이 파라미터를 켰다면, 연결을 설정하는 데 걸리는 시간이 달라지는지 모니터링해야 합니다. | 
|  `log_line_prefix `  | 동적 | 각 로그 행에 접두사가 붙은 정보를 제어합니다. | 
|  `log_lock_waits`  | 동적 | 오랜 잠금 대기 시간을 기록합니다. | 
|  `log_min_duration_statement`  | 동적 | 문이 기록되는 최소 실행 시간을 설정합니다. | 
|  `log_min_error_statement`  | 동적 | 이 수준 이상으로 오류 원인이 되는 모든 문을 기록합니다. | 
|  `log_min_messages`  | 동적 | 기록되는 메시지 수준을 설정합니다. | 
|  `log_parser_stats`  | 동적 | 구문 분석기 성능 통계를 서버 로그에 기록합니다. | 
|  `log_planner_stats`  | 동적 | planner 성능 통계를 서버 로그에 기록합니다. | 
|  `log_rotation_age`  | 동적 | N분 후에 자동 로그 파일 로테이션이 일어납니다. | 
|  `log_rotation_size`  | 동적 | N킬로바이트 후에 자동 로그 파일 로테이션이 일어납니다. | 
|  `log_statement`  | 동적 | 기록할 문 유형을 설정합니다. | 
|  `log_statement_stats`  | 동적 | 누적 성능 통계를 서버 로그에 기록합니다. | 
|  `log_temp_files`  | 동적 | 이 킬로바이트 수치보다 큰 임시 파일의 사용을 기록합니다. | 
|  `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`  | 정적 | 하나의 트랜잭션에서 사용할 수 있는 최대 술어(predicate) 잠금 횟수를 설정합니다. | 
|  `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/ko_kr/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Parameters.html) Amazon RDS for PostgreSQL DB 인스턴스에서 다음 명령을 사용하여 현재 값을 확인합니다. <pre>SHOW max_wal_size;</pre>  | 
| min\$1wal\$1size | 동적 | WAL을 축소할 최소 크기를 설정합니다. PostgreSQL 버전 9.6 이하의 경우 min\$1wal\$1size는 16MB 단위입니다. PostgreSQL 버전 10 이상의 경우 min\$1wal\$1size는 1MB 단위입니다. | 
|  `quote_all_identifiers`  | 동적 | SQL 조각 생성 시 모든 식별자에 인용 부호(")를 추가합니다. | 
|  `random_page_cost`  | 동적 | 비순차적으로 가져온 디스크 페이지에 대한 planner의 예상 코스트를 설정합니다. 이 파라미터는 쿼리 계획 관리(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 이상에서만 사용할 수 있습니다. 자세한 내용은 [reserved\$1connections](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-RESERVED-CONNECTIONS) PostgreSQL 설명서를 참조하세요. | 
| `rds.replica_identity_full` | 동적 | 이 파라미터를 `on`으로 설정하면 모든 데이터베이스 테이블에 대해 복제본 ID 설정이 `FULL`로 재정의됩니다. 즉, `REPLICA IDENTITY FULL` 설정에 관계없이 모든 열 값이 Write Ahead Log(WAL)에 기록됩니다.  이 파라미터를 켜면 추가 WAL 로깅으로 인해 데이터베이스 인스턴스 IOPS가 증가할 수 있습니다.   | 
| rds.restrict\$1password\$1commands | 정적 | 암호를 관리할 수 있는 사람을 rds\$1password 역할이 있는 사용자로 제한합니다. 암호 제한을 활성화하려면 이 파라미터를 1로 설정합니다. 기본값은 0입니다. | 
|  `search_path`  | 동적 | 스키마로 한정되지 않은 이름의 스키마 검색 순서를 설정합니다. | 
|  `seq_page_cost`  | 동적 | 순차적으로 가져온 디스크 페이지에 대한 planner의 예상 코스트를 설정합니다. | 
|  `session_replication_role`  | 동적 | 트리거 및 다시 쓰기 규칙에 대한 세션 동작을 설정합니다. | 
|  `shared_buffers`  | 정적 | 서버에서 사용할 공유 메모리 버퍼의 수를 설정합니다. | 
|  `shared_preload_libraries `  | 정적 | RDS for PostgreSQL DB 인스턴스에 미리 로드할 공유 라이브러리를 나열합니다. 지원되는 값으로는 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 keepalive의 최대 재전송 횟수를 지정합니다. | 
|  `tcp_keepalives_idle`  | 동적 | TCP keepalive의 실행 주기를 지정합니다. | 
|  `tcp_keepalives_interval`  | 동적 | TCP keepalive의 재전송 주기를 지정합니다. | 
|  `temp_buffers`  | 동적 | 각 세션에서 사용하는 임시 버퍼의 최대 수를 설정합니다. | 
| temp\$1file\$1limit | 동적 | 임시 파일이 증가할 수 있는 최대 크기(KB)를 설정합니다. | 
|  `temp_tablespaces`  | 동적 | 임시 테이블 및 정렬 파일에 사용할 테이블스페이스를 설정합니다. | 
|  `timezone`  | 동적 | 타임스탬프를 표시 및 해석할 시간대를 설정합니다. IANA(Internet Assigned Numbers Authority)에서는 [https://www.iana.org/time-zones](https://www.iana.org/time-zones)에서 일 년에 여러 번 새로운 표준 시간대를 게시합니다. RDS에서 PostgreSQL의 새로운 마이너 유지 관리 릴리스를 릴리스할 때마다 릴리스 시점의 최신 표준 시간대 데이터가 함께 제공됩니다. 최신 RDS for PostgreSQL 버전을 사용하면 RDS의 최신 표준 시간대 데이터를 갖게 됩니다. DB 인스턴스에 최신 표준 시간대 데이터가 있는지 확인하려면 상위 DB 엔진 버전으로 업그레이드하는 것이 좋습니다. PostgreSQL DB 인스턴스의 표준 시간대 테이블은 수동으로 수정할 수 없습니다. RDS는 실행 중인 DB 인스턴스의 표준 시간대 데이터를 수정하거나 재설정하지 않습니다. 새 표준 시간대 데이터는 데이터베이스 엔진 버전 업그레이드를 수행할 때만 설치됩니다. | 
|  `track_activities`  | 동적 | 명령 실행에 대한 정보를 수집합니다. | 
|  `track_activity_query_size`  | 정적 | pg\$1stat\$1activity.current\$1query에 예약되는 크기(바이트)를 설정합니다. | 
|  `track_counts`  | 동적 | 데이터베이스 작업에 관한 통계를 수집합니다. | 
|  `track_functions`  | 동적 | 데이터베이스 작업에 관한 함수 수준 통계를 수집합니다. | 
|  `track_io_timing`  | 동적 | 데이터베이스 I/O 작업에 관한 시간 통계를 수집합니다. | 
|  `transaction_deferrable`  | 동적 | 잠재적 직렬화 오류 없이 시작될 때까지 직렬화가 가능한 읽기 전용 트랜잭션의 지연 여부를 결정합니다. | 
|  `transaction_isolation`  | 동적 | 현재 트랜잭션 격리 수준을 설정합니다. | 
|  `transaction_read_only`  | 동적 | 현재 트랜잭션의 읽기 전용 상태를 설정합니다. | 
|  `transform_null_equals`  | 동적 | expr=NULL을 expr IS NULL로 처리합니다. | 
|  `update_process_title`  | 동적 | 프로세스 제목을 업데이트하여 활성 SQL 명령을 표시합니다. | 
|  `vacuum_cost_delay`  | 동적 | vacuum 코스트 지연 시간(밀리초)을 지정합니다. | 
|  `vacuum_cost_limit`  | 동적 | 지연 시간 이전에 이용 가능한 vacuum 코스트 값을 지정합니다. | 
|  `vacuum_cost_page_dirty`  | 동적 | vacuum으로 페이지 변경 시 부과되는 vacuum 코스트를 지정합니다. | 
|  `vacuum_cost_page_hit`  | 동적 | 버퍼 캐시에서 발견되는 페이지에 대한 vacuum 코스트를 지정합니다. | 
|  `vacuum_cost_page_miss`  | 동적 | 버퍼 캐시에서 발견되지 않는 페이지에 대한 vacuum 코스트를 지정합니다. | 
|  `vacuum_defer_cleanup_age`  | 동적 | vacuum 및 hot cleanup을 연기해야 하는 트랜잭션 수를 지정합니다(있는 경우). | 
|  `vacuum_freeze_min_age`  | 동적 | vacuum에서 테이블 행을 동결해야 하는 최소 기간을 지정합니다. | 
|  `vacuum_freeze_table_age`  | 동적 | vacuum에서 전체 테이블을 스캔하여 튜플을 동결해야 하는 기간을 지정합니다. | 
|  `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` | 8KB | 
| `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` | 8KB | 
| `shared_buffers` | 8KB | 
| `statement_timeout` | ms | 
| `ssl_renegotiation_limit` | KB | 
| `tcp_keepalives_idle` | s | 
| `tcp_keepalives_interval` | s | 
| `temp_file_limit` | KB | 
| `work_mem` | KB | 
| `temp_buffers` | 8KB | 
| `vacuum_cost_delay` | ms | 
| `wal_buffers` | 8KB | 
| `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:parallel 대기 이벤트](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) 위키북을 참조하세요.

**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>

*대기 이벤트*는 세션이 리소스를 대기 중임을 나타냅니다. 예를 들어 대기 이벤트 `Client:ClientRead`는 RDS for PostgreSQL이 클라이언트로부터 데이터를 수신하기 위해 대기 중일 때 발생합니다. 세션은 일반적으로 대기하는 리소스는 다음과 같습니다.
+ 버퍼에 대한 단일 스레드 액세스(예: 세션이 버퍼 수정을 시도하는 경우)
+ 현재 다른 세션에 의해 잠겨 있는 행
+ 데이터 파일 읽기
+ 로그 파일 쓰기

예를 들어 쿼리를 충족하기 위해 세션에서 전체 테이블 스캔을 수행할 수 있습니다. 데이터가 아직 메모리에 없는 경우 세션은 디스크 I/O가 완료될 때까지 기다립니다. 버퍼를 메모리로 읽으면 다른 세션이 동일한 버퍼에 액세스하기 때문에 세션을 기다려야 할 수 있습니다. 데이터베이스는 미리 정의된 대기 이벤트를 사용하여 대기를 기록합니다. 이러한 이벤트는 카테고리로 그룹화됩니다.

대기 이벤트 자체는 성능 문제를 나타내지 않습니다. 예를 들어 요청된 데이터가 메모리에 없으면 디스크에서 데이터를 읽어야 합니다. 한 세션이 업데이트를 위해 행을 잠그면 다른 세션은 해당 행의 잠금이 해제될 때까지 기다려 업데이트할 수 있습니다. 커밋을 수행하려면 로그 파일에 대한 쓰기가 완료될 때까지 대기해야 합니다. 대기는 데이터베이스의 정상적인 기능에 필수적입니다.

반면 많은 수의 대기 이벤트는 일반적으로 성능 문제를 나타냅니다. 이러한 경우 대기 이벤트 데이터를 사용하여 세션이 시간을 소비하는 위치를 결정할 수 있습니다. 예를 들어 일반적으로 실행하는 데 몇 분 정도 걸리는 보고서가 몇 시간 동안 실행되는 경우 총 대기 시간에 가장 많이 기여하는 대기 이벤트를 식별할 수 있습니다. 최상위 대기 이벤트의 원인을 확인할 수 있는 경우 성능을 향상시키는 변경 작업을 수행할 수 있습니다. 예를 들어 세션이 다른 세션에 의해 잠긴 행에서 대기 중인 경우 잠금 세션을 종료할 수 있습니다.

# 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` 파라미터는 서버가 데이터 캐싱에 전념하는 메모리 양을 결정합니다. 기본값은 DB 인스턴스에 사용 가능한 메모리를 기반으로 `{DBInstanceClassMemory/32768}`바이트로 설정됩니다.

### 미리 쓰기 로그(WAL) 버퍼
<a name="PostgreSQL.Tuning.concepts.WAL"></a>

*미리 쓰기 로그(WAL) 버퍼*는 RDS for PostgreSQL이 나중에 영구 스토리지에 쓰는 트랜잭션 데이터를 보유합니다. WAL 메커니즘을 사용하여 RDS for PostgreSQL이 다음을 수행할 수 있습니다.
+ 장애 발생 후 데이터 복구
+ 디스크에 빈번한 쓰기를 방지하여 디스크 I/O 감소

클라이언트가 데이터를 변경하면 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` 파라미터는 임시 디스크 파일에 쓰기 전에 내부 정렬 작업 및 해시 테이블에서 사용할 메모리 양이며, 메가바이트 단위로 측정됩니다. 기본값은 4MB입니다. 여러 세션을 동시에 실행할 수 있으며 각 세션은 유지 관리 작업을 병렬로 실행할 수 있습니다. 이러한 이유로 사용되는 총 작업 메모리는 `work_mem` 설정의 배수가 될 수 있습니다.

### 유지 관리 작업 메모리 영역
<a name="PostgreSQL.Tuning.concepts.local.maintenance_work_mem"></a>

*유지 관리 작업 메모리 영역*은 유지 관리 작업을 위해 데이터를 캐시합니다. 이러한 작업에는 베큠, 인덱스 생성 및 외래 키 추가가 포함됩니다.

`maintenance_work_mem` 파라미터는 유지 관리 작업에서 사용할 최대 메모리 양을 지정하며, 메가바이트 단위로 측정됩니다. 기본값은 64MB입니다. 데이터베이스 세션은 한 번에 하나의 유지 관리 작업만 실행할 수 있습니다.

### 임시 버퍼 영역
<a name="PostgreSQL.Tuning.concepts.temp"></a>

*임시 버퍼 영역*에서는 각 데이터베이스 세션에 대한 임시 테이블을 캐시합니다.

각 세션은 사용자가 지정한 한도까지 필요에 따라 임시 버퍼를 할당합니다. 세션이 끝나면 서버는 버퍼를 지웁니다.

`temp_buffers` 파라미터는 각 세션에서 사용하는 임시 버퍼의 최대 수를 설정하며, 메가바이트 단위로 측정됩니다. 기본값은 8MB입니다. 세션 내에서 임시 테이블을 처음 사용하기 전에 `temp_buffers` 값을 변경할 수 있습니다.

# RDS for PostgreSQL 프로세스
<a name="PostgreSQL.Tuning.concepts.processes"></a>

RDS for PostgreSQL은 여러 프로세스를 사용합니다.

**Topics**
+ [Postmaster 프로세스](#PostgreSQL.Tuning.concepts.postmaster)
+ [백엔드 프로세스](#PostgreSQL.Tuning.concepts.backend)
+ [백그라운드 프로세스](#PostgreSQL.Tuning.concepts.vacuum)

## Postmaster 프로세스
<a name="PostgreSQL.Tuning.concepts.postmaster"></a>

*Postmaster 프로세스*는 RDS for PostgreSQL을 시작할 때 시작되는 첫 번째 프로세스입니다. 포스트마스터 프로세스는 다음과 같은 주요 책임이 있습니다.
+ 백그라운드 프로세스 포크 및 모니터링
+ 클라이언트 프로세스에서 인증 요청을 수신하고 데이터베이스에서 요청을 처리하도록 허용하기 전에 인증 요청을 인증합니다.

## 백엔드 프로세스
<a name="PostgreSQL.Tuning.concepts.backend"></a>

Postmaster가 클라이언트 요청을 인증하면 postmaster는 postgres 프로세스라고도 하는 새 백엔드 프로세스를 생성합니다. 하나의 클라이언트 프로세스가 정확히 하나의 백엔드 프로세스에 연결됩니다. 클라이언트 프로세스와 백엔드 프로세스는 포스트마스터 프로세스의 개입 없이 직접 통신합니다.

## 백그라운드 프로세스
<a name="PostgreSQL.Tuning.concepts.vacuum"></a>

Postmaster 프로세스는 서로 다른 백엔드 작업을 수행하는 여러 프로세스를 생성합니다. 몇 가지 중요한 사항은 다음과 같습니다.
+ WAL 라이터

  RDS for PostgreSQL 미리 쓰기 로깅(WAL) 버퍼의 데이터를 로그 파일에 씁니다. 미리 쓰기 로깅의 원칙은 데이터베이스가 변경 사항을 설명하는 로그 레코드를 디스크에 기록하기 전까지는 데이터베이스가 데이터 파일에 변경 사항을 쓸 수 없다는 것입니다. WAL 메커니즘은 디스크 I/O를 줄이고, RDS for PostgreSQL 장애 후 로그를 사용하여 데이터베이스를 복구할 수 있도록 합니다.
+ 백그라운드 라이터

  이 프로세스는 메모리 버퍼에서 데이터 파일로 더티(수정된) 페이지를 주기적으로 씁니다. 백엔드 프로세스가 메모리에서 페이지를 수정하면 페이지가 더티(dirty) 상태가 됩니다.
+ Autovacuum 데몬

  데몬은 다음 구성 요소로 이루어져 있습니다.
  + Autovacuum 시작 관리자
  + Autovacuum 작업자 프로세스

  Autovacuum은 삽입되고 업데이트되거나 삭제된 튜플 수가 많은 테이블이 있는지 확인합니다. 데몬에는 다음과 같은 책임이 있습니다.
  + 업데이트되거나 삭제된 행이 차지하는 디스크 공간 복구 또는 재사용
  + 플래너가 사용하는 통계 업데이트
  + 트랜잭션 ID 랩어라운드로 인해 이전 데이터 손실 방지

  Autovacuum 기능은 `VACUUM`과 `ANALYZE` 명령을 자동화합니다. `VACUUM`에는 다음과 같은 표준 및 전체 변형이 있습니다. 스탠다드 베큠은 다른 데이터베이스 연산과 병행하여 실행됩니다. `VACUUM FULL`에는 작업 중인 테이블에 독점적인 잠금이 필요합니다. 따라서 동일한 테이블에 액세스하는 연산과 병렬로 실행할 수 없습니다. `VACUUM`은 상당한 양의 I/O 트래픽을 생성하여 다른 활성 세션의 성능이 저하될 수 있습니다.

# 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)  | 이 이벤트는 예상 비용 한도에 도달하여 진공 프로세스가 휴면 상태임을 나타냅니다. | 

# Client:ClientRead
<a name="wait-event.clientread"></a>

`Client:ClientRead` 이벤트는 RDS for PostgreSQL이 클라이언트에서 데이터를 수신하기 위해 대기 중일 때 발생합니다.

**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 DB 인스턴스가 클라이언트로부터 데이터를 수신하기 위해 대기 중입니다. RDS for PostgreSQL DB 인스턴스는 클라이언트로부터 데이터를 수신해야 클라이언트에 더 많은 데이터를 보낼 수 있습니다. 클라이언트에서 데이터를 수신하기 전에 인스턴스가 대기하는 시간이 `Client:ClientRead` 이벤트입니다.

## 대기 증가의 가능한 원인
<a name="wait-event.clientread.causes"></a>

상위 대기에서 나타나는 `Client:ClientRead` 이벤트의 일반적인 원인은 다음을 포함합니다.

**네트워크 대기 시간 증가**  
RDS for PostgreSQL DB 인스턴스와 클라이언트 간에 네트워크 지연 시간이 늘어날 수 있습니다. 네트워크 지연 시간이 높을수록 DB 인스턴스가 클라이언트에서 데이터를 수신하는 데 필요한 시간이 늘어납니다.

**클라이언트에 대한 로드 증가**  
클라이언트에 CPU 압력 또는 네트워크 포화가 있을 수 있습니다. 클라이언트 로드가 증가하면 클라이언트에서 RDS for PostgreSQL DB 인스턴스로의 데이터 전송이 지연될 수 있습니다.

**과도한 네트워크 왕복**  
RDS for PostgreSQL DB 인스턴스와 클라이언트 간의 네트워크 왕복 횟수가 많으면 클라이언트에서 RDS for PostgreSQL DB 인스턴스로의 데이터 전송을 지연시킬 수 있습니다.

**대량 복사 연산**  
복사 연산 중에 데이터가 클라이언트의 파일 시스템에서 RDS for PostgreSQL DB 인스턴스로 전송됩니다. DB 인스턴스에 대량의 데이터를 전송하면 클라이언트에서 DB 인스턴스로의 데이터 전송이 지연될 수 있습니다.

**유휴 클라이언트 연결**  
클라이언트가 `idle in transaction` 상태의 RDS for PostgreSQL DB 인스턴스에 연결하는 경우 DB 인스턴스는 클라이언트가 더 많은 데이터를 보내거나 명령을 실행할 때까지 기다릴 수 있습니다. 이 상태의 연결은`Client:ClientRead` 이벤트 증가로 이어질 수 있습니다.

**연결 풀링에 사용되는 PGBouncer**  
PGBouncer에는 `pkt_buf`와 같은 낮은 수준의 네트워크 구성 설정이 있으며, 기본적으로 4,096으로 설정됩니다. 워크로드가 PGBouncer를 통해 4,096바이트보다 큰 쿼리 패킷을 보내는 경우, `pkt_buf` 설정을 8,192까지 늘리는 것이 좋습니다. 새 설정으로 인해 `Client:ClientRead` 이벤트의 수가 줄어들지 않는 경우 `pkt_buf` 설정을 16,384 또는 32,768과 같이 더 큰 값으로 설정하는 것이 좋습니다. 쿼리 텍스트가 큰 경우 더 큰 설정이 특히 유용할 수 있습니다.

## 작업
<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>

네트워크 대기 시간을 줄이고 네트워크 처리량(throughput)을 늘리려면 RDS for PostgreSQL DB 인스턴스와 동일한 가용 영역 및 Virtual Private Cloud(VPC) 서브넷에 클라이언트를 배치합니다. 클라이언트가 가능한 한 DB 인스턴스에 지리적으로 가까이 있는지 확인합니다.

### 클라이언트 확장
<a name="wait-event.clientread.actions.scale-client"></a>

Amazon CloudWatch 또는 기타 호스트 지표를 사용하여 클라이언트가 현재 CPU 또는 네트워크 대역폭 또는 둘 다에 의해 제한되어 있는지 확인합니다. 클라이언트가 제한된 경우 그에 따라 클라이언트를 확장합니다.

### 현재 세대 인스턴스 사용
<a name="wait-event.clientread.actions.db-instance-class"></a>

점보 프레임을 지원하는 DB 인스턴스 클래스를 사용하지 않는 경우도 있습니다. Amazon EC2 애플리케이션을 실행하는 경우 클라이언트에 현재 세대 인스턴스를 사용하는 것이 좋습니다. 또한 클라이언트 운영 체제에서 최대 전송 단위(MTU)를 구성합니다. 이 기술은 네트워크 왕복 수를 줄이고 네트워크 처리량을 늘릴 수 있습니다. 자세한 내용은 Amazon EC2 사용 설명서**의 [점보 프레임(9001 MTU)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances)을 참조하세요.

DB 인스턴스 클래스에 대한 자세한 내용은 [DB 인스턴스 클래스](Concepts.DBInstanceClass.md) 섹션을 참조하세요. Amazon EC2 인스턴스 유형과 동일한 DB 인스턴스 클래스를 확인하려면 `db.`가 Amazon EC2 인스턴스 유형 이름 앞에 있어야 합니다. 예를 들어, `r5.8xlarge` Amazon EC2 인스턴스는 `db.r5.8xlarge` DB 인스턴스 클래스입니다.

### 네트워크 대역폭 향상
<a name="wait-event.clientread.actions.increase-network-bandwidth"></a>

DB 인스턴스의 수신 및 발신 네트워크 트래픽을 모니터링하는 `NetworkReceiveThroughput` 및 `NetworkTransmitThroughput` Amazon CloudWatch 지표를 사용합니다. 이러한 지표는 네트워크 대역폭이 워크로드에 충분한지 확인하는 데 도움이 될 수 있습니다.

네트워크 대역폭이 충분하지 않으면 늘리세요. 만약 AWS 클라이언트 또는 DB 인스턴스가 네트워크 대역폭 제한에 도달했다면. 대역폭을 늘리는 유일한 방법은 DB 인스턴스 크기를 늘리는 것입니다. 자세한 내용은 [DB 인스턴스 클래스 유형](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` 연결의 수가 점점 늘어나고 있는지 확인하세요. 이를 수행하려면 `state`열의 `pg_stat_activity`테이블을 모니니터링하세요. 다음과 유사한 쿼리를 실행하여 연결 소스를 식별할 수 있습니다.

```
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>

`Client:ClientWrite` 이벤트는 RDS for PostgreSQL이 클라이언트에 데이터를 쓰기 위해 대기 중일 때 발생합니다.

**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 DB 클러스터로부터 받은 모든 데이터를 읽어야 합니다. 클라이언트에서 데이터를 수신하기 전에 클러스터가 대기하는 시간은 `Client:ClientWrite` 이벤트를 트리거합니다.

RDS for PostgreSQL DB 인스턴스와 클라이언트 간의 네트워크 처리량(throughput)이 감소하면 이 이벤트가 발생할 수 있습니다. 클라이언트에 대한 CPU 압력 및 네트워크 포화 상태시에도 이 이벤트가 발생할 수 있습니다. *CPU 압력*은 CPU가 완전히 활용되고 CPU 시간을 기다리는 작업이 있을 때입니다. *네트워크 포화*는 데이터베이스와 클라이언트 간의 네트워크가 처리할 수 있는 것보다 많은 데이터를 전달하는 경우입니다.

## 대기 증가의 가능한 원인
<a name="wait-event.clientwrite.causes"></a>

상위 대기에서 나타나는 `Client:ClientWrite` 이벤트의 일반적인 원인은 다음을 포함합니다.

**네트워크 대기 시간 증가**  
RDS for PostgreSQL DB 인스턴스와 클라이언트 간에 네트워크 지연 시간이 늘어날 수 있습니다. 네트워크 대기 시간이 높을수록 클라이언트가 데이터를 수신하는 데 필요한 시간이 늘어납니다.

**클라이언트에 대한 로드 증가**  
클라이언트에 CPU 압력 또는 네트워크 포화가 있을 수 있습니다. 클라이언트에 대한 로드가 증가하면 RDS for MySQL DB 인스턴스에서 데이터 수신이 지연됩니다.

**클라이언트에 전송되는 대용량 데이터**  
RDS for PostgreSQL DB 인스턴스가 많은 양의 데이터를 클라이언트에 전송하고 있을 수 있습니다. 클라이언트는 클러스터가 데이터를 전송하는 만큼 빠르게 데이터를 수신하지 못할 수 있습니다. 큰 테이블 복사와 같은 활동 시 `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>

네트워크 대기 시간을 줄이고 네트워크 처리량(throughput)을 늘리려면 RDS for PostgreSQL DB 인스턴스와 동일한 가용 영역 및 Virtual Private Cloud(VPC) 서브넷에 클라이언트를 배치합니다.

### 현재 세대 인스턴스 사용
<a name="wait-event.clientwrite.actions.db-instance-class"></a>

점보 프레임을 지원하는 DB 인스턴스 클래스를 사용하지 않는 경우도 있습니다. Amazon EC2 애플리케이션을 실행하는 경우 클라이언트에 현재 세대 인스턴스를 사용하는 것이 좋습니다. 또한 클라이언트 운영 체제에서 최대 전송 단위(MTU)를 구성합니다. 이 기술은 네트워크 왕복 수를 줄이고 네트워크 처리량을 늘릴 수 있습니다. 자세한 내용은 Amazon EC2 사용 설명서**의 [점보 프레임(9001 MTU)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances)을 참조하세요.

DB 인스턴스 클래스에 대한 자세한 내용은 [DB 인스턴스 클래스](Concepts.DBInstanceClass.md) 섹션을 참조하세요. Amazon EC2 인스턴스 유형과 동일한 DB 인스턴스 클래스를 확인하려면 `db.`가 Amazon EC2 인스턴스 유형 이름 앞에 있어야 합니다. 예를 들어, `r5.8xlarge` Amazon EC2 인스턴스는 `db.r5.8xlarge` DB 인스턴스 클래스입니다.

### 클라이언트에 전송해야 하는 데이터 양 감소
<a name="wait-event.clientwrite.actions.reduce-data"></a>

가능하면 애플리케이션을 조정하여 RDS for PostgreSQL DB 인스턴스가 클라이언트에 보내는 데이터의 양을 줄이세요. 이러한 조정을 수행하면 클라이언트에서 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 시간을 부여합니다. 스케줄링은 운영 체제 커널에 의해 조정됩니다.

**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를 기다리고 있음을 나타냅니다. 쿼리에 다음 정보가 표시될 때 발생한다는 것을 알고 있습니다.
+ `pg_stat_activity.state` 열이 `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는 활성 상태입니다. 일반적인 데이터베이스 워크로드에서는 이 유형의 I/O가 지배적입니다.

다음 조건이 충족되면 프로세스가 CPU에 스케줄링될 때까지 대기할 수 있습니다.
+ CloudWatch `CPUUtilization` 지표가 100%에 가깝습니다.
+ 평균 로드가 vCPU 수보다 크므로 부하가 많음을 나타냅니다. 성능 개선 도우미의 OS 지표 섹션에서 `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가 페이지 테이블 항목을 관리하고 있을 수 있습니다. 이 메모리 관리 기능은 마이크로, 스몰, 미디엄 DB 인스턴스 클래스를 제외한 모든 DB 인스턴스 클래스에 대해 기본적으로 사용 설정되어 있습니다. 자세한 내용은 [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 Proxy](rds-proxy.md) 섹션을 참조하세요.
  + 인스턴스 크기를 업그레이드하여 vCPU 수를 늘립니다.
  + 해당하는 경우 일부 읽기 전용 워크로드를 리더 노드로 리디렉션하세요.

#### 연결이 증가하지 않았습니다.
<a name="wait-event.cpu.actions.connections.decreased"></a>

성능 개선 도우미의 `blks_hit` 지표를 검토합니다. `blks_hit`의 증가와 CPU 사용량 사이의 상관관계를 찾습니다. 가능한 시나리오는 다음과 같습니다.
+ CPU 사용량 및 `blks_hit`이 상관관계가 있습니다.

  이 경우 CPU 사용량에 연결된 최상위 SQL 문을 찾아 계획 변경을 찾습니다. 다음과 같은 기술을 사용할 수 있습니다.
  + 계획을 수동으로 설명하고 예상 실행 계획과 비교합니다.
  + 초당 블록 히트와 초당 로컬 블록 히트가 증가하는지 확인합니다. 성능 개선 도우미의 대시보드의 **상위 SQL** 섹션에서 **환경설정**을 선택합니다.
+ CPU 사용량 및 `blks_hit`이 상관관계가 없습니다.

  이 경우 다음 중 한 가지라도 발생하는지 확인합니다.
  + 애플리케이션이 데이터베이스에 급속하게 연결되고 데이터베이스와의 연결이 끊어지고 있습니다.

    `log_connections`와 `log_disconnections`를 켜 이 동작을 진단하고, 그런 다음 PostgreSQL 로그를 분석합니다. `pgbadger` 로그 분석기 사용을 고려하세요. 자세한 내용은 [https://github.com/darold/pgbadger](https://github.com/darold/pgbadger) 섹션을 참조하세요.
  + OS에 과부하가 걸렸습니다.

    이 경우 성능 개선 도우미는 백엔드 프로세스가 평소보다 오랜 시간 동안 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이 로컬 스토리지에 임시 파일을 만듭니다. 이러한 임시 파일의 디스크 I/O는 성능을 저하시킬 수 있습니다.

다음과 같은 일련의 이벤트를 관찰하면 데이터베이스에서 임시 파일이 생성될 수 있습니다.

1. 갑작스럽고 급격한 가용성 감소

1. 여유 공간을 위한 신속한 복구

'체인톱' 패턴도 볼 수 있습니다. 이 패턴은 데이터베이스에서 지속적으로 작은 파일을 생성한다는 것을 의미할 수 있습니다.

## 대기 증가의 가능한 원인
<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>

Performance Insights에서 직접 임시 파일 사용량을 볼 수 있습니다. 자세한 내용은 [성능 개선 도우미를 사용하여 임시 파일 사용량 확인](PostgreSQL.ManagingTempFiles.Example.md) 섹션을 참조하세요. Performance Insights가 비활성화되면 `IO:BufFileRead` 및 `IO:BufFileWrite` 작업이 증가하는 것을 확인할 수 있습니다.

문제의 원인을 식별하기 위해 지정한 임계값 KB를 초과하는 임시 파일을 생성하는 모든 쿼리를 로깅하도록 `log_temp_files` 파라미터를 설정할 수 있습니다. 기본적으로 `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`에 조인하여 모든 고객과 모든 주문 사이에 데카르트 프로덕트를 생성합니다. 이러한 유형의 우발적인 조인은 큰 임시 파일을 생성합니다. 테이블의 크기에 따라 테카르트 쿼리(Cartesian query)는 스토리지를 채울 수도 있습니다. 다음 조건이 충족되면 애플리케이션에 데카르트 조인(Cartesian join)이 있을 수 있습니다.
+ 스토리지 가용성이 급격히, 크게 줄어들고 복구가 빨라집니다.
+ 인덱스가 생성되지 않습니다.
+ `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` 절을 사용하세요. 예를 들어 상위 5개 행만 원하는 경우 `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 DB 인스턴스에서 확장을 설정하는 방법은 [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`은 각 연결 또는 병렬 워커에 대해 계획 노드당 최대값을 설정합니다. 데이터베이스에 5,000개의 연결이 있고 각 연결이 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%는 공유 버퍼 풀에 예약되어 있습니다. 공유 메모리 영역에 할당된 양을 빼면 16,384MB가 남아 있습니다. 운영 체제와 엔진에도 메모리가 필요하므로 나머지 메모리를 작업 메모리 영역에만 할당하지 마세요.

`work_mem`에 할당할 수 있는 메모리는 인스턴스 클래스에 따라 달라집니다. 더 큰 인스턴스 클래스를 사용하는 경우 더 많은 메모리를 사용할 수 있습니다. 하지만 앞의 예에서는 16GiB를 초과하여 사용할 수 없습니다. 그렇지 않으면 메모리가 부족할 때 인스턴스를 사용할 수 없게 됩니다. 인스턴스를 사용할 수 없는 상태에서 복구하기 위해 RDS for PostgreSQL 자동화 서비스가 자동으로 다시 시작됩니다.

#### 연결 수 관리
<a name="wait-event.iobuffile.actions.tuning-memory.connections"></a>

데이터베이스 인스턴스에 5,000개의 동시 연결이 있다고 가정합니다. 각 연결은 최소 4MiB의 `work_mem`을 사용합니다. 연결의 메모리 소비량이 많으면 성능이 저하될 수 있습니다. 다음과 같은 옵션이 있습니다.
+ vCPU가 더 많은 대규모 인스턴스 클래스로 업그레이드하세요.
+ 연결 프록시 또는 풀러를 사용하여 동시 데이터베이스 연결 수를 줄이세요.

프록시의 경우 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 인덱스**  
*CTAS*는 `CREATE TABLE AS SELECT` 문입니다. 대용량 데이터 세트를 소스로 사용하여 CTAS를 실행하거나 큰 테이블에 인덱스를 만드는 경우 `IO:DataFileRead` 이벤트가 발생할 수 있습니다. 인덱스를 만들 때 데이터베이스는 순차 스캔을 사용하여 전체 객체를 읽어야 할 수 있습니다. CTAS는 페이지가 메모리에 없을 때 `IO:DataFile` 리드를 생성합니다.

**여러 베큠 작업자가 동시에 실행**  
베큠 작업자는 수동 또는 자동으로 트리거될 수 있습니다. 공격적인 베큠 전략을 채택하는 것이 좋습니다. 그러나 테이블에 업데이트되거나 삭제된 행이 많으면 `IO:DataFileRead` 대기가 늘어납니다. 공간을 회수한 후 `IO:DataFileRead`에 소비되는 베큠 시간이 감소합니다.

**대용량 데이터 수집**  
애플리케이션이 대용량 데이터를 수집할 때 `ANALYZE` 연산이 더 자주 발생할 수 있습니다. `ANALYZE` 프로세스는 autovacuum 시작 관리자에 의해 트리거되거나 수동으로 호출될 수 있습니다.  
`ANALYZE` 연산은 테이블의 하위 집합을 읽습니다. 스캔해야 하는 페이지 수는 `default_statistics_target` 값에 30을 곱하여 계산합니다. 자세한 내용은 [PostgreSQL 설명서](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET)를 참조하세요. `default_statistics_target` 파라미터 1에서 10,000 사이의 값을 허용합니다. 여기서 기본값은 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` 대기 이벤트를 찾을 수 있으므로 끄지 않는 것이 좋습니다. 다음 방법을 사용하면 이러한 작업의 효과를 최소화할 수 있습니다.
+ 사용량이 적은 시간대에 수동으로 유지 관리 작업을 실행합니다. 이 기술은 데이터베이스가 자동 연산의 임계값에 도달하지 못하도록 합니다.
+ 매우 큰 테이블의 경우 테이블을 분할하는 것이 좋습니다. 이 기술은 유지보수 작업의 오버헤드를 줄여줍니다. 데이터베이스는 유지 관리가 필요한 파티션에만 액세스합니다.
+ 대량의 데이터를 수집할 때는 자동 분석 기능을 사용하지 않도록 설정하는 것이 좋습니다.

다음 공식이 true이면 테이블에 대해 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 DB 인스턴스에서 기본적으로 사용할 수 있으며, 다음 명령을 사용하여 인스턴스에서 인스턴스화할 수 있습니다.

```
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 프록시 또는 대안을 사용하는 것이 좋습니다. 이 접근 방식을 사용하면 애플리케이션이 로드 밸런서와 여러 연결을 열 수 있습니다. 그런 다음 밸런서는 데이터베이스와의 제한된 수의 연결을 열 수 있습니다. 병렬로 실행되는 연결 수가 적을수록 DB 인스턴스는 커널에서 컨텍스트 전환을 덜 수행합니다. 쿼리는 더 빠르게 진행되므로 대기 이벤트 수가 줄어듭니다. 자세한 내용은 [ Amazon RDS Proxy](rds-proxy.md) 섹션을 참조하세요.
+ 가능하면 항상 RDS for PostgreSQL용 읽기 전용 복제본을 활용하세요. 애플리케이션이 읽기 전용 작업을 실행할 때는 이러한 요청을 읽기 전용 복제본으로 보내세요. 이 방법은 기본 (라이터) 노드의 I/O 부담을 줄입니다.
+ DB 인스턴스를 확장하는 것이 좋습니다. 대용량 인스턴스 클래스는 더 많은 메모리를 제공하므로 RDS for PostgreSQL에 페이지를 저장할 수 있는 더 큰 공유 버퍼 풀이 제공됩니다. 크기가 클수록 DB 인스턴스에 연결을 처리할 수 있는 vCPU가 늘어납니다. 더 많은 vCPU가 `IO:DataFileRead` 대기 이벤트를 생성 중인 연산이 쓰기를 하고 있을 때 특히 유용합니다.

# 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 버퍼를 채운 다음 비동기적으로 디스크에 씁니다. 대기 이벤트 `IO:WALWrite`는 SQL 세션이 트랜잭션의 COMMIT 호출을 해제할 수 있도록 WAL 데이터가 디스크에 쓰기를 완료하기를 기다리고 있을 때 생성됩니다.

## 대기 증가의 가능한 원인
<a name="wait-event.iowalwrite.causes"></a>

이 대기 이벤트가 자주 발생하는 경우 워크로드와 워크로드가 수행하는 업데이트 유형 및 빈도를 검토해야 합니다. 특히 다음 활동 유형을 찾습니다.

**과중한 DML 활동**  
데이터베이스 테이블의 데이터는 즉시 변경되지 않습니다. 한 테이블에 대한 삽입은 다른 클라이언트가 동일한 테이블을 삽입하거나 업데이트할 때까지 기다려야 할 수 있습니다. 데이터 값 변경(INSERT, UPDATE, DELETE, COMMIT, ROLLBACK TRANSACTION)을 위한 데이터 조작 언어(DML) 문으로 인해 경합이 발생하여 미리 쓰기 로그 파일이 버퍼가 플러시되기를 기다리고 있을 수 있습니다. 이 상황은 과중한 DML 활동을 나타내는 다음과 같은 Amazon RDS 성능 개선 도우미 지표에 캡처됩니다.  
+  `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 DB 인스턴스가 체크포인트용 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 DB 인스턴스의 데이터베이스 변경 사항이 WAL 파일이 처리할 크기가 아닌 속도로 작성될 때 경고를 받도록 할 수 있습니다. 예를 들어 이 파라미터를 30으로 설정한다고 가정해 보겠습니다. RDS for PostgreSQL 인스턴스가 30초 빈도보다 더 자주 변경 사항을 작성해야 하는 경우 "체크포인트가 너무 자주 발생합니다"라는 경고가 PostgreSQL 로그로 전송됩니다. 이는 `max_wal_size` 값을 늘려야 함을 나타낼 수 있습니다.

  자세한 내용은 PostgreSQL 설명서에서 [Write Ahead Log](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) 대기 이벤트 유형은 더 빠른 IO를 제공하도록 초당 입출력 작업 처리량(IOPS)을 조정하여 해결할 수 있습니다. CPU를 확장하는 것보다 IO를 확장하는 것이 좋습니다. 늘어난 CPU는 더 많은 작업을 처리할 수 있고 따라서 IO 병목 현상이 더욱 악화될 수 있으므로 CPU를 확장하면 I/O 경합이 더 심해질 수 있기 때문입니다. 일반적으로 크기 조정 작업을 수행하기 전에 워크로드 조정을 고려하는 것이 좋습니다.

### 전용 로그 볼륨(DLV)
<a name="wait-event.iowalwrite.actions.dlv"></a>

Amazon RDS 콘솔, AWS CLI 또는 Amazon RDS API를 사용하여 프로비저닝된 IOPS(PIOPS) 스토리지를 사용하는 DB 인스턴스 전용 로그 볼륨(DLV)을 사용할 수 있습니다. DLV는 데이터베이스 테이블이 들어 있는 볼륨과 분리된 스토리지 볼륨으로 PostgreSQL 데이터베이스 트랜잭션 로그를 옮깁니다. 자세한 내용은 [전용 로그 볼륨(DLV)](CHAP_Storage.md#CHAP_Storage.dlv) 단원을 참조하십시오.

# IPC:parallel 대기 이벤트
<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:ExecuteGather` 및 `IPC:ParallelFinish` 이벤트의 IPC 대기 시간이 늘어날 수 있습니다. 이러한 계획 문제는 오래된 통계 및 테이블/인덱스 팽창으로 인해 발생하는 경우가 많습니다.

**병렬 워커의 빈번한 시작 및 종료**  
병렬 워커를 자주 시작하고 종료하는 수명이 짧은 쿼리는 `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 명령을 사용하여 세션 수준에서 특정 쿼리에 대해 병렬 처리를 비활성화하는 것이 좋습니다. 더 광범위한 영향을 미치려면 DB 파라미터 그룹에서 관련 파라미터를 조정하여 인스턴스 수준에서 병렬 처리를 비활성화할 수 있습니다. 자세한 내용은 [Amazon RDS에서 DB 파라미터 그룹의 파라미터 수정](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 수를 조정하는 것이 좋습니다. 병렬 작업에 적절한 메모리를 사용할 수 있는지 확인합니다.
+ 성능 개선 도우미 지표를 사용하여 시스템이 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 대기 이벤트로 계측됩니다. 리더 프로세스라고 하는 ProcArrayprocArrayGroupMember의 첫 번째 프로세스는 ProcArrayLock을 독점 모드로 획득합니다. 그런 다음 그룹 transactionID 지우기를 기다리는 프로세스 목록을 지웁니다. 이 작업이 완료되면 리더는 ProcArrayLock을 해제한 다음, 이 목록의 모든 프로세스를 깨워 트랜잭션이 완료되었음을 알립니다.

## 대기 증가의 가능한 원인
<a name="apg-rpg-ipcprocarraygroup.causes"></a>

실행 중인 프로세스가 많을수록 리더가 독점 모드에서 procArrayLock을 더 오래 유지합니다. 따라서 쓰기 트랜잭션이 많을수록 그룹 업데이트 시나리오로 인해 `ProcArrayGroupUpdate` 대기 이벤트를 기다리는 프로세스가 잠재적으로 쌓일 수 있습니다. Database Insights의 상위 SQL 보기에서 COMMIT이이 대기 이벤트의 대부분을 포함하는 문임을 알 수 있습니다. 이는 예상되지만 실행 중인 특정 쓰기 SQL에 대한 심층 조사를 통해 취해야 할 적절한 조치를 결정해야 합니다.

## 작업
<a name="apg-rpg-ipcprocarraygroup.actions"></a>

대기 이벤트의 원인에 따라 다른 작업을 권장합니다. Amazon RDS Performance Insights를 사용하거나 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 Database Insights는 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>

`Lock:advisory` 이벤트는 PostgreSQL 애플리케이션이 잠금을 사용하여 여러 세션에서 활동을 조정할 때 발생합니다.

**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)`를 사용하는 세션을 종료하여 세션 수준 잠금의 느린 축적을 수정할 수 있습니다.

권고 잠금을 대기하는 클라이언트는 `pg_stat_activity`에서 `wait_event_type=Lock` 및 `wait_event=advisory`와 표시됩니다. `locktype=advisory` 및 `granted=f`를 탐색하며 동일한 `pid`를 위해 `pg_locks` 시스템 뷰를 쿼리하여 특정 잠금 값을 얻을 수 있습니다.

그런 다음, 예에 표시된 대로 `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` 인수입니다. 
+ 하나의 API 함수의 경우 `bigint` 인수, 상위 32비트는`pg_locks.classid` 인수, 더 낮은 32비트는 `pg_locks.objid` 인수입니다.
+ 두 개가 포함된 API 함수의 경우 `integer` 인수, 첫 번째 인수는 `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` 이벤트가 정상보다 많이 나타나 성능 문제를 나타내는 경우 일반적인 원인은 다음과 같습니다.

**동일한 테이블에 대한 동시 삽입 또는 업데이트 서지 **  
동일한 테이블에 삽입하거나 업데이트하는 쿼리의 동시 세션 수가 증가할 수 있습니다.

**네트워크 대역폭 부족**  
DB 인스턴스의 네트워크 대역폭이 현재 워크로드의 스토리지 통신 요구 사항에 따라 충분하지 않을 수 있습니다. 이로 인해 `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` 지표 및 이 대기 이벤트의 증가가 수반됩니다. 그렇다면 삽입 및 업데이트 작업에 대한 경합이 높은 관계식을 확인합니다. 이를 확인하려면 `n_tup_ins` 및 `n_tup_upd` 필드의 값을 위한 `pg_stat_all_tables` 뷰를 쿼리하세요. `pg_stat_all_tables` 뷰에 대한 자세한 내용은 PostgreSQL 설명서의 [pg\$1stat\$1statements](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) 섹션을 참조하세요.
+ 대기 이벤트가 주로 업데이트 활동으로 인한 경우 관계식의 채우기 요소 값을 줄이는 것이 좋습니다. 이렇게 하면 업데이트 중에 새 블록에 대한 요청을 줄일 수 있습니다. 필팩터는 테이블 페이지를 포장하기 위한 최대 공간을 결정하는 테이블의 저장 파라미터입니다. 이 값은 페이지의 전체 공간의 백분율로 표시됩니다. 필팩터 파라미터에 대한 자세한 내용은 PostgreSQL 설명서의 [테이블 생성](https://www.postgresql.org/docs/13/sql-createtable.html)을 참조하세요.
**중요**  
필팩터를 변경하는 경우 이 값을 변경하면 워크로드에 따라 성능에 부정적인 영향을 줄 수 있으므로 시스템을 테스트하는 것이 좋습니다.

### 네트워크 대역폭 향상
<a name="wait-event.lockextend.actions.increase-network-bandwidth"></a>

쓰기 지연 시간이 증가하는지 확인하려면 CloudWatch의 `WriteLatency` 지표를 확인하세요. 그렇다면, `WriteThroughput` 및 `ReadThroughput` Amazon CloudWatch 지표를 사용하여 DB 인스턴스의 스토리지 관련 트래픽을 모니터링하세요. 이러한 지표는 네트워크 대역폭이 워크로드의 스토리지 활동에 충분한지 확인하는 데 도움이 될 수 있습니다.

네트워크 대역폭이 충분하지 않으면 늘리세요. 만약 클라이언트 또는 DB 인스턴스가 네트워크 대역폭 제한에 도달했다면. 대역폭을 늘리는 유일한 방법은 DB 인스턴스 크기를 늘리는 것입니다.

CloudWatch 지표에 대한 자세한 내용은 [Amazon RDS에 대한 Amazon CloudWatch 지표](rds-metrics.md#rds-cw-metrics-instance) 섹션을 참조하세요. 각 DB 인스턴스 클래스에 대한 네트워크 성능에 관한 자세한 내용은 [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` 문을 위한 기본 잠금 모드입니다.
+ 데이터 조작 언어(DML) 명령문 `UPDATE`,`DELETE`, 및 `INSERT`와 충돌하는 테이블에 `ROW EXCLUSIVE` 잠금을 획득하는 `CREATE INDEX (without CONCURRENT)`를 사용하세요.

테이블 수준 잠금 및 충돌하는 잠금 모드에 대한 자세한 내용은 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` 옵션 사용 - `SELECT`나 `LOCK` 문 같은 일부 SQL 명령은 이 옵션을 지원합니다. `NOWAIT` 지시어는 잠금을 즉시 획득할 수 없는 경우 잠금 요청 쿼리를 취소합니다. 이 기술은 차단 세션이 그 뒤에 차단된 세션이 쌓이지 않게 하는 데 도움이 될 수 있습니다.

  예: 트랜잭션 A가 트랜잭션 B가 보유한 잠금을 기다리고 있다고 가정합니다. 이제 B가 트랜잭션 C에 의해 잠긴 테이블에 대한 잠금을 요청하면 트랜잭션 C가 완료될 때까지 트랜잭션 A가 차단될 수 있습니다. 그러나 트랜잭션 B가 `NOWAIT`를 사용하는 경우 C에서 잠금을 요청하면 빠르게 실패하고 트랜잭션 A가 계속해서 기다릴 필요가 없도록 할 수 있습니다.
+ `SET lock_timeout` 사용 - SQL 문이 관계식 잠금을 획득하기 위해 대기하는 시간을 제한하는 `lock_timeout` 값을 설정하세요. 지정된 제한 시간 내에 잠금을 획득하지 않으면 잠금을 요청하는 트랜잭션이 취소됩니다. 세션 수준에서 이 값을 설정합니다.

### 유지 보수 작업의 영향 최소화
<a name="wait-event.lockrelation.actions.maintenance"></a>

`VACUUM`과 `ANALYZE` 같은 유지 관리 작업이 중요합니다. 이러한 유지 관리 작업과 관련된 `Lock:Relation` 대기 이벤트를 찾을 수 있으므로 끄지 않는 것이 좋습니다. 다음 방법을 사용하면 이러한 작업의 효과를 최소화할 수 있습니다.
+ 사용량이 적은 시간대에 수동으로 유지 관리 작업을 실행합니다.
+ Autovacuum 작업으로 인한 `Lock:Relation` 대기를 줄이려면 필요한 autovacuum 튜닝을 수행하세요. Autovacuum 튜닝에 대한 자세한 내용은 [Amazon RDS 사용 설명서](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)의 *Amazon RDS에서 PostgreSQL Autovacuum 사용*을 참조하세요.

# 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 Proxy](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` 이벤트를 생성하는 시나리오를 가정합니다.


|  Time  |  세션 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` 문을 실행하고 있습니다.
+ 다양한 요인으로 인해 애플리케이션이나 연결 풀이 더 많은 세션을 열어 동일한 작업을 실행할 수 있습니다. 새 세션이 동일한 행을 수정하려고 하면 DB 로드가 급증할 수 있으며, `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)을 참조하세요.
+ autocommit을 최대한 많이 사용합니다. 자세한 내용은 PostgreSQL 설명서의 [AUTOCOMMIT 설정](https://www.postgresql.org/docs/current/ecpg-sql-set-autocommit.html)을 참조하세요.

### 차단 세션 찾기
<a name="wait-event.locktuple.actions.find-blocker"></a>

`Lock:tuple` 대기 이벤트가 발생하는 동안 어떤 잠금이 서로 의존하는지 파악하여 차단 및 차단된 세션을 식별합니다. 자세한 내용은 PostgreSQL 위키의 [잠금 종속성 정보](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>

`Lock:tuple`은 CPU 부족 또는 Amazon EBS 대역폭의 최대 사용량과 같은 병목 현상이 발생시킬 수 있습니다. 병목 현상을 줄이려면 다음 방법을 고려하세요.
+ 인스턴스 클래스 유형을 확장하세요.
+ 리소스 집약적인 쿼리를 최적화하세요.
+ 애플리케이션 로직을 변경하세요.
+ 거의 액세스하지 않는 데이터를 아카이브하세요.

# 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`  
이 성능 개선 도우미 카운터 지표는 공유 버퍼 풀에서 I/O를 읽어야 하는 블록 수를 나타냅니다. `LWLock:buffer_mapping` 대기 이벤트의 리드업에서 `blks_read`의 스파이크가 발생할 수 있습니다.

### 인덱싱 전략 평가
<a name="wait-event.lwl-buffer-mapping.actions.indexes"></a>

인덱싱 전략의 성능 저하가 아닌지 확인하려면 다음을 알아보세요.

인덱스 팽창  
인덱스와 테이블 팽창으로 인해 불필요한 페이지가 공유 버퍼로 읽히지 않는지 확인합니다. 테이블에 사용되지 않는 행이 포함된 경우 데이터를 보관하고 테이블에서 행을 제거하는 것이 좋습니다. 그런 다음 크기가 조정된 테이블의 인덱스를 다시 작성할 수 있습니다.

자주 사용하는 쿼리의 인덱스  
최적의 인덱스가 있는지 확인하려면 성능 개선 도우미에서 DB 엔진 지표를 모니터링하세요. `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>

`LWLock:BufferIO` 이벤트는 RDS for PostgreSQL이 페이지에 동시에 액세스하려고 하는 다른 프로세스들이 입출력 (I/O) 작업을 완료할 때까지 기다리는 경우에 발생합니다. 그 목적은 동일한 페이지를 공유 버퍼로 읽는 것입니다.

**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` 대기 이벤트와 연결된 I/O 잠금이 있습니다.

이 잠금은 모두 동일한 블록에 액세스해야 하는 여러 세션을 처리하는 데 사용됩니다. 이 블록은 `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` 이벤트의 일반적인 원인은 다음을 포함합니다.
+ I/O 작업이 보류 중인 동일한 페이지에 액세스하려고 시도하는 여러 백엔드 또는 연결
+ 공유 버퍼 풀의 크기 간의 비율(`shared_buffers` 파라미터로 정의됨) 및 현재 워크로드에 필요한 버퍼 수
+ 공유 버퍼 풀의 크기가 다른 작업에서 제거되는 페이지 수와 균형이 맞지 않습니다.
+ 엔진이 공유 버퍼 풀에 필요한 것보다 많은 페이지를 읽어야 하는 크거나 부풀린 인덱스
+ DB 엔진이 테이블에서 필요한 것보다 더 많은 페이지를 읽도록 하는 인덱스의 부족
+ 체크포인트가 너무 자주 발생하거나 수정된 페이지를 너무 많이 플러시해야 함
+ 같은 페이지에서 작업을 수행하려고 시도하는 데이터베이스 연결의 갑작스러운 급증

## 작업
<a name="wait-event.lwlockbufferio.actions"></a>

대기 이벤트의 원인에 따라 다른 작업을 권장합니다.
+ `BufferCacheHitRatio` 및 `LWLock:BufferIO` 대기 이벤트의 급격한 감소 간의 상관관계에 대한 Amazon CloudWatch 지표가 관찰됩니다. 이 효과는 공유 버퍼 설정이 작음을 의미할 수 있습니다. DB 인스턴스 클래스를 늘리거나 확장해야 할 수 있습니다. 워크로드를 더 많은 리더 노드로 분할할 수 있습니다.
+ `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`) 이벤트가 정상보다 많이 나타나 성능 문제를 나타내는 경우 일반적인 원인은 다음과 같습니다.

**동일한 데이터에 대한 동시 업데이트 증가**  
동일한 테이블에 삽입하거나 업데이트하는 쿼리의 동시 세션 수가 증가할 수 있습니다. 이 경합은 인덱스가 많은 테이블에서 더 두드러질 수 있습니다.

**워크로드 데이터가 메모리에 없습니다.**  
활성 워크로드에서 처리 중인 데이터가 메모리에 없으면 이러한 대기 이벤트가 증가할 수 있습니다. 이 효과는 잠금을 유지하는 프로세스가 디스크 I/O 작업을 수행하는 동안 더 오래 유지할 수 있기 때문입니다.

**외래 키 제약 조건을 과도하게 사용**  
외래 키 제약 조건은 프로세스가 버퍼 콘텐츠 잠금에 보관하는 시간을 늘릴 수 있습니다. 이 효과는 해당 키가 업데이트되는 동안 읽기 작업에서 참조된 키에 대해 공유 버퍼 콘텐츠 잠금이 필요하기 때문입니다.

## 작업
<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>

활성 워크로드 데이터가 메모리에 있을 확률을 높이려면 테이블을 분할하거나 인스턴스 클래스를 확장하세요. DB 인스턴스 클래스에 대한 자세한 내용은 [DB 인스턴스 클래스](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`입니다. 버전 13 이상의 RDS for PostgreSQL에서 이 대기 이벤트의 이름은 `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)
```

고속 경로 잠금에 대한 자세한 내용은 잠금 관리자 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`인 테이블이 매일로 분할된 5년짜리 데이터를 저장합니다. 각 파티션에는 두 개의 인덱스가 있습니다. 다음과 같은 일련의 이벤트가 발생합니다.

1. 며칠 분량의 데이터를 쿼리하면 데이터베이스가 많은 파티션을 읽어야 합니다.

1. 데이터베이스는 각 파티션에 대한 잠금 항목을 만듭니다. 파티션 인덱스가 최적기 액세스 경로의 일부인 경우 데이터베이스도 해당 인덱스에 대한 잠금 항목을 만듭니다.

1. 동일한 백엔드 프로세스에 대해 요청된 잠금 항목 수가 `FP_LOCK_SLOTS_PER_BACKEND`의 값인 16보다 높은 경우 잠금 관리자는 비고속 경로 잠금 방법을 사용합니다.

최신 애플리케이션에는 수백 개의 세션이 있을 수 있습니다. 동시 세션이 적절한 파티션 정리 없이 부모를 쿼리하는 경우 데이터베이스는 수백 또는 수천 개의 고속 경로 잠금을 생성할 수 있습니다. 일반적으로 이 동시성이 vCPU 수보다 높으면 `LWLock:lock_manager` 대기 이벤트가 표시됩니다.

**참고**  
`LWLock:lock_manager` 대기 이벤트는 데이터베이스 스키마의 파티션 또는 인덱스 수와 관련이 없습니다. 대신 데이터베이스가 제어해야 하는 비고속 경로 잠금 수와 관련이 있습니다.

## 대기 증가의 가능한 원인
<a name="wait-event.lw-lock-manager.causes"></a>

`LWLock:lock_manager` 대기 이벤트가 정상보다 더 발생하여 성능 문제를 나타낼 수 있으며 갑작스런 스파이크의 가장 큰 원인은 다음과 같습니다.
+ 동시 활성 세션은 빠른 경로 잠금을 사용하지 않는 쿼리를 실행하고 있습니다. 이러한 세션도 최대 vCPU를 초과합니다.
+ 많은 수의 동시 활성 세션이 심하게 분할된 테이블에 액세스하고 있습니다. 각 파티션에는 여러 개의 인덱스가 있습니다.
+ 데이터베이스에 연결 폭풍이 발생합니다. 기본적으로 일부 애플리케이션 및 연결 풀 소프트웨어는 데이터베이스 속도가 느릴 때 더 많은 연결을 만듭니다. 이 관행은 문제를 악화시킵니다. 연결 스톰이 발생하지 않도록 연결 풀 소프트웨어를 튜닝합니다.
+ 많은 수의 세션이 파티션을 정리하지 않고 상위 테이블을 쿼리합니다.
+ 데이터 정의 언어 (DDL), 유지 관리 명령은 자주 액세스하거나 수정되는 사용 중인 관계식 또는 튜플을 독점적으로 잠급니다.

## 작업
<a name="wait-event.lw-lock-manager.actions"></a>

`CPU` 대기 이벤트가 발생하는 것이 반드시 성능 문제를 나타내지는 않습니다. 성능이 저하되고 이 대기 이벤트가 DB 로드를 지배하는 경우에만 이 이벤트에 응답합니다.

**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 위키의 [사용되지 않는 인덱스](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를 초과하는 경우 인스턴스 유형이 지원할 수 있는 것보다 많은 OS 프로세스에 CPU가 필요합니다. 이 경우에는 연결 풀을 사용하거나 튜닝하는 것이 좋습니다. 인스턴스 유형별 vCPU 수에 대한 자세한 내용은 [Amazon RDS 인스턴스 유형](https://aws.amazon.com/rds/instance-types/)을 참조하세요.

연결 풀링에 대한 자세한 내용은 다음 리소스를 참조하세요.
+ [ Amazon RDS Proxy](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 DB 엔진 업그레이드](USER_UpgradeDBInstance.PostgreSQL.md) 섹션을 참조하세요.

# LWLock:pg\$1stat\$1statements
<a name="apg-rpg-lwlockpgstat"></a>

LWLock:pg\$1stat\$1statements 대기 이벤트는 `pg_stat_statements` 확장이 SQL 문을 추적하는 해시 테이블에서 배타적 잠금을 수행할 때 발생합니다. 다음 시나리오에서 발생할 수 있습니다.
+ 추적된 문 수가 구성된 `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 문 실행 통계를 추적합니다. 이 확장은 `pg_stat_statements.max` 파라미터에서 정의된 한도까지 SQL 문을 추적합니다. 이 파라미터는 추적할 수 있는 문의 최대 수를 결정하며, 이는 pg\$1stat\$1statements 뷰의 최대 행 수에 해당합니다.

**문 통계 지속성** - 이 확장은 다음을 통해 인스턴스 재시작 시 문 통계를 유지합니다.
+ pg\$1stat\$1statements.stat라는 파일에 데이터 쓰기
+ pg\$1stat\$1statements.save 파라미터를 사용하여 지속성 동작 제어

pg\$1stat\$1statements.save가 다음과 같이 설정된 경우:
+ on(기본값): 통계는 종료 시 저장되고 서버 시작 시 다시 로드됩니다.
+ off: 통계는 종료 시 저장되지 않으며 서버 시작 시 다시 로드되지 않습니다.

**쿼리 텍스트 저장소** - 이 확장은 추적된 쿼리의 텍스트를 `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 Performance Insights를 사용하거나 `pg_stat_activity` 뷰를 쿼리하여 `LWLock:pg_stat_statements` 이벤트를 식별할 수 있습니다.

다음 `pg_stat_statements` 파라미터를 조정하여 추적 동작을 제어하고 LWLock:pg\$1stat\$1 문 대기 이벤트를 줄입니다.

**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` 파라미터는 정적입니다. 이 파라미터에 변경 사항을 적용하려면 DB 인스턴스를 다시 시작해야 합니다.

### 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에는 유틸리티 명령 추적을 위한 몇 가지 향상된 기능이 도입되었습니다.
+ 이제 Savepoint 이름이 상수로 표시됩니다.
+ 이제 두 단계 커밋 명령의 글로벌 트랜잭션 ID(GID)가 상수로 표시됩니다.
+ DEALLOCATE 문의 이름이 상수로 표시됩니다.
+ 이제 CALL 파라미터가 상수로 표시됩니다.

# LWLock:SubtransSLRU (LWLock:SubtransControlLock)
<a name="wait-event.lwlocksubtransslru"></a>

`LWLock:SubtransSLRU` 및 `LWLock:SubtransBuffer` 대기 이벤트는 세션이 하위 트랜잭션 정보를 위해 가장 오래전에 사용된 단순(SLRU) 캐시에 액세스하기 위해 대기 중임을 나타냅니다. 이는 트랜잭션 가시성 및 상위-하위 관계를 결정할 때 발생합니다.
+ `LWLock:SubtransSLRU`: 프로세스가 하위 트랜잭션에 대해 가장 오래전에 사용된 단순(SLRU) 캐시에 액세스하기 위해 대기 중입니다. 버전 13 이전의 RDS for PostgreSQL에서는 이 대기 이벤트를 `SubtransControlLock`이라고 합니다.
+ `LWLock:SubtransBuffer`: 프로세스가 하위 트랜잭션에 대해 가장 오래전에 사용된 단순(SLRU) 버퍼에서 I/O를 기다리고 있습니다. 버전 13 이전의 RDS for PostgreSQL에서는 이 대기 이벤트를 `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입니다.
  + 롤백 수준 설정이 문 수준 롤백으로 설정된 경우의 psqlODBC입니다(예: `PROTOCOL=7.4-2`).
+ **장기 실행 트랜잭션 및 하위 트랜잭션이 있는 높은 동시 워크로드** - 동시 워크로드가 많고 장기 실행 트랜잭션 및 하위 트랜잭션 중에 하위 트랜잭션 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`)를 캐싱하는 데 사용되는 공유 메모리의 양을 지정합니다. 단위 없이 지정하면 값은 일반적으로 각각 8KB인 `BLCKSZ`바이트 블록을 나타냅니다. 예를 들어, 값을 128로 설정하면 하위 트랜잭션 캐시에 1MB(128 \$1 8kB)의 메모리가 할당됩니다.

**참고**  
모든 인스턴스가 일관되게 유지되도록 클러스터 수준에서 이 파라미터를 설정할 수 있습니다. 특정 워크로드 요구 사항 및 인스턴스 클래스에 적합하도록 값을 테스트하고 조정합니다. 파라미터 변경 사항을 적용하려면 인스턴스를 재부팅해야 합니다.

### 장기적인 조치
<a name="wait-event.lwlocksubtransslru.actions.longterm"></a>
+ **애플리케이션 코드 및 구성 검사** - 애플리케이션 코드 및 데이터베이스 드라이버 구성을 검토하여 일반적으로 명시적 및 암시적 `SAVEPOINT` 사용량과 하위 트랜잭션 사용량을 모두 확인합니다. 64개 이상의 하위 트랜잭션을 생성할 가능성이 있는 트랜잭션을 식별합니다.
+ **저장점 사용량 감소** - 트랜잭션에서 저장점 사용을 최소화합니다.
  + EXCEPTION 블록을 사용하여 PL/pgSQL 프로시저 및 함수를 검토합니다. EXCEPTION 블록은 암시적 저장점을 자동으로 생성하여 하위 트랜잭션 오버플로에 기여할 수 있습니다. 각 EXCEPTION 절은 실행 중에 실제로 예외가 발생하는지 여부에 관계없이 하위 트랜잭션을 생성합니다.  
**Example**  

    예제 1: 문제가 있는 예외 블록 사용

    다음 코드 예제는 여러 하위 트랜잭션을 생성하는 문제가 있는 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 트랜잭션 구성 검사
  + 저장점이 필요하지 않은 대체 오류 처리 전략 고려
+ **트랜잭션 설계 최적화** - 트랜잭션을 재구성하여 과도한 중첩을 방지하고 하위 트랜잭션 오버플로 조건의 가능성을 줄입니다.
+ **장기 실행 트랜잭션 감소** - 장기 실행 트랜잭션은 하위 트랜잭션 정보를 더 오래 보유하여 하위 트랜잭션 문제를 악화시킬 수 있습니다. Performance Insights 지표를 모니터링하고 유휴 트랜잭션을 자동으로 종료하도록 `idle_in_transaction_session_timeout` 파라미터를 구성합니다.
+ Performance Insights 지표 모니터링 - `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>

`Timeout:PgSleep` 이벤트는 서버 프로세스가 `pg_sleep` 함수를 가리키고 및 절전 시간 초과가 만료될 때까지 대기할 때 발생합니다.

**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 I/O의 비용 한도가 초과되었고 vacuum 프로세스가 절전 모드로 전환되었음을 나타냅니다. vacuum 작업은 해당 비용 지연 파라미터에 지정된 기간 동안 중지되었다가 작업을 재개합니다. 수동 vacuum 명령의 경우 `vacuum_cost_delay` 파라미터에 지연이 지정됩니다. autovacuum 대몬(deamon)의 경우 `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 대몬(daemon)과 수동 vacuum 명령이 모두 있습니다. RDS for PostgreSQL DB 인스턴스의 경우 autovacuum 프로세스가 기본적으로 켜져 있습니다. 수동 vacuum 명령은 필요에 따라 사용됩니다(예: 죽은 튜플의 테이블을 지우거나 새 통계를 생성하기 위해).

vacuum이 진행 중일 때 PostgreSQL은 시스템이 다양한 I/O 작업을 수행할 때의 예상 비용을 내부 카운터를 사용하여 추적합니다. 카운터가 비용 한도 파라미터에 지정된 값에 도달하면 작업을 수행하는 프로세스는 비용 지연 파라미터에 지정된 짧은 기간 동안 절전 상태로 전환됩니다. 그런 다음 카운터를 재설정하고 작업을 계속합니다.

vacuum 프로세스에는 리소스 소비 조절에 사용할 수 있는 파라미터가 있습니다. autovacuum과 수동 vacuum 명령에는 비용 한도 값을 설정하기 위한 자체 파라미터가 있습니다. 또한 비용 지연, 즉 한도에 도달했을 때 vacuum을 절전 상태로 전환하는 데 걸리는 시간을 지정하는 자체 파라미터도 있습니다. 비용 지연 파라미터는 이렇게 리소스 소비 제한 메커니즘으로 작동합니다. 다음 목록에서 이러한 파라미터에 대한 설명을 찾을 수 있습니다.

**autovacuum 대몬(daemon)의 제한에 영향을 주는 파라미터**
+ `[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 설명서의 [자동 Vacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)을 참조하세요.

**수동 vacuum 프로세스의 제한에 영향을 미치는 파라미터**
+ `vacuum_cost_limit` - vacuum 프로세스가 절전 상태로 전환되는 임계값입니다. 기본적으로 한도는 200입니다. 이 숫자는 다양한 리소스에 필요한 추가 I/O의 누적 예상 비용을 나타냅니다. 이 값을 늘리면 `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 자동 정리 사용](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md)을 참조하세요.

## 대기 증가의 가능한 원인
<a name="wait-event.timeoutvacuumdelay.causes"></a>

`Timeout:VacuumDelay`는 vacuum의 절전 시간을 제어하는 비용 한도 파라미터 설정(`vacuum_cost_limit`, `autovacuum_vacuum_cost_limit`)과 비용 지연 파라미터(`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 DB 인스턴스에서 문제를 일으킬 수 있는 조건을 감지하여 문제가 발생하기 전에 이를 알려줍니다. 사전 예방적 인사이트를 통해 트랜잭션 연결의 장기 유휴 상태를 경고할 수 있습니다. 트랜잭션 연결에서 유휴 상태로 오래 실행되는 문제 해결에 대한 자세한 내용은 [데이터베이스가 트랜잭션 연결 시 오랫동안 유휴 상태로 실행됨](#proactive-insights.idle-txn) 섹션을 참조하세요.

DevOps Guru는 다음과 같은 작업을 수행할 수 있습니다.
+ 데이터베이스 구성을 일반적인 권장 설정과 교차 검사하여 여러 가지 일반적인 데이터베이스 문제를 방지합니다.
+ 확인하지 않은 상태로 두면 나중에 더 큰 문제로 이어질 수 있는 플릿의 심각한 문제를 알려줍니다.
+ 새로 발견된 문제를 알려줍니다.

모든 사전 예방 인사이트에는 문제의 원인에 대한 분석과 수정 조치를 위한 권장 사항이 포함됩니다.

Amazon DevOps Guru for Amazon RDS에 대한 자세한 내용은 [Amazon DevOps Guru for Amazon RDS로 성능 이상 분석](devops-guru-for-rds.md) 섹션을 참조하세요.

## 데이터베이스가 트랜잭션 연결 시 오랫동안 유휴 상태로 실행됨
<a name="proactive-insights.idle-txn"></a>

데이터베이스에 대한 연결이 1,800초 이상 `idle in transaction` 상태로 지속되었습니다.

**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`(autovacuum 포함)이 잘못된 행을 정리하여 인덱스 또는 테이블 팽창 또는 트랜잭션 ID 랩어라운드로 이어지는 것을 방지할 수 있습니다.

### 이 문제의 잠재적 원인
<a name="proactive-insights.idle-txn.causes"></a>

BEGIN 또는 START TRANSACTION을 사용하여 대화형 세션에서 시작된 트랜잭션이 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/ko_kr/AmazonRDS/latest/UserGuide/images/apg-insight-pgadmin-autocommit.png)

#### 애플리케이션 코드에서 트랜잭션 로직 확인
<a name="proactive-insights.idle-txn.actions.app-logic"></a>

애플리케이션 로직에 문제가 있는지 조사합니다. 다음 조치를 고려해 보세요.
+ JDBC 자동 커밋이 애플리케이션에서 참으로 설정되어 있는지 확인합니다. 또한 코드에 명시적 `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` 상태에서 가장 오래 실행되는 트랜잭션의 지속 시간입니다.

# Amazon RDS for PostgreSQL로 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은 DB 인스턴스에 추가할 수 있는 `pg_tle` 확장을 통해 PostgreSQL용 신뢰할 수 있는 언어 확장을 지원합니다. 이 확장을 사용하면 개발자는 설정 및 구성 요구 사항을 간소화하는 안전한 환경에서 자체 PostgreSQL 확장을 만들 수 있습니다. `pg_tle` 확장을 지원하는 RDS for PostgreSQL 버전에 대해 알아보고 자세한 내용을 확인하려면 [PostgreSQL용 신뢰할 수 있는 언어 확장 작업](PostgreSQL_trusted_language_extension.md) 섹션을 참조하세요.

경우에 따라 확장을 설치하는 대신 RDS for PostgreSQL DB 인스턴스의 사용자 지정 DB 파라미터 그룹의 `shared_preload_libraries` 목록에 특정 모듈을 추가할 수 있습니다. 일반적으로 기본 DB 클러스터 파라미터 그룹은 `pg_stat_statements`만 로드하지만 목록에 추가할 수 있는 다른 모듈도 몇 개 있습니다. 예를 들어, [PostgreSQL pg\$1cron 확장을 사용하여 유지 관리 예약](PostgreSQL_pg_cron.md)에 자세히 설명된 대로 `pg_cron` 모듈을 추가하여 스케줄링 기능을 추가할 수 있습니다. 또 다른 예로, `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 for PostgreSQL DB 인스턴스에 설치할 수 있는 확장 프로그램을 `rds.allowed_extensions` 파라미터에 나열하여 정확하게 지정할 수도 있습니다. 자세한 내용은 [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. DB 인스턴스를 생성할 때 사용한 기본 사용자 이름으로 DB 인스턴스에 연결합니다.

   동일한 DB 인스턴스의 다른 데이터베이스에 대해 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 DB 인스턴스에 설치할 수 있는 확장을 `rds.allowed_extensions` 파라미터에 등록하여 지정할 수 있습니다. 자세한 내용은 [Amazon RDS for PostgreSQL로 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)
+ [RDS 위임 확장 지원에서 PostgreSQL에 대해 사용되는 구성](#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`를 통해 DB 클러스터 파라미터에서 `rds.allowed_extensions`를 사용하여 가용 확장의 하위 집합을 지정할 수 있습니다. 다음 수준 중 하나에서 이 작업을 수행할 수 있습니다.
   + 클러스터 또는 인스턴스 파라미터 그룹에서 AWS Management Console 또는 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();
   ```

## RDS 위임 확장 지원에서 PostgreSQL에 대해 사용되는 구성
<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/ko_kr/AmazonRDS/latest/UserGuide/RDS_delegated_ext.html) 이 파라미터 설정에 대한 자세한 내용은 [사용자에게 위임 확장 지원 활성화](#RDSPostgreSQL.delegated_ext_mgmt) 섹션을 참조하세요. | rds\$1superuser | 
| `rds.allowed_extensions` | 이 파라미터를 사용하면 고객이 RDS DB 인스턴스에 설치할 수 있는 확장을 제한할 수 있습니다. 자세한 내용은 [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 DB 인스턴스에 확장을 설치할 수 없습니다. | 관리자 | 
| `rds-delegated_extension_allow_drop_cascade` | 이 파라미터는 `rds_extension` 권한이 있는 사용자가 캐스케이드 옵션을 사용하여 확장을 삭제할 수 있는 기능을 제어합니다. | 끄기 | 기본적으로 `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>

**부분적으로 비활성화**  
위임된 사용자는 새 확장을 만들 수는 없지만 기존 확장을 계속 업데이트할 수는 있습니다.
+ DB 클러스터 파라미터 그룹에서 `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` 역할이 필요하지 않습니다.
+ 동일한 DB 클러스터의 여러 데이터베이스에 대해 서로 다른 확장 세트를 지원하는 기능을 제공합니다.

## 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>

다음과 같은 확장을 생성, 사용 또는 업데이트하려면 위임된 사용자에게 다음과 같은 함수, 테이블 및 스키마에 대해 필요한 권한이 있어야 합니다.


| 소유권이나 권한이 필요한 확장 | 함수 | 테이블 | 스키마 | 텍스트 검색 사전 | 설명 | 
| --- | --- | --- | --- | --- | --- | 
| address\$1standardizer\$1data\$1us | 없음 | us\$1gaz, us\$1lex, us\$1lex, I.us\$1rules | 없음 | 없음 | 없음 | 
| amcheck | bt\$1index\$1check, bt\$1index\$1parent\$1check | 없음 | 없음 | 없음 | 없음 | 
| dict\$1int | 없음 | 없음 | 없음 | intdict | 없음 | 
| pg\$1partman | 없음 | custom\$1time\$1partitions, part\$1config, part\$1config\$1sub | 없음 | 없음 | 없음 | 
| pg\$1stat\$1statements | 없음 | 없음 | 없음 | 없음 | 없음 | 
| PostGIS | st\$1tileenvelope | spatial\$1ref\$1sys | 없음 | 없음 | 없음 | 
| postgis\$1raster | 없음 | 없음 | 없음 | 없음 | 없음 | 
| postgis\$1topology | 없음 | topology, layer | topology | 없음 | 위임된 사용자는 데이터베이스 소유자여야 함 | 
| log\$1fdw | create\$1foreign\$1table\$1for\$1log\$1file | 없음 | 없음 | 없음 | 없음 | 
| rds\$1tools | role\$1password\$1encryption\$1type | 없음 | 없음 | 없음 | 없음 | 
| postgis\$1tiger\$1geocoder | 없음 | geocode\$1settings\$1default, geocode\$1settings | tiger | 없음 | 없음 | 
| pg\$1freespacemap | pg\$1freespace | 없음 | 없음 | 없음 | 없음 | 
| pg\$1visibility | pg\$1visibility | 없음 | 없음 | 없음 | 없음 | 

## 보안 고려 사항
<a name="RDSPostgreSQL.delegated_ext_sec"></a>

 `rds_extension` 역할이 있는 사용자는 접속 권한이 있는 모든 데이터베이스의 확장을 관리할 수 있다는 점을 기억하세요. 위임된 사용자가 단일 데이터베이스의 확장을 관리하도록 하려는 경우, 각 데이터베이스의 모든 공개 권한을 취소한 다음 해당 특정 데이터베이스의 연결 권한을 위임 사용자에게 명시적으로 부여하는 것이 좋습니다.

 사용자가 여러 데이터베이스의 정보에 액세스할 수 있도록 하는 확장에는 여러 가지가 있습니다. 이러한 확장을 `rds.allowed_delegated_extensions`에 추가하기 전에 `rds_extension` 권한을 부여한 사용자가 데이터베이스 간 기능을 사용할 수 있는지 확인하세요. 예를 들어, `postgres_fdw` 및 `dblink`는 동일한 인스턴스 또는 원격 인스턴스의 여러 데이터베이스를 쿼리할 수 있는 기능을 제공합니다. `log_fdw`는 인스턴스의 모든 데이터베이스에 대한 postgres 엔진 로그 파일을 읽습니다. 이 로그 파일에는 여러 데이터베이스의 느린 쿼리나 오류 메시지가 포함될 수 있습니다. `pg_cron`은 예약된 백그라운드 작업을 DB 인스턴스에서 실행할 수 있도록 하고 작업이 다른 데이터베이스에서 실행되도록 구성할 수 있습니다.

## 확장 삭제 캐스케이드 비활성화
<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 Management Console 또는 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 리소스가 적기 때문에 데이터베이스 인스턴스에 영향을 주지 않고 데이터를 유지 관리하는 데 도움이 됩니다.

파티셔닝을 사용하면 데이터를 사용자 지정 크기의 청크로 분할하여 처리할 수 있습니다. 예를 들어, 시간별, 일별, 주별, 월별, 분기별, 연도별, 사용자 지정 또는 이러한 조합과 같은 범위의 시계열 데이터를 분할할 수 있습니다. 시계열 데이터 예제의 경우 테이블을 시간별로 분할한 경우 각 파티션에는 1시간의 데이터가 포함됩니다. 시계열 테이블을 일별로 분할한 경우 파티션에는 하루 분량의 데이터가 저장되는 식입니다. 파티션 키는 파티션의 크기를 제어합니다.

분할된 테이블에서 `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)를 참조하세요.

**참고**  
`pg_partman` 확장은 RDS for PostgreSQL 버전 12.5 이상에서 지원됩니다.

각 파티션을 수동으로 생성하지 않고 다음 설정으로 `pg_partman`을 구성합니다.
+ 분할할 테이블
+ 파티션 유형
+ 파티션 키
+ 분할 영역 세분성
+ 파티션 사전 생성 및 관리 옵션

PostgreSQL 분할 테이블을 만든 후, `create_parent` 함수를 호출하여 `pg_partman`에 등록합니다. 이렇게 하면 함수에 전달하는 파라미터를 기반으로 필요한 파티션이 생성됩니다.

`pg_partman` 확장은 예약된 시간에 호출하여 파티션을 자동으로 관리할 수 있는 `run_maintenance_proc` 함수도 제공합니다. 필요에 따라 적절한 파티션이 생성되도록 하려면 이 기능을 주기적으로 실행하도록 예약합니다(예: 매 시간). 파티션이 자동으로 삭제되게 할 수도 있습니다.

## pg\$1partman 확장 활성화
<a name="PostgreSQL_Partitions.enable"></a>

파티션을 관리하려는 동일한 PostgreSQL DB 인스턴스 내에 여러 개의 데이터베이스가 있는 경우 각 데이터베이스별로 별도로 `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` 적용하는 CHECK 제약 조건.
+ 두 개의 외래 키. 하나는 외부 테이블을`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`을 DB 인스턴스의 파라미터 그룹의 `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. DB 인스턴스와 연결된 파라미터 그룹을 수정하고 `pg_cron` 파라미터 값에 `shared_preload_libraries` 추가합니다. 이 변경 사항을 적용하려면 DB 인스턴스를 다시 시작해야 합니다. 자세한 내용은 [Amazon RDS에서 DB 파라미터 그룹의 파라미터 수정](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',` – 최대 보존 기간이 3개월이 되도록 테이블을 구성합니다.

   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>

금융 기관, 정부 기관 및 많은 업계에서는 규제 요구 사항을 충족하기 위해 감사 로그를** 보관해야 합니다. RDS for PostgreSQL DB 인스턴스와 함께 PostgreSQL Audit 확장(pgAudit)을 사용하면 감사자가 일반적으로 필요로 하거나 규제 요구 사항을 충족하는 데 필요한 세부 레코드를 캡처할 수 있습니다. 예를 들어 특정 데이터베이스 및 테이블의 변경 내용을 추적하고 변경한 사용자 및 기타 여러 세부 정보를 기록하도록 pgAudit 확장을 설정할 수 있습니다.

pgAudit 확장은 네이티브 PostgreSQL 로깅 인프라의 기능을 기반으로 로그 메시지를 더 자세히 확장한 것입니다. 즉, 다른 로그 메시지를 보는 것과 동일한 접근 방식을 사용하여 감사 로그를 볼 수 있습니다. PostgreSQL 로깅에 대한 자세한 내용은 [ RDS for PostgreSQL 데이터베이스 로그 파일](USER_LogAccess.Concepts.PostgreSQL.md) 섹션을 참조하세요.

pgAudit 확장은 일반 텍스트 암호와 같은 민감한 데이터를 로그에서 삭제합니다. RDS for PostgreSQL DB 인스턴스가 [ RDS for PostgreSQL DB 인스턴스에 쿼리 로깅을 활성화합니다.](USER_LogAccess.Concepts.PostgreSQL.Query_Logging.md)에 설명된 대로 데이터 조작 언어(DML) 문을 로깅하도록 구성된 경우 PostgreSQL Audit 확장을 사용하여 일반 텍스트 암호 문제를 방지할 수 있습니다.

매우 구체적으로 데이터베이스 인스턴스에 대한 감사를 구성할 수 있습니다. 모든 데이터베이스와 모든 사용자를 감사할 수 있습니다. 또는 특정 데이터베이스, 사용자 및 기타 객체만 감사하도록 선택할 수 있습니다. 특정 사용자 및 데이터베이스를 감사에서 명시적으로 제외할 수도 있습니다. 자세한 내용은 [감사 로깅에서 사용자 또는 데이터베이스 제외](Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db.md) 단원을 참조하십시오.

캡처할 수 있는 세부 정보의 양을 고려하여 pgAudit를 사용하는 경우 스토리지 사용량을 모니터링하는 것이 좋습니다.

pgAudit 확장은 사용 가능한 모든 RDS for PostgreSQL 버전 RDS for PostgreSQL 버전에서 지원되는 pgAudit 버전 목록을 보려면 **Aurora PostgreSQL 릴리스 정보의 [Extension versions for Amazon RDS for PostgreSQL](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)(Amazon RDS for PostgreSQL 확장 버전)을 참조하세요.

**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 DB 인스턴스에 pgAudit 확장을 설정하려면 먼저 RDS for PostgreSQL DB 인스턴스용 사용자 지정 DB 파라미터 그룹의 공유 라이브러리에 pgAudit을 추가해야 합니다. 사용자 지정 DB 클러스터 파라미터 그룹을 만드는 방법에 관한 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 섹션을 참조하세요. 다음으로 pgAudit 확장을 설치합니다. 마지막으로, 감사하려는 데이터베이스 및 객체를 지정합니다. 이 섹션에 절차가 설명되어 있습니다. AWS Management Console 또는 AWS CLI를 사용할 수 있습니다.

이 모든 작업을 수행하려면 `rds_superuser` 역할의 권한이 있어야 합니다.

다음 단계에서는 사용자의 RDS for PostgreSQL DB 인스턴스가 사용자 지정 DB에 연결되어 있다고 가정합니다.

## 콘솔
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.CON"></a>

**pgAudit 확장 설정 방법**

1. [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 AWS Management Console에 로그인한 후 Amazon RDS 콘솔을 엽니다.

1. 탐색 창에서 RDS for PostgreSQL DB 인스턴스를 선택합니다.

1. 의 **구성** 탭을 엽니다. RDS for PostgreSQL DB 인스턴스 인스턴스 세부 정보 중에서 **파라미터 그룹** 링크를 찾습니다.

1. 링크를 선택하여 와 연결된 사용자 지정 파라미터를 엽니다. RDS for PostgreSQL DB 인스턴스 

1. **파라미터** 검색 필드에 `shared_pre`를 입력하여 `shared_preload_libraries` 파라미터를 찾습니다.

1. **파라미터 편집**을 선택하여 속성 값에 액세스합니다.

1. **값** 필드의 목록에 `pgaudit`를 추가합니다. 쉼표를 사용하여 값 목록에서 항목을 구분합니다.  
![\[pgAudit가 추가된 shared_preload_libaries 파라미터 이미지.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pgaudit.png)

1. RDS for PostgreSQL DB 인스턴스를 재부팅하여 `shared_preload_libraries` 파라미터 변경 사항이 적용되도록 합니다.

1. 인스턴스를 사용할 수 있게 되면 pgAudit가 초기화되었는지 확인합니다. `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결하고 다음 명령을 실행합니다.

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

1. pgAudit가 초기화되었으므로 이제 확장을 생성할 수 있습니다. 확장은 라이브러리를 초기화한 후에 생성해야 합니다. `pgaudit` 확장이 데이터 정의 언어(DDL) 문 감사를 위한 이벤트 트리거를 설치하기 때문입니다.

   ```
   CREATE EXTENSION pgaudit;
   ```

1. `psql` 세션을 닫습니다.

   ```
   labdb=> \q
   ```

1. [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 AWS Management Console에 로그인한 후 Amazon RDS 콘솔을 엽니다.

1. 목록에서 `pgaudit.log` 파라미터를 찾아 사용 사례에 적합한 값으로 설정합니다. 예를 들어, 다음 이미지처럼 `pgaudit.log` 파라미터를 `write`로 설정하면 로그에 대한 삽입, 업데이트, 삭제 및 기타 유형의 변경 사항이 캡처됩니다.  
![\[pgaudit.log 파라미터의 설정 이미지.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/rpg_set_pgaudit-log-level.png)

   `pgaudit.log` 파라미터에 다음 값 중 하나를 선택할 수도 있습니다.
   + 없음 - 기본값입니다. 데이터베이스 변경 사항이 로깅되지 않습니다.
   + 모두 - 모든 항목(읽기, 쓰기, 함수, 역할, ddl, 기타)을 로깅합니다.
   + ddl - `ROLE` 클래스에 포함되지 않은 모든 데이터 정의 언어(DDL) 문을 로깅합니다.
   + 함수 - 함수 호출 및 `DO` 블록을 로깅합니다.
   + 기타 – 기타 명령(예: `DISCARD`, `FETCH`, `CHECKPOINT`, `VACUUM`, `SET`)을 로깅합니다.
   + 읽기 – 원본이 관계(예: 테이블) 또는 쿼리인 경우 `SELECT` 및 `COPY`를 로깅합니다.
   + 역할 - 역할 및 권한과 관련된 문을 로깅합니다(예: `GRANT`, `REVOKE`, `CREATE ROLE`, `ALTER ROLE`, `DROP ROLE`).
   + 쓰기 - 대상이 관계(테이블)인 경우 `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, `COPY`를 로깅합니다.

1. **Save changes**(변경 사항 저장)를 선택합니다.

1. [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 데이터베이스 목록에서 RDS for PostgreSQL DB 인스턴스를 선택합니다.

## 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 DB 인스턴스를 재부팅하여 pgaudit 라이브러리가 초기화되도록 합니다.

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 인스턴스를 사용할 수 있게 되면 `pgaudit`가 초기화되었는지 확인할 수 있습니다. `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결하고 다음 명령을 실행합니다.

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

   pgAudit가 초기화되었으므로 이제 확장을 생성할 수 있습니다.

   ```
   CREATE EXTENSION pgaudit;
   ```

1. AWS CLI를 사용할 수 있도록 `psql` 세션을 닫습니다.

   ```
   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` 파라미터에 다음 값 중 하나를 선택할 수도 있습니다.
   + 없음 - 기본값입니다. 데이터베이스 변경 사항이 로깅되지 않습니다.
   + 모두 - 모든 항목(읽기, 쓰기, 함수, 역할, ddl, 기타)을 로깅합니다.
   + ddl - `ROLE` 클래스에 포함되지 않은 모든 데이터 정의 언어(DDL) 문을 로깅합니다.
   + 함수 - 함수 호출 및 `DO` 블록을 로깅합니다.
   + 기타 – 기타 명령(예: `DISCARD`, `FETCH`, `CHECKPOINT`, `VACUUM`, `SET`)을 로깅합니다.
   + 읽기 – 원본이 관계(예: 테이블) 또는 쿼리인 경우 `SELECT` 및 `COPY`를 로깅합니다.
   + 역할 - 역할 및 권한과 관련된 문을 로깅합니다(예: `GRANT`, `REVOKE`, `CREATE ROLE`, `ALTER ROLE`, `DROP ROLE`).
   + 쓰기 - 대상이 관계(테이블)인 경우 `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, `COPY`를 로깅합니다.

   다음 AWS CLI 명령으로 RDS for PostgreSQL DB 인스턴스를 재부팅합니다.

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

# 데이터베이스 객체 감사
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.auditing"></a>

RDS for PostgreSQL DB 인스턴스에 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/ko_kr/AmazonRDS/latest/UserGuide/images/pgaudit-log-example.png)


이 예에서 볼 수 있듯이 LOG: AUDIT: SESSION 행은 테이블 및 해당 스키마를 비롯한 세부 정보를 제공합니다.

**객체 감사를 설정하는 방법**

1. `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

   ```
   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 명령을 사용하여 `rds_pgaudit`에 `pgaudit.role` 파라미터를 추가합니다. 기본적으로 이 파라미터는 설정되어 있지 않으며 유일하게 허용되는 값은 `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 DB 인스턴스를 재부팅하여 파라미터 변경 사항이 적용되도록 합니다.

   ```
   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 DB 인스턴스

스토리지에 미치는 영향을 최소화하고 불필요하게 감사 레코드를 캡처하지 않도록 사용자 및 데이터베이스를 감사에서 제외할 수 있습니다. 지정된 세션 내에서 로깅을 변경할 수도 있습니다. 다음 예에서는 그 방법을 보여줍니다.

**참고**  
세션 수준의 파라미터 설정은 RDS for PostgreSQL DB 인스턴스에 대한 사용자 지정 DB 파라미터 그룹의 설정보다 우선합니다. 데이터베이스 사용자가 감사 로깅 구성 설정을 우회하지 못하게 하려면 사용자의 권한을 변경해야 합니다.

 RDS for PostgreSQL DB 인스턴스가 모든 사용자 및 데이터베이스에 대해 동일한 수준의 활동을 감사하도록 구성되어 있다고 가정하겠습니다. 그런데 사용자 `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, 함수, 기타, 읽기, 역할, 쓰기, 없음, 모두 등이 포함됩니다. 자세한 내용은 [`pgaudit.log` 파라미터에 허용되는 설정 목록](#Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings) 섹션을 참조하세요. | 
| `pgaudit.log_catalog` | 활성화(1로 설정)하면 문의 모든 관계가 pg\$1catalog에 있는 경우 감사 추적에 문을 추가합니다. | 
| `pgaudit.log_level` | 로그 항목에 사용할 로그 수준을 지정합니다. 허용되는 값은 ebug5, debug4, debug3, debug2, debug1, 정보, 알림, 경고, 로그입니다. | 
| `pgaudit.log_parameter` | 활성화(1로 설정)하면 문과 함께 전달된 파라미터가 감사 로그에 캡처됩니다. | 
| `pgaudit.log_relation` | 활성화(1로 설정)하면 세션의 감사 로그에서 SELECT 또는 DML 문에서 참조되는 각 관계(TABLE, VIEW 등) 에 대해 별도의 로그 항목을 생성합니다. | 
| `pgaudit.log_statement_once` | 로깅에 문/하위 문 조합에 대한 첫 번째 로그 항목이 있는 문 텍스트 및 파라미터를 포함할지 아니면 모든 항목이 있는 문 텍스트 및 파라미터를 포함할지를 지정합니다. | 
| `pgaudit.role` | 객체 감사 로깅에 사용할 마스터 역할을 지정합니다. 유일하게 허용되는 항목은 `rds_pgaudit`입니다. | 

## `pgaudit.log` 파라미터에 허용되는 설정 목록
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings"></a>

 


| 값 | 설명 | 
| --- | --- | 
| 없음 | 이 값이 기본값입니다. 데이터베이스 변경 사항이 로깅되지 않습니다. | 
| 모두 | 모든 항목(읽기, 쓰기, 함수, 역할, ddl, 기타)을 로깅합니다. | 
| ddl | `ROLE` 클래스에 포함되지 않은 모든 데이터 정의 언어(DDL) 문을 로깅합니다. | 
| 함수 | 함수 호출 및 `DO` 블록을 로깅합니다. | 
| 기타 | 기타 명령을 로깅합니다(예: `DISCARD`, `FETCH`, `CHECKPOINT`, `VACUUM`, `SET`). | 
| 읽기 | 원본이 관계(예: 테이블) 또는 쿼리인 경우 `SELECT` 및 `COPY`를 로깅합니다. | 
| 역할 | 역할 및 권한과 관련된 문을 로깅합니다(예: `GRANT`, `REVOKE`, `CREATE ROLE`, `ALTER ROLE`, `DROP ROLE`). | 
| write | 대상이 관계(테이블)인 경우 `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, `COPY`를 로깅합니다. | 

세션 감사를 사용하여 여러 이벤트 유형을 기록하려면 쉼표로 구분된 목록을 사용합니다. 모든 이벤트 유형을 기록하려면 `pgaudit.log`를 `ALL`로 설정합니다. DB 인스턴스를 재부팅하여 변경 사항을 적용합니다.

객체 감사를 사용하면 특정 관계를 사용하도록 감사 로깅을 구체화할 수 있습니다. 예를 들어 하나 이상의 테이블에서 `READ` 작업에 대한 감사 로깅을 지정할 수 있습니다.

# PostgreSQL pg\$1cron 확장을 사용하여 유지 관리 예약
<a name="PostgreSQL_pg_cron"></a>

PostgreSQL `pg_cron` 확장을 사용하여 PostgreSQL 데이터베이스 내에서 유지 관리 명령을 예약할 수 있습니다. 확장에 대한 자세한 내용은 pg\$1cron 설명서의 [pg\$1cron이란 무엇입니까?](https://github.com/citusdata/pg_cron) 섹션을 참조하십시오.

`pg_cron` 확장은 RDS for PostgreSQL 엔진 버전 12.5 이상에서 지원됩니다.

`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_cron` 확장 버전은 pg\$1available\$1extensions 보기에 1.6과 같은 2자리 버전으로 표시됩니다. 일부 컨텍스트에 나열된 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 DB 인스턴스와 연결된 사용자 지정 파라미터 그룹을 수정합니다.
   + RDS for PostgreSQL DB 인스턴스가 `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 DB 인스턴스를 다시 시작합니다. 파라미터 그룹 사용에 대한 자세한 내용은 [Amazon RDS에서 DB 파라미터 그룹의 파라미터 수정](USER_WorkingWithParamGroups.Modifying.md). 섹션을 참조하십시오.

1. PostgreSQL DB 인스턴스가 다시 시작된 후 `rds_superuser` 권한이 있는 계정을 사용하여 다음 명령을 수행합니다. 예를 들어 RDS for PostgreSQL DB 인스턴스를 생성할 때 기본 설정을 사용한 경우 사용자 `postgres`로 연결하고 확장을 생성합니다.

   ```
   CREATE EXTENSION pg_cron;
   ```

   `pg_cron` 스케줄러는 `postgres`라는 기본 PostgreSQL 데이터베이스에 설정됩니다. `pg_cron` 객체가 이 `postgres` 데이터베이스에 생성되고 모든 예약 작업이 이 데이터베이스에서 실행됩니다.

1. 기본 설정을 사용하거나 PostgreSQL DB 인스턴스 내의 다른 데이터베이스에서 실행되도록 작업을 예약할 수 있습니다. PostgreSQL DB 인스턴스 내의 다른 데이터베이스에 대한 작업을 예약하려면 [기본 데이터베이스 이외의 데이터베이스에 대한 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;
```

이렇게 하면 액세스 권한이 있는 개체에 대해 cron 작업을 예약하기 위해 `cron` 스키마에 액세스할 수 있는 권한이 *db-user*에게 부여됩니다. 데이터베이스 사용자에게 권한이 없으면 다음과 같이 `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 자동 정리 사용](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md) 섹션도 참조하세요.

다음은 매일 22:00(GMT)에 특정 테이블에 `cron.schedule`를 사용하는 작업을 설정하는 `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 작업 기록이 포함되어 있습니다. 이 테이블을 지우는 작업을 예약하는 것이 좋습니다. 예를 들어, 1 주일 분량의 항목을 보관하면 문제 해결을 위해 충분할 수 있습니다.

다음 예에서는 [cron.schedule](#PostgreSQL_pg_cron.schedule) 함수를 사용하여, 매일 자정에 실행되어 `cron.job_run_details` 테이블을 지우는 작업을 예약합니다. 이 작업은 지난 7 일 동안의 항목만 유지합니다. `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 DB 인스턴스와 연결된 파라미터 그룹을 수정하고 `cron.log_run` 파라미터를 '꺼짐'으로 설정합니다. `pg_cron` 확장이 더 이상 테이블에 기록하지 않고 `postgresql.log` 파일에만 오류를 캡처합니다. 자세한 내용은 [Amazon RDS에서 DB 파라미터 그룹의 파라미터 수정](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 DB 인스턴스 내의 모든 데이터베이스에서 작업을 예약할 수 있습니다.

**참고**  
`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 DB 인스턴스 내의 다른 데이터베이스에서 실행되도록 합니다.

   ```
   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 DB 인스턴스 내의 다른 데이터베이스에서 작업이 실행되도록 예약하려면 [기본 데이터베이스 이외의 데이터베이스에 대한 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/ko_kr/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/ko_kr/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` 확장을 지원합니다. pglogical 확장은 PostgreSQL 버전 10에서 도입된 기능적으로 유사한 논리적 복제 기능보다 먼저 출시되었습니다. 자세한 내용은 [Amazon RDS for PostgreSQL에 대한 논리적 복제 수행](PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication.md) 단원을 참조하세요.

`pglogical` 확장은 둘 이상의 간의 논리적 복제를 지원합니다. RDS for PostgreSQL DB 인스턴스. 서로 다른 PostgreSQL 버전 간의 복제와 PostgreSQL DB 인스턴스용 RDS 및 Aurora PostgreSQL DB 클러스터에서 실행되는 데이터베이스 간의 복제도 지원합니다. `pglogical` 확장은 게시-구독 모델을 사용하여 게시자의 테이블 및 기타 객체(예: 시퀀스)의 변경 사항을 구독자에 복제합니다. 이 확장은 복제 슬롯을 사용하여, 다음과 같이 게시자 노드의 변경 사항이 구독자 노드로 동기화되게 합니다.
+ *게시자 노드*는 다른 노드에 복제할 데이터의 소스인 RDS for PostgreSQL DB 인스턴스입니다. 게시자 노드는 게시 세트에서 복제될 테이블을 정의합니다.
+ *구독자 노드*는 게시자로부터 WAL 업데이트를 받는 RDS for PostgreSQL DB 인스턴스입니다. 구독자는 구독을 생성하여 게시자에 연결하고 디코딩된 WAL 데이터를 얻습니다. 구독자가 구독을 생성하면 게시자 노드에서 복제 슬롯이 생성됩니다.

아래에서 `pglogical` 확장 설정 관련 정보를 확인할 수 있습니다.

**Topics**
+ [plogical 확장에 대한 요구 사항 및 제한](#Appendix.PostgreSQL.CommonDBATasks.pglogical.requirements-limitations)
+ [pglogical 확장 설정](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)
+ [RDS for PostgreSQL DB 인스턴스용 논리적 복제 설정](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)
+ [plogical 확장용 파라미터 참조](Appendix.PostgreSQL.CommonDBATasks.pglogical.reference.md)

## plogical 확장에 대한 요구 사항 및 제한
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.requirements-limitations"></a>

현재 사용 가능한 모든 RDS for PostgreSQL 릴리스는 `pglogical` 확장을 지원합니다.

게시자 노드와 구독자 노드 모두가 논리적 복제를 할 수 있도록 설정되어야 합니다.

게시자에서 구독자로 복제할 테이블은 이름과 스키마가 동일해야 합니다. 또한 이러한 테이블은 동일한 열을 포함해야 하며, 각 열은 동일한 데이터 유형을 사용해야 합니다. 게시자와 구독자 테이블 모두 프라이머리 키가 동일해야 합니다. PRIMARY KEY만 고유 제약 조건으로 사용하는 것이 좋습니다.

구독자 노드의 테이블에는 CHECK 제약 조건 및 NOT NULL 제약 조건에 대해 게시자 노드의 테이블에 있는 것보다 더 많은 허용 제약 조건이 존재할 수 있습니다.

`pglogical` 확장은 PostgreSQL(버전 10 이상)에 내장된 논리적 복제 기능에서는 지원하지 않는 양방향 복제 같은 기능을 제공합니다. 자세한 내용은 [pglogical을 사용한 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 DB 인스턴스 에 `pglogical` 확장을 설정하려면 PostgreSQL DB 인스턴스용 사용자 지정 DB 파라미터 그룹 의 공유 라이브러리에 `pglogical`을 추가해야 합니다. 논리적 디코딩을 켜려면 `rds.logical_replication` 파라미터의 값을 `1`로 설정해야 합니다. 마지막으로, 데이터베이스에서 확장을 만듭니다. 이러한 작업에는 AWS Management Console 또는 AWS CLI를 사용할 수 있습니다.

이러한 작업을 수행하려면 `rds_superuser` 역할의 권한이 있어야 합니다.

다음 단계에서는 사용자의 RDS for PostgreSQL DB 인스턴스가 사용자 지정 DB 파라미터 그룹에 연결되어 있다고 가정합니다. 사용자 지정 DB 클러스터 파라미터 그룹을 만드는 방법에 관한 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 섹션을 참조하세요.

## 콘솔
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.CON"></a>

**pglogical 확장 설정 방법**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 탐색 창에서 RDS for PostgreSQL DB 인스턴스를 선택합니다.

1. 의 **구성** 탭을 엽니다. RDS for PostgreSQL DB 인스턴스  인스턴스 세부 정보 중에서 **파라미터 그룹** 링크를 찾습니다.

1. 링크를 선택하여 와 연결된 사용자 지정 파라미터를 엽니다. RDS for PostgreSQL DB 인스턴스  

1. **파라미터** 검색 필드에 `shared_pre`를 입력하여 `shared_preload_libraries` 파라미터를 찾습니다.

1. **파라미터 편집**을 선택하여 속성 값에 액세스합니다.

1. **값** 필드의 목록에 `pglogical`를 추가합니다. 쉼표를 사용하여 값 목록에서 항목을 구분합니다.  
![\[pglogical이 추가된 shared_preload_libraries 파라미터 이미지.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pglogical.png)

1. `rds.logical_replication` 파라미터를 찾아 `1`로 설정하여 논리적 복제를 켭니다.

1. RDS for PostgreSQL DB 인스턴스를 재부팅하여 파라미터 변경 사항이 적용되게 합니다.

1. 인스턴스를 사용할 수 있다면 `psql`(또는 pgAdmin)을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결할 수 있습니다.

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

1. plogical이 초기화되었는지 확인하려면 다음 명령을 실행합니다.

   ```
   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. [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 데이터베이스 목록에서 RDS for PostgreSQL DB 인스턴스를 선택한 다음, 작업 메뉴에서 **재부팅**을 선택합니다.

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.CLI"></a>

**plogical 확장 설정 방법**

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 DB 인스턴스 

   ```
   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 DB 인스턴스를 재부팅하여 pglogical 라이브러리가 초기화되도록 합니다.

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 인스턴스를 사용할 수 있다면 `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

   ```
   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 DB 인스턴스를 재부팅합니다.

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

# RDS for PostgreSQL DB 인스턴스용 논리적 복제 설정
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.setup-replication"></a>

다음 절차는 RDS for PostgreSQL DB 인스턴스 간에 논리적 복제를 시작하는 방법을 보여줍니다. 다음 단계에서는 원본(게시자)과 대상(구독자) 모두에 [pglogical 확장 설정](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)에서 설명하는 방법에 따라 `pglogical` 확장이 설정되어 있다고 가정합니다.

**참고**  
구독자 노드의 `node_name`은 `rds`로 시작할 수 없습니다.

**게시자 노드를 생성하고 복제할 테이블을 정의하는 방법**

이 단계에서는 RDS for PostgreSQL DB 인스턴스에 데이터베이스 하나가 있고 이러한 데이터베이스에는 다른 노드에 복제할 하나 이상의 테이블이 있다고 가정합니다. 구독자의 테이블 구조를 게시자에서 다시 만들어야 하므로, 필요한 경우 먼저 테이블 구조를 가져와야 합니다. 이렇게 하려면 `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 DB 인스턴스를 게시자 노드로 식별합니다.

   ```
   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)
   ```

게시자 노드 설정이 완료되었습니다. 이제 게시자로부터 업데이트를 수신하도록 구독자 노드를 설정할 수 있습니다.

**구독자 노드를 설정하고, 업데이트를 수신할 구독을 만드는 방법**

이 단계에서는 RDS for PostgreSQL DB 인스턴스가 `pglogical` 확장을 이용해 설정되었다고 가정합니다. 자세한 내용은 [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 DB 인스턴스에서 게시자에 존재하는 것과 동일한 테이블을 만듭니다. 이 예제에서 테이블은 `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 DB 인스턴스를 구독자 노드로 식별합니다.

   ```
   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 DB 인스턴스의 메이저 버전 업그레이드를 수행하려면, 먼저 활성화되지 않는 슬롯을 포함한 모든 복제 슬롯을 삭제해야 합니다. 게시자 노드에서 데이터베이스 트랜잭션을 일시적으로 전환하고, 복제 슬롯을 삭제하고, RDS for PostgreSQL DB인스턴스를 업그레이드한 다음 복제를 다시 설정하고 재시작하는 것이 좋습니다.

복제 슬롯은 게시자 노드에서만 호스팅됩니다. 논리적 복제 시나리오에서 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 DB 인스턴스의 메이저 버전 업그레이드를 수행하려면, 먼저 인스턴스에서 복제 슬롯을 삭제해야 합니다. 메이저 버전 업그레이드 사전 점검 프로세스에서는 업그레이드를 진행하려면 슬롯을 삭제해야 한다는 메시지가 표시됩니다.

RDS for PostgreSQL DB 인스턴스에서 슬롯을 삭제하려면 먼저 구독을 삭제한 다음 슬롯을 삭제합니다.

`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)
```

# plogical 확장용 파라미터 참조
<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 | 하위 수준 API 대신 SPI(서버 프로그래밍 인터페이스)를 사용하여 변경 사항을 적용합니다. 켜려면 '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 DB 인스턴스용 액티브-액티브 복제 설정](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 DB 인스턴스에서 `pgactive` 확장 기능을 초기화하려면 `rds.enable_pgactive` 파라미터 값을 `1`로 설정한 다음 데이터베이스에 확장을 생성합니다. 이렇게 하면 파라미터 `rds.logical_replication` 및 `track_commit_timestamp`가 자동으로 활성화되고 `wal_level` 값이 `logical`로 설정됩니다.

이러한 작업을 수행하려면 `rds_superuser` 역할의 권한이 있어야 합니다.

AWS Management Console 또는 AWS CLI를 사용하여 PostgreSQL DB 인스턴스에 필요한 RDS를 생성할 수 있습니다. 다음 단계에서는 RDS for PostgreSQL DB 인스턴스가 사용자 지정 DB 파라미터 그룹에 연결되어 있다고 가정합니다. 사용자 지정 DB 파라미터 그룹 생성에 대한 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 단원을 참조하세요.

## 콘솔
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.CON"></a>

**pgactive 확장 기능을 초기화하려면**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 탐색 창에서 RDS for PostgreSQL DB 인스턴스를 선택합니다.

1. RDS for PostgreSQL DB 인스턴스의 **구성** 탭을 엽니다. 인스턴스 세부 정보에서 **DB 인스턴스 파라미터 그룹** 링크를 찾습니다.

1. 링크를 선택하여 RDS for PostgreSQL DB 인스턴스와 연결된 사용자 지정 파라미터를 엽니다.

1. `rds.enable_pgactive` 파라미터를 찾아 `1`로 설정하여 `pgactive` 기능을 초기화합니다.

1. **변경 사항 저장**을 선택합니다.

1. Amazon RDS 콘솔의 탐색 창에서 **데이터베이스**를 선택합니다.

1. RDS for PostgreSQL DB 인스턴스를 선택한 다음 **작업** 메뉴에서 **재부팅**을 선택합니다.

1. DB 인스턴스 재부팅을 확인하여 변경 사항을 적용합니다.

1. DB 인스턴스를 사용할 수 있게 되면 `psql` 또는 다른 PostgreSQL 클라이언트를 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

   다음 예시에서는 RDS for PostgreSQL DB 인스턴스에 *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 DB 인스턴스의 `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 DB 인스턴스를 재부팅하여 `pgactive` 라이브러리가 초기화되도록 합니다.

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 인스턴스를 사용할 수 있다면 `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

   ```
   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 DB 인스턴스용 액티브-액티브 복제 설정
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.setup-replication"></a>

다음 절차는 `pgactive`를 사용할 수 있을 때 RDS for PostgreSQL DB 인스턴스 간에 액티브-액티브 복제를 시작하는 방법을 보여 줍니다. 다중 리전 고가용성 예제를 실행하려면 Amazon RDS for PostgreSQL 인스턴스를 서로 다른 두 리전에 배포하고 VPC 피어링을 설정해야 합니다. 자세한 내용은 [VPC 피어링](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html)을 참조하세요.

**참고**  
여러 리전 간에 트래픽을 전송하면 추가 비용이 발생할 수 있습니다.

이 단계에서는 RDS for PostgreSQL DB 인스턴스가 `pgactive` 확장을 이용해 활성화되었다고 가정합니다. 자세한 내용은 [pgactive 확장 기능 초기화](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md) 섹션을 참조하세요.

**`pgactive` 확장을 사용하여 첫 번째 RDS for PostgreSQL DB 인스턴스를 구성하려면**

다음 예제는 `pgactive` 그룹을 생성하는 방법과 RDS for PostgreSQL에서 `pgactive` 확장을 생성하는 데 필요한 기타 단계를 보여줍니다.

1. `psql` 또는 다른 클라이언트 도구를 사용하여 첫 번째 RDS for PostgreSQL DB 인스턴스에 연결할 수 있습니다.

   ```
   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` 그룹 내 노드를 고유하게 식별하기 위해 할당하는 이름입니다.
**참고**  
공개적으로 액세스할 수 있는 DB 인스턴스에서 이 단계를 성공적으로 수행하려면 `rds.custom_dns_resolution` 파라미터를 `1`로 설정하여 활성화해야 합니다.

1. DB 인스턴스가 준비되었는지 확인하려면 다음 명령을 사용합니다.

   ```
   app=> SELECT pgactive.pgactive_wait_for_node_ready();
   ```

   이 명령이 제대로 실행되면 다음과 같은 출력이 표시됩니다.

   ```
   pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

**두 번째 RDS for PostgreSQL 인스턴스를 구성하고 `pgactive` 그룹에 연결하려면**

다음 예제는 RDS for PostgreSQL DB 인스턴스를 `pgactive` 그룹에 조인하는 방법과 DB 인스턴스에서 `pgactive` 확장을 생성하는 데 필요한 기타 단계를 보여줍니다.

이 단계에서는 다른 RDS for PostgreSQL DB 인스턴스가 `pgactive` 확장을 이용해 설정되었다고 가정합니다. 자세한 내용은 [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 DB 인스턴스에 데이터베이스를 생성합니다.

   ```
   postgres=> CREATE DATABASE app;
   ```

1. 다음 명령을 사용하여 새 데이터베이스로 연결을 전환합니다.

   ```
   \c app
   ```

1. 기존 데이터베이스에 `pgactive` 확장을 생성합니다.

   ```
   app=> CREATE EXTENSION pgactive;
   ```

1. 다음 명령을 사용하여 RDS for PostgreSQL 두 번째 DB 인스턴스를 더 안전한 방법으로 `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 두 번째 DB 인스턴스를 `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. DB 인스턴스가 준비되었는지 확인하려면 다음 명령을 사용합니다.

   ```
   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`는 두 DB 인스턴스 간에 데이터를 동기화합니다.

1. 다음 명령을 사용하여 두 번째 DB 인스턴스의 데이터베이스에 데이터가 있는지 확인할 수 있습니다.

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   데이터가 성공적으로 동기화되면 다음과 같은 출력이 표시됩니다.

   ```
    count
   -------
    3
   ```

1. 다음 명령을 실행하여 새 값을 삽입합니다.

   ```
   app=> INSERT INTO inventory.products (id, product_name) VALUES (4, 'lotion');
   ```

1. 첫 번째 DB 인스턴스의 데이터베이스에 연결하고 다음 쿼리를 실행합니다.

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   액티브-액티브 복제가 초기화된 경우 출력은 다음과 비슷합니다.

   ```
   count
   -------
    4
   ```

**`pgactive` 그룹에서 DB 인스턴스를 분리하고 제거하려면**

다음 단계를 사용하여 `pgactive` 그룹에서 DB 인스턴스를 분리하고 제거할 수 있습니다.

1. 다음 명령을 사용하여 첫 번째 DB 인스턴스에서 두 번째 DB 인스턴스를 분리할 수 있습니다.

   ```
   app=> SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app']);
   ```

1. 다음 명령을 사용하여 두 번째 DB 인스턴스에서 `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
```

최소한 다음 진단을 모니터링합니다.

활성화  
활성이 false이면 알림을 설정합니다. 이는 슬롯이 현재 사용 중이 아님을 나타냅니다(구독자 인스턴스가 게시자와 연결 해제됨).

pending\$1wal\$1decoding  
PostgreSQL의 논리적 복제에서 WAL 파일은 이진 형식으로 저장됩니다. 게시자는 이러한 WAL 변경 사항을 디코딩하고 논리적 변경(예: 삽입, 업데이트 또는 삭제 작업)으로 변환해야 합니다.  
지표 pending\$1wal\$1decoding은 게시자 측에서 디코딩 대기 중인 WAL 파일 수를 보여 줍니다.  
이 수는 다음과 같은 요인으로 인해 증가할 수 있습니다.  
+ 구독자가 연결되지 않은 경우 활성 상태는 false이고 pending\$1wal\$1decoding은 증가합니다.
+ 슬롯이 활성 상태이지만 게시자가 WAL 변경 볼륨을 따라갈 수 없습니다.

pending\$1wal\$1to\$1apply  
지표 pending\$1wal\$1apply는 구독자 측에서 적용 대기 중인 WAL 파일 수를 나타냅니다.  
몇 가지 요인으로 인해 구독자가 변경 사항을 적용하지 못하고 다음과 같은 디스크 전체 시나리오가 발생할 수 있습니다.  
+ 스키마 차이 - 예를 들어 샘플이라는 테이블의 WAL 스트림이 변경되었지만 해당 테이블이 구독자 측에 없는 경우
+ 프라이머리 키 열의 값이 업데이트됨
+ 보조 고유 인덱스로 인해 데이터 분산이 발생할 수 있음

# pgactive 확장에 대한 파라미터 설정 구성
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters"></a>

다음 쿼리를 사용하여 `pgactive` 확장과 관련된 모든 파라미터를 볼 수 있습니다.

```
app=> SELECT * FROM pg_settings WHERE name LIKE 'pgactive.%';
```

다양한 파라미터를 사용하여 `pgactive` 확장을 구성할 수 있습니다. 이러한 파라미터는 AWS Management Console 또는 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` | 끄기 | pgactive 적용 작업자의 커밋 동작을 결정합니다. 비활성화(꺼짐)되면 적용 작업자가 비동기 커밋을 수행하여 적용 작업 중에 PostgreSQL 처리량이 개선되지만, 업스트림에 대한 재생 확인은 지연됩니다. `off`로 설정하면 항상 안전하고 트랜잭션 손실이나 건너뛰기가 발생하지 않습니다. 이 설정은 다운스트림 노드의 디스크 플러시 타이밍 및 확인이 업스트림으로 전송되는 시점에만 영향을 미칩니다. 체크포인트 또는 주기적 작업과 같은 관련 없는 작업을 통해 커밋이 디스크로 플러시될 때까지 시스템에서 재생 플러시 확인 전송이 지연됩니다. 그러나 업스트림이 `synchronous_standby_names`에 나열된 다운스트림을 포함하는 경우 이를 `off`로 설정하면 업스트림에서 동기 커밋이 클라이언트에 성공을 보고하는 데 더 오랜 시간이 걸립니다. 이 경우 파라미터를 `on`으로 설정하세요.  `synchronous_standby_names`에 나열된 노드를 사용하여 이 파라미터를 `on`으로 설정하더라도 액티브-액티브 구성에서 복제 충돌이 발생할 수 있습니다. 이는 시스템에 노드 간 잠금 및 글로벌 스냅샷 관리가 부족하여 서로 다른 노드의 동시 트랜잭션이 동일한 튜플을 수정할 수 있기 때문입니다. 또한 트랜잭션은 업스트림 노드에서 커밋한 후에만 복제를 시작합니다. 동기 커밋을 활성화해도 pgactive 확장이 항상 일관된 시스템으로 변환되지 않습니다.  | 
| pgactive.temp\$1dump\$1directory | `string` | – | 초기 설정 중 데이터베이스 복제 작업에 필요한 임시 스토리지 경로를 정의합니다. 이 디렉터리는 postgres 사용자가 쓸 수 있어야 하며 전체 데이터베이스 덤프를 포함할 만큼 충분한 스토리지 공간이 있어야 합니다. 시스템은 논리적 복사 작업이 포함된 초기 데이터베이스 설정 중에만 이 위치를 사용합니다. 이 파라미터는 `pgactive_init_copy command`에서 사용되지 않습니다. | 
| pgactive.max\$1ddl\$1lock\$1delay | `milliseconds` | `-1` | 동시 쓰기 트랜잭션을 강제로 중단하기 전에 DDL 잠금의 최대 대기 시간을 지정합니다. 기본값은 `-1`이며, 이는 `max_standby_streaming_delay`에 설정된 값을 채택합니다. 이 파라미터는 시간 단위를 허용합니다. 예를 들어 10초를 나타내는 10s로 설정할 수 있습니다. 이 대기 기간 동안 시스템은 지속적 쓰기 트랜잭션이 커밋되거나 롤백될 때까지 기다리는 동안 DDL 잠금 획득을 시도합니다. 자세한 내용은 DDL 잠금을 참조하세요. | 
| pgactive.ddl\$1lock\$1timeout | `milliseconds` | `-1` | DDL 잠금 시도가 잠금을 얻기 위해 대기하는 시간을 지정합니다. 기본값은 lock\$1timeout에 지정된 값을 사용하는 `-1`입니다. 10초를 나타내는 10s와 같은 시간 단위를 사용하여 이 파라미터를 설정할 수 있습니다. 이 타이머는 DDL 잠금을 얻기 위한 대기 기간만 제어합니다. 시스템이 잠금을 얻고 DDL 작업을 시작하면 타이머가 중지됩니다. 이 파라미터는 DDL 잠금을 유지할 수 있는 총 기간 또는 전체 DDL 작업 시간을 제한하지 않습니다. 작업의 총기간을 제어하려면 `statement_timeout`을 대신 사용합니다. 자세한 내용은 DDL 잠금을 참조하세요. | 
| pgactive.debug\$1trace\$1ddl\$1locks\$1level | `boolean` | –  | `pgactive` 확장의 DDL 잠금 작업에 대한 기본 디버그 로그 수준을 재정의합니다. 이 설정을 구성하면 기본 수준 대신 LOG 디버그 수준에서 DDL 잠금 관련 메시지가 내보내집니다. 전체 서버에서 상세 `DEBUG1` 또는 `DEBUG2` 로그 수준을 활성화하지 않고 DDL 잠금 활동을 모니터링하려면 이 파라미터를 사용합니다. 사용 가능한 로그 수준(상세 수준이 낮은 순): [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/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의 지연 시간이 500ms인 경우 노드 A에 값을 삽입한 후 노드 B에 충돌하는 삽입을 수행할 수 있는 시간이 500ms 이상입니다.  서버를 다시 로드하거나 적용 작업자를 다시 시작해야 적용됩니다.  | 
| pgactive.connectability\$1check\$1duration | `integer` | –  | 실패한 시도 중에 데이터베이스 작업자가 연결을 설정하려고 시도하는 기간(초)을 지정합니다. 작업자는 성공하거나 이 제한 시간 값에 도달할 때까지 초당 1회 연결을 시도합니다. 이 설정은 작업자가 연결을 설정할 준비가 되기 전에 데이터베이스 엔진이 시작될 때 유용합니다. | 
| pgactive.skip\$1ddl\$1replication | `boolean` | `on` | `pgactive`가 활성화된 Amazon RDS에서 DDL 변경 사항이 복제되거나 처리되는 방식을 제어합니다. `on`으로 설정하면 노드가 비 pgcctive 노드와 같은 DDL 변경 사항을 처리합니다. 이 파라미터를 사용할 때는 다음 요구 사항이 적용됩니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 최고 사용자 권한을 사용하여 글로벌, 로컬(세션 수준)의 두 가지 방법으로 이 파라미터를 수정할 수 있습니다.  이 파라미터를 잘못 변경하면 복제 설정이 손상될 수 있습니다.  | 
| pgactive.do\$1not\$1replicate | `boolean` | – | 이 파라미터는 내부 전용입니다. 트랜잭션에서 이 파라미터를 설정하면 변경 사항이 DB 클러스터의 다른 노드에 복제되지 않습니다.  이 파라미터를 잘못 변경하면 복제 설정이 손상될 수 있습니다.  | 
| pgactive.discard\$1mismatched\$1row\$1attributes | `boolean` | –  | 이 파라미터는 전문가 전용입니다. 특정 복제 문제를 해결할 때만 이 파라미터를 사용하는 것이 좋습니다. 다음과 같은 경우 이 파라미터를 사용합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/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/ko_kr/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) 로그는 대기 중인 DDL 명령과 테이블 삭제도 캡처합니다.para> 기본적으로 로그에는 행 필드 콘텐츠가 포함되지 않습니다. 로그에 행 값을 포함하려면 다음 플래그가 활성화된 상태로 다시 컴파일해야 합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html)  이 로깅 설정을 활성화하면 성능에 영향이 미칠 수 있습니다. 문제 해결을 위해 필요한 경우에만 활성화하는 것이 좋습니다. 이 설정에 대한 변경 사항은 구성을 다시 로드할 때 적용됩니다. 서버를 다시 시작할 필요가 없습니다.   | 
| pgactive.extra\$1apply\$1connection\$1options |  | – | pgactive 노드와의 모든 피어 노드 연결에 대해 연결 파라미터를 구성할 수 있습니다. 이러한 파라미터는 keepalive 및 SSL 모드와 같은 설정을 제어합니다. 기본적으로 pgactive는 다음 연결 파라미터를 사용합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/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 설정을 활성화된 상태로 유지하는 것이 좋습니다. 신뢰할 수 없는 네트워크를 통해 대규모 트랜잭션을 완료하는 데 문제가 있는 경우에만 keepalive를 비활성화합니다.  기본 keepalive 설정을 활성화된 상태로 유지하는 것이 좋습니다. 신뢰할 수 없는 네트워크를 통해 대규모 트랜잭션을 완료하는 데 문제가 있는 경우에만 keepalive를 비활성화합니다. 이 설정에 대한 변경 사항은 구성을 다시 로드할 때 적용됩니다. 서버를 다시 시작할 필요가 없습니다.  | 
| 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/ko_kr/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 충돌은 PRIMARY KEY를 포함하여 여러 UNIQUE 제약 조건을 위반할 수 있습니다. 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는 UPDATE가 새 행(INSERT가 아직 수신되지 않음)인지 아니면 삭제된 행인지 확인할 수 없습니다. 두 시나리오 모두에서 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>

 pgactive 링크는 제외 제약 조건을 지원하지 않으며 이러한 조건이 만들어지지 못하게 합니다.

**참고**  
기존 독립 실행형 데이터베이스를 pgactivelink 데이터베이스로 변환하는 경우 모든 제외 제약 조건을 수동으로 삭제합니다.

분산 비동기 시스템에서는 제약 조건을 위반하는 행 집합이 없음을 보장할 수 없습니다. 이는 서로 다른 노드의 모든 트랜잭션이 완전히 격리되기 때문입니다. 제외 제약 조건으로 인해 노드에서 다른 노드로 재생을 진행할 수 없는 재생 교착 상태가 발생할 수 있습니다.

pgactive Link가 제외 제약 조건을 만들도록 강제하거나 독립 실행형 데이터베이스를 pgactive Link로 변환할 때 기존 제외 제약 조건을 삭제하지 않으면 복제가 중단될 수 있습니다. 복제 진행 상황을 복원하려면 원격 트랜잭션을 적용할 수 있도록 수신되는 원격 튜플과 충돌하는 로컬 튜플을 제거하거나 변경합니다.

### 글로벌 데이터 충돌
<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에는 Node2에 존재하지 않는 `foo`라는 테이블이 있습니다.
+ 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 확장은 `pgactive.log_conflicts_to_table` 설정에 관계없이 log\$1min\$1messages가 `LOG` 또는 `lower`로 설정된 경우 PostgreSQL 로그 파일에 충돌을 기록합니다.

 충돌 기록 테이블을 사용하여 다음을 수행할 수 있습니다.
+ 애플리케이션이 충돌을 생성하는 빈도 측정
+ 충돌이 발생하는 위치 식별
+ 애플리케이션을 개선하여 충돌률 감소
+ 충돌 해결로 원하는 결과가 나오지 않는 경우 감지
+ 사용자 정의 충돌 트리거 또는 애플리케이션 설계 변경이 필요한 위치 확인

 행 충돌의 경우 선택적으로 행 값을 로깅할 수 있습니다. 이는 `pgactive.log_conflicts_to_table` 설정에 의해 제어됩니다. 참고:
+ 이는 글로벌 데이터베이스 전체 옵션입니다.
+ 행 값 로깅에 대한 테이블별 제어는 없습니다.
+ 필드 번호, 배열 요소 또는 필드 길이에는 제한이 적용되지 않습니다.
+ 충돌을 트리거할 수 있는 수 메가바이트 크기의 행으로 작업하는 경우 이 기능을 활성화하지 않는 것이 좋습니다.

 충돌 기록 테이블에는 데이터베이스의 모든 테이블(각각 스키마가 다를 수 있음)의 데이터가 포함되어 있으므로 로깅된 행 값은 JSON 필드로 저장됩니다. JSON은 SQL에서 직접적으로 호출하는 것과 마찬가지로 `row_to_json`을 사용하여 만들어집니다. PostgreSQL은 `json_to_row` 함수를 제공하지 않으므로 로깅된 JSON에서 복합 형식 튜플을 재구성하려면 테이블별 코드(PL/pgSQL, PL/Python, PL/Perl 등)가 필요합니다.

**참고**  
사용자 정의 충돌에 대한 지원은 향후 확장 기능으로 계획되어 있습니다.

# 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는 액티브-액티브 복제 그룹에 참여하는 노드에 대한 정보를 저장합니다.


| 열 | Type | 콜레이션 | Nullable | 기본값 | 
| --- | --- | --- | --- | --- | 
| 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는 각 노드에 대한 연결 세부 정보를 저장합니다.


| 열 | Type | 콜레이션 | Nullable | 기본값 | 
| --- | --- | --- | --- | --- | 
| conn\$1sysid | 텍스트 | 없음 | Null이 아님 | 없음 | 
| conn\$1timeline | oid | 없음 | Null이 아님 | 없음 | 
| conn\$1dboid | oid | 없음 | Null이 아님 | 없음 | 
| conn\$1dsn | 텍스트 | 없음 | Null이 아님 | 없음 | 
| conn\$1apply\$1delay | 정수 | 없음 | 없음 | 없음 | 
| conn\$1replication\$1sets | 텍스트 | 없음 | 없음 | 없음 | 

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>

지정된 노드에 대해 마지막으로 적용된 트랜잭션 정보를 검색합니다.

**인수**  
+ sysid(텍스트) - 타임라인 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>

복제 적용 프로세스를 일시 중지합니다.

**인수**  
없음

**반환 타입**  
boolean

**사용 노트**  
복제 적용 프로세스를 일시 중지하려면 이 함수를 직접적으로 호출합니다.

## pgactive\$1apply\$1resume
<a name="pgactive-apply-resume"></a>

복제 적용 프로세스를 재개합니다.

**인수**  
없음

**반환 타입**  
void

**사용 노트**  
복제 적용 프로세스를 재개하려면 이 함수를 직접적으로 호출합니다.

## pgactive\$1is\$1apply\$1paused
<a name="pgactive-is-apply-paused"></a>

복제 적용이 현재 일시 중지되었는지 확인합니다.

**인수**  
없음

**반환 타입**  
boolean

**사용 노트**  
이 함수를 사용하여 복제 적용이 현재 일시 중지되었는지 확인합니다.

## pgactive\$1create\$1group
<a name="pgactive-create-group"></a>

독립 실행형 데이터베이스를 초기 노드로 변환하여 pgactive 그룹을 만듭니다.



**인수**  
+ node\$1name(텍스트)
+ node\$1dsn(텍스트)
+ apply\$1delay 정수 DEFAULT NULL::정수 - replication\$1sets 텍스트[] DEFAULT ARRAY[‘default’::텍스트]

**반환 타입**  
void

**사용 노트**  
독립 실행형 데이터베이스를 초기 노드로 변환하여 pgactive 그룹을 만듭니다. 이 함수는 노드를 pgactive 노드로 변환하기 전에 무결성 검사를 수행합니다. 이 함수를 사용하기 전에 PostgreSQL 클러스터에 pgactive 백그라운드 작업자를 지원할 수 있는 충분한 `max_worker_processes`가 있는지 확인합니다.

## pgactive\$1detach\$1nodes
<a name="pgactive-detach-nodes"></a>

pgactive 그룹에서 지정된 노드를 제거합니다.

**인수**  
+ p\$1nodes(텍스트[])

**반환 타입**  
void

**사용 노트**  
이 함수를 사용하여 pgactive 그룹에서 지정된 노드를 제거합니다.

## pgactive\$1exclude\$1table\$1replication\$1set
<a name="pgactive-exclude-table-replication-set"></a>

복제에서 특정 테이블을 제외합니다.

**인수**  
+ p\$1relation(regclass)

**반환 타입**  
void

**사용 노트**  
이 함수를 사용하여 복제에서 특정 테이블을 제외합니다.

## pgactive\$1get\$1replication\$1lag\$1info
<a name="pgactive-get-replication-lag-info"></a>

노드 세부 정보, WAL 상태 및 LSN 값을 포함한 자세한 복제 지연 정보를 검색합니다.

**인수**  
없음

**반환 타입**  
SETOF 레코드 - node\$1name 텍스트 - node\$1sysid 텍스트 - application\$1name 텍스트 - slot\$1name 텍스트 - active 부울 - active\$1pid 정수 - 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 복제 통계를 검색합니다.

**인수**  
없음

**반환 타입**  
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>

특정 관계에 대한 복제 세트 구성을 가져옵니다.

**인수**  
+ 관계(regclass)

**반환 타입**  
SETOF 레코드

**사용 노트**  
이 함수를 직접적으로 호출하여 특정 관계에 대한 복제 세트 구성을 가져옵니다.

## pgactive\$1include\$1table\$1replication\$1set
<a name="pgactive-include-table-replication-set"></a>

복제에 특정 테이블을 포함합니다.

**인수**  
+ p\$1relation(regclass)

**반환 타입**  
void

**사용 노트**  
복제에 특정 테이블을 포함하려면 이 함수를 사용합니다.

## pgactive\$1join\$1group
<a name="pgactive-join-group"></a>

기존 pgactive 그룹에 노드를 추가합니다.

**인수**  
+ node\$1name(텍스트)
+ node\$1dsn(텍스트)
+ join\$1using\$1dsn(텍스트)
+ apply\$1delay(정수, 선택 사항)
+ replication\$1sets(텍스트[], 기본값: ['default'])
+ bypass\$1collation\$1check(부울, 기본값: false)
+ bypass\$1node\$1identifier\$1creation(부울, 기본값: false)
+ bypass\$1user\$1tables\$1check(부울, 기본값: false)

**반환 타입**  
void

**사용 노트**  
이 함수를 직접적으로 호출하여 기존 pgactive 그룹에 노드를 추가합니다. PostgreSQL 클러스터에 pgactive 백그라운드 작업자를 위한 충분한 max\$1worker\$1processes가 있는지 확인합니다.

## pgactive\$1remove
<a name="pgactive-remove"></a>

로컬 노드에서 모든 pgactive 구성 요소를 제거합니다.

**인수**  
+ force(부울, 기본값: false)

**반환 타입**  
void

**사용 노트**  
로컬 노드에서 모든 pgactive 구성 요소를 제거하려면 이 함수를 직접적으로 호출합니다.

## pgactive\$1snowflake\$1id\$1nextval
<a name="pgactive-snowflake-id-nextval"></a>

노드별 고유 시퀀스 값을 생성합니다.

**인수**  
+ regclass

**반환 타입**  
bigint

**사용 노트**  
이 함수를 사용하여 노드별 고유 시퀀스 값을 생성합니다.

## pgactive\$1update\$1node\$1conninfo
<a name="pgactive-update-node-conninfo"></a>

pgactive 노드의 연결 정보를 업데이트합니다.

**인수**  
+ node\$1name\$1to\$1update(텍스트)
+ node\$1dsn\$1to\$1update(텍스트)

**반환 타입**  
void

**사용 노트**  
이 함수를 사용하여 pgactive 노드의 연결 정보를 업데이트합니다.

## pgactive\$1wait\$1for\$1node\$1ready
<a name="pgactive-wait-for-node-ready"></a>

그룹 생성 또는 조인 작업의 진행 상황을 모니터링합니다.

**인수**  
+ timeout(정수, 기본값: 0)
+ progress\$1interval(정수, 기본값: 60)

**반환 타입**  
void

**사용 노트**  
이 함수를 직접적으로 호출하여 그룹 만들기 또는 조인 작업의 진행 상황을 모니터링합니다.

# 액티브-액티브 복제의 충돌 처리
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-conflicts"></a>

`pgactive` 확장은 클러스터별이 아니라 데이터베이스별로 작동합니다. `pgactive`를 사용하는 각 DB 인스턴스는 독립 인스턴스이며 모든 소스의 데이터 변경을 수락할 수 있습니다. 변경 사항이 DB 인스턴스로 전송되면 PostgreSQL은 변경 사항을 로컬에서 커밋한 다음 `pgactive`를 사용하여 변경 사항을 다른 DB 인스턴스에 비동기적으로 복제합니다. 두 PostgreSQL DB 인스턴스가 거의 동시에 같은 레코드를 업데이트하는 경우 충돌이 발생할 수 있습니다.

`pgactive` 확장은 충돌 감지 및 자동 해결을 위한 메커니즘을 제공합니다. 두 DB 인스턴스 모두에서 트랜잭션이 커밋된 시점의 타임스탬프를 추적하고 최신 타임스탬프와 함께 변경 사항을 자동으로 적용합니다. 또한 `pgactive` 확장은 `pgactive.pgactive_conflict_history` 테이블에서 충돌이 발생하는 경우에 이를 로깅합니다.

`pgactive.pgactive_conflict_history`는 계속 규모가 늘어납니다. 제거 정책을 정의할 수 있습니다. 정기적으로 일부 레코드를 삭제하거나 이 관계에 대한 파티션 스키마를 정의하여 수행할 수 있으며, 나중에 원하는 파티션을 분리, 삭제, 잘라낼 수 있습니다. 정기적으로 제거 정책을 구현하기 위한 한 가지 옵션은 `pg_cron` 확장을 사용하는 것입니다. [PostgreSQL pg\$1cron 확장을 사용하여 유지 관리 일정 예약](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html) `pg_cron` 기록 테이블에 대한 다음 예제 정보를 참조하세요.

# 액티브-액티브 복제의 시퀀스 처리
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-sequences"></a>

`pgactive` 확장이 포함된 RDS for PostgreSQL DB 인스턴스는 서로 다른 두 개의 시퀀스 메커니즘을 사용하여 고유한 값을 생성합니다.

**글로벌 시퀀스**  
글로벌 시퀀스를 사용하려면 `CREATE SEQUENCE` 명령문을 사용하여 로컬 시퀀스를 생성합니다. 시퀀스의 다음 고유 값을 가져오려면 `usingnextval(seqname)` 대신 `pgactive.pgactive_snowflake_id_nextval(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` 권한을 가지고 있다고 가정하겠습니다. 다음 구문은 `postgres` 데이터베이스의 모든 표 인덱스를 포함하는 전체 표에 대해 `pg_repack`을 수행합니다.

   ```
   pg_repack -h db-instance-name.111122223333.aws-region.rds.amazonaws.com -U rds_test -k postgres
   ```
**참고**  
-k 옵션을 사용하여 연결해야 합니다. -a 옵션은 지원되지 않습니다.

   `pg_repack` 클라이언트의 응답은 재압축된 DB 인스턴스상의 표에 대한 정보를 제공합니다.

   ```
   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인 경우 초기 표 구축 작업을 완료하는 데 약 1,000분 또는 약 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 DB 인스턴스의 스냅샷을 생성하는 것이 좋습니다. 자세한 내용은 [Amazon RDS의 단일 AZ DB 인스턴스에 대한 DB 스냅샷 생성](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 DB 인스턴스의 스냅샷을 생성합니다. 이미 해당 스냅샷을 생성한 경우 이 단계를 건너뜁니다. 스냅샷이 생성되는 동안 다음 단계를 따라 계속 진행할 수 있습니다.

1. DB 인스턴스에 있는 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` - 사용자 지정 형식
   + --schema-only - 스키마(이 경우에서는 함수)를 생성하는 데 필요한 명령만 덤프
   + `-U` – RDS 기본 사용자 이름
   + `database` – DB 인스턴스의 데이터베이스 이름

   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)
+ [PL/Rust가 있는 상자 사용](#PL_Rust-crates)
+ [PL/Rust 제한 사항](#PL_Rust-limitations)

## PL/Rust 설정
<a name="PL_Rust-setting-up"></a>

DB 인스턴스에 plrust 확장을 설치하려면 DB 인스턴스와 연결된 DB 파라미터 그룹의 `shared_preload_libraries` 파라미터에 plrust를 추가합니다. plrust 확장이 설치되어 있으면 함수를 만들 수 있습니다.

`shared_preload_libraries` 파라미터를 수정하려면 DB 인스턴스가 사용자 지정 파라미터 그룹과 연결되어 있어야 합니다. 사용자 지정 DB 파라미터 그룹 생성에 대한 자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 단원을 참조하세요.

AWS Management Console 또는 AWS CLI를 사용하여 plrust 확장을 설치할 수 있습니다.

다음 단계에서는 DB 인스턴스가 사용자 지정 DB 파라미터 그룹에 연결되어 있다고 가정합니다.

### 콘솔
<a name="PL_Rust-setting-up.CON"></a>

**`shared_preload_libraries` 파라미터에 plrust 확장 설치**

`rds_superuser` 그룹(역할)의 멤버인 계정을 사용하여 다음 단계를 완료합니다.

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. 탐색 창에서 **Databases**(데이터베이스)를 선택합니다.

1. DB 인스턴스의 이름을 선택하여 세부 정보를 표시합니다.

1. DB 인스턴스의 **구성** 탭을 열고 DB 인스턴스 파라미터 그룹 링크를 찾습니다.

1. 링크를 선택하여 DB 인스턴스와 연결된 사용자 지정 파라미터를 엽니다.

1. **파라미터** 검색 필드에 `shared_pre`를 입력하여 **`shared_preload_libraries`** 파라미터를 찾습니다.

1. **파라미터 편집**을 선택하여 속성 값에 액세스합니다.

1. **값** 필드의 목록에 plrust를 추가합니다. 쉼표를 사용하여 값 목록에서 항목을 구분합니다.

1. `shared_preload_libraries` 파라미터 변경 사항을 적용하려면 DB 인스턴스를 재부팅합니다. 초기 재부팅을 완료하려면 추가 시간이 필요할 수 있습니다.

1. 인스턴스를 사용할 수 있게 되면 plrust가 초기화되었는지 확인합니다. `psql`을 사용하여 DB 인스턴스에 연결하고 다음 명령을 실행합니다.

   ```
   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 명령을 사용하여 DB 인스턴스를 재부팅하고 plrust 라이브러리를 초기화합니다. 초기 재부팅을 완료하려면 추가 시간이 필요할 수 있습니다.

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 인스턴스를 사용할 수 있게 되면 plrust가 초기화되었는지 확인합니다. `psql`을 사용하여 DB 인스턴스에 연결하고 다음 명령을 실행합니다.

   ```
   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;
```

## 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는 추가 상자를 지원합니다.
+ `url` 
+ `regex` 
+ `serde` 
+ `serde_json` 

RDS for PostgreSQL 15.5-R2 이상 버전, 14.10-R2 이상 14 버전, 13.13-R2 이상 13 버전에서 RDS for PostgreSQL은 PL/Rust에서 두 개의 추가 크레이트를 지원합니다.
+ `croaring-rs` 
+ `num-bigint` 

Amazon RDS for PostgreSQL 버전 15.4, 14.9, 13.12부터 PL/Rust는 다음 상자를 지원합니다.
+ `aes` 
+ `ctr` 
+ `rand` 

이 상자에서는 기본 기능만 지원됩니다. 새 RDS for PostgreSQL 버전에는 업데이트된 버전의 상자가 포함될 수 있으며 기존 버전의 상자는 더 이상 지원되지 않을 수 있습니다.

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 DB 엔진 업그레이드](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 DB 인스턴스에 연결합니다. 인스턴스를 설정할 때 기본 이름을 유지했다면 `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
```

세션을 종료하고 다음과 같이 RDS for PostgreSQL DB 인스턴스에 `gis_admin`으로 다시 연결합니다.

```
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 보안](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 Geocoder](https://postgis.net/docs/Extras.html#Tiger_Geocoder)를 참조하세요.

다음 `SELECT` 문을 사용하여 `topology` 스키마를 테스트합니다. 이렇게 하면 지정된 공간 참조 식별자(26986) 및 기본 허용 오차(0.5)를 사용하여 새 토폴로지 개체(my\$1new\$1topo)를 등록하는 `createtopology` 함수를 호출합니다. 자세한 내용은 PostgreSQL의 [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 DB 인스턴스에서 사용 가능한 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>

*Aurora PostgreSQL 릴리스 정보*의 *Amazon RDS for PostgreSQL 릴리스 정보*의 [Extension versions for Amazon RDS for PostgreSQL의 확장 버전](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html) 릴리스에서 사용 가능한 버전 목록을 얻으려면 다음 명령을 사용하세요.

```
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. 의 PostgreSQL 버전에 사용할 수 있는 PostGIS의 기본 버전을 식별합니다. RDS for PostgreSQL DB 인스턴스  이렇게 하려면 다음 쿼리를 실행합니다.

   ```
   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. 에서 각 데이터베이스에 설치된 PostGIS 버전을 식별합니다. 사용자의 RDS for PostgreSQL DB 인스턴트. 즉, 다음과 같이 각 사용자 데이터베이스를 쿼리합니다.

   ```
   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)입니다. 업그레이드를 완료하려면 다음과 같이 upgrade 명령을 다시 실행합니다.

   ```
   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 DB 클러스터가 Oracle 데이터베이스와 함께 작동할 수 있습니다. 또 다른 예로, PostgreSQL 네이티브 `postgres_fdw` 확장을 사용하면 RDS for PostgreSQL DB 인스턴스 외부에서 PostgreSQL DB 인스턴스에 저장된 데이터에 액세스할 수 있습니다.

아래에서는 여러 지원되는 PostgreSQL 외부 데이터 래퍼에 관한 정보를 확인할 수 있습니다.

**Topics**
+ [log\$1fdw 확장으로 SQL을 사용하여 DB 로그에 액세스](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을 사용하여 DB 로그에 액세스
<a name="CHAP_PostgreSQL.Extensions.log_fdw"></a>

RDS for PostgreSQL DB 인스턴스는 SQL 인터페이스를 사용하여 데이터베이스 엔진 로그에 액세스할 수 있는 `log_fdw` 확장을 지원합니다. `log_fdw` 확장은 데이터베이스 로그용 외부 테이블을 간편하게 생성할 수 있게 해주는 2가지 함수를 제공합니다.
+ `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` 역할의 구성원은 다른 데이터베이스 사용자에게 이러한 함수에 대한 액세스 권한을 부여할 수 있습니다.

기본적으로 로그 파일은 `log_destination` 파라미터에 명시된 대로 Amazon RDS에 의해 `stderr`(표준 오류) 형식으로 생성됩니다. 이 파라미터에는 두 가지 옵션만 있습니다. `stderr` 및 `csvlog`(쉼표로 구분된 값, CSV)입니다. 파라미터에 `csvlog` 옵션을 추가하는 경우 Amazon RDS가 `stderr` 및 `csvlog` 로그를 모두 생성합니다. 이는 DB 클러스터의 스토리지 용량에 영향을 줄 수 있으므로 로그 처리에 영향을 주는 다른 파라미터를 알고 있어야 합니다. 자세한 내용은 [로그 대상 설정(`stderr`, `csvlog`)](USER_LogAccess.Concepts.PostgreSQL.overview.parameter-groups.md#USER_LogAccess.Concepts.PostgreSQL.Log_Format) 섹션을 참조하세요.

`csvlog` 로그를 생성할 때의 한 가지 이점은 `log_fdw` 확장을 사용하여 여러 열로 깔끔하게 분할된 데이터로 외부 테이블을 작성할 수 있다는 점입니다. 그러려면 인스턴스를 사용자 지정 DB 파라미터 그룹과 연결해야 `log_destination`에 대한 설정을 변경할 수 있습니다. 이에 관한 정보는 [RDS for PostgreSQL DB 인스턴스에 파라미터로 작업](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 DB 인스턴스에서 원격 연결을 설정하는 경우 읽기 전용 복제본에도 액세스할 수 있습니다.

**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 DB 인스턴스에서 MySQL 호환 데이터베이스에 액세스하려면 `mysql_fdw` 확장을 설치하고 사용하면 됩니다. 이 외부 데이터 래퍼를 사용하면 RDS for MySQL, Aurora MySQL, MariaDB 및 기타 MySQL 호환 데이터베이스로 작업할 수 있습니다. RDS for PostgreSQL DB 인스턴스에서 MySQL 데이터베이스로의 연결은 클라이언트 및 서버 구성에 따라 최선의 방식으로 암호화됩니다. 그러나 원하는 경우 암호화를 적용할 수 있습니다. 자세한 내용은 [확장에서 전송 중 암호화 사용](#postgresql-mysql-fdw.encryption-in-transit) 섹션을 참조하세요.

`mysql_fdw` 확장은 Amazon RDS for PostgreSQL 버전 14.2, 13.6 이상에서 지원됩니다. RDS for PostgreSQL DB에서 MySQL 호환 데이터베이스 인스턴스의 테이블에 대한 선택, 삽입, 업데이트 및 삭제를 지원합니다.

**Topics**
+ [mysql\$1fdw 확장을 사용하도록 RDS for PostgreSQL DB 설정](#postgresql-mysql-fdw.setting-up)
+ [예: RDS for PostgreSQL에서 RDS for MySQL 데이터베이스로 작업](#postgresql-mysql-fdw.using-mysql_fdw)
+ [확장에서 전송 중 암호화 사용](#postgresql-mysql-fdw.encryption-in-transit)

## mysql\$1fdw 확장을 사용하도록 RDS for PostgreSQL DB 설정
<a name="postgresql-mysql-fdw.setting-up"></a>

RDS for PostgreSQL DB 인스턴스에서 `mysql_fdw` 확장을 설정하려면 DB 인스턴스에서 확장을 로드한 다음 MySQL DB 인스턴스에 대한 연결 지점을 생성해야 합니다. 이 작업을 수행하려면 MySQL DB 인스턴스에 대한 다음과 같은 세부 정보가 필요합니다.
+ 호스트 이름 또는 엔드포인트. RDS for MySQL DB 인스턴스의 경우 콘솔을 사용하여 엔드포인트를 찾을 수 있습니다. 연결 및 보안(Connectivity & security) 탭을 선택하고 '엔드포인트 및 포트(Endpoint and port)' 섹션을 살펴봅니다.
+ 포트 번호. MySQL의 기본 포트 번호는 3306입니다.
+ 데이터베이스 이름 DB 식별자입니다.

또한 MySQL 포트 3306의 액세스 제어 목록(ACL) 또는 보안 그룹에 대한 액세스를 제공해야 합니다. RDS for PostgreSQL DB 인스턴스와 RDS for MySQL DB 인스턴스에 포트 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 DB 인스턴스로 작업하기 위해 적절한 MySQL 사용자 계정에 대한 자체 매핑을 생성합니다.

**mysql\$1fdw로 MySQL 데이터베이스 서버에 액세스하려면**

1. `rds_superuser` 역할이 있는 계정을 사용하여 PostgreSQL DB 인스턴스에 연결합니다. RDS for PostgreSQL DB 인스턴스를 생성할 때 기본값을 수락한 경우 사용자 이름은 `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 DB 인스턴스에 확장을 설치한 후 MySQL 데이터베이스에 대한 연결을 제공하는 외부 서버를 설정합니다.

**외부 서버를 생성하려면**

RDS for PostgreSQL DB 인스턴스에서 작업을 수행합니다. 이러한 단계에서는 `postgres`와 같은 `rds_superuser` 권한이 있는 사용자로 연결되어 있다고 가정합니다.

1. RDS for PostgreSQL DB 인스턴스에서 외부 서버를 생성합니다.

   ```
   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 DB 인스턴스에 간단한 테이블이 있다고 가정합니다. RDS for PostgreSQL 사용자는 해당 테이블에 대해 (`SELECT`), `INSERT`, `UPDATE`, `DELETE` 항목을 쿼리하려고 합니다. 앞의 절차에서 설명한 대로 RDS for PostgreSQL DB 인스턴스에 `mysql_fdw` 확장이 생성되었다고 가정합니다. `rds_superuser` 권한이 있는 사용자로 RDS for PostgreSQL DB 인스턴스에 연결한 후 다음 단계를 진행할 수 있습니다.

1. RDS for PostgreSQL DB 인스턴스에서 외부 서버를 생성합니다.

   ```
   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 DB 인스턴스에서 Oracle 데이터베이스에 액세스하려면 `oracle_fdw` 확장을 설치하고 사용할 수 있습니다. 이 확장은 Oracle 데이터베이스의 외부 데이터 래퍼입니다. 이 확장 프로그램에 대해 자세히 알아보려면 [oracle\$1fdw](https://github.com/laurenz/oracle_fdw) 문서를 참조하세요.

`oracle_fdw` 확장은 RDS for PostgreSQL 버전 12.7 및 13.3 이상에서 지원됩니다.

**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 Database에 연결된 외부 서버를 만들려면**

1. RDS for Oracle DB 인스턴스에서는 다음 사항에 유의하세요.
   + 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에서 Oracle 간의 전송 중인 암호화는 클라이언트와 서버 구성 파라미터의 조합을 기반으로 합니다. Oracle 21c를 사용하는 예제는 Oracle 문서의 [About the Values for Negotiating Encryption and Integrity](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 Security Library(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`에서 암호를 보려면 추가 권한이 필요합니다.

`information_schema._pg_user_mappings`에서 암호를 보려면 `rds_superuser`에 대한 추가 권한은 필요하지 않습니다.

`rds_superuser` 역할이 없는 사용자는 다음 조건에서만 `pg_user_mappings`에서 암호를 볼 수 있습니다.
+ 현재 사용자는 매핑되는 사용자이며 서버를 소유하거나 서버에 대한 `USAGE` 권한을 보유하고 있습니다.
+ 현재 사용자는 서버 소유자이고 매핑은 `PUBLIC`에 대한 것입니다.

# tds\$1fdw 확장을 사용하여 SQL Server 데이터베이스 작업
<a name="postgresql-tds-fdw"></a>

PostgreSQL `tds_fdw` 확장을 사용하여 Sybase 및 Microsoft SQL Server 데이터베이스와 같은 테이블 형식 데이터 스트림(TDS) 프로토콜을 지원하는 데이터베이스에 액세스할 수 있습니다. 이 외부 데이터 래퍼를 사용하면 RDS for PostgreSQL DB 인스턴스 에서 Amazon RDS for Microsoft SQL Server를 포함하여 TDS 프로토콜을 사용하는 데이터베이스에 연결할 수 있습니다. 자세한 내용은 GitHub에서 [tds-fdw/tds\$1fdw](https://github.com/tds-fdw/tds_fdw) 설명서를 참조하세요.

`tds_fdw` 확장은 Amazon RDS for PostgreSQL 버전 14.2 및 13.6 이상 릴리스에서 지원됩니다.

## tds\$1fdw 확장을 사용하도록 Aurora PostgreSQL DB 설정
<a name="postgresql-tds-fdw-setting-up"></a>

다음 절차에서는 RDS for PostgreSQL DB 인스턴스와 함께 `tds_fdw`를 설정하고 사용하는 예를 확인할 수 있습니다. `tds_fdw`를 사용하여 SQL Server 데이터베이스에 연결하기 전에 인스턴스에 대한 다음 세부 정보를 확인해야 합니다.
+ 호스트 이름 또는 엔드포인트. RDS for SQL Server DB 인스턴스의 경우 콘솔을 사용하여 엔드포인트를 찾을 수 있습니다. 연결 및 보안(Connectivity & security) 탭을 선택하고 '엔드포인트 및 포트(Endpoint and port)' 섹션을 살펴봅니다.
+ 포트 번호. Microsoft SQL Server의 기본 포트 번호는 포트 1433입니다.
+ 데이터베이스 이름 DB 식별자입니다.

또한 SQL Server 포트 1433의 액세스 제어 목록(ACL) 또는 보안 그룹에 대한 액세스를 제공해야 합니다. RDS for PostgreSQL DB 인스턴스와 RDS for MySQL DB 인스턴스가 모두 포트 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 DB 인스턴스에 연결합니다.

   ```
   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 DB 인스턴스에 확장을 설치한 후 외부 서버를 설정합니다.

**외부 서버를 생성하려면**

`rds_superuser` 권한이 있는 계정을 사용하여 RDS for PostgreSQL DB 인스턴스에서 다음과 같은 작업을 수행합니다.

1. RDS for PostgreSQL DB 인스턴스에서 외부 서버를 생성합니다.

   ```
   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 DB 인스턴스S에서 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로의 연결은 SQL Server 데이터베이스 구성에 따라 전송 중 암호화(TLS/SSL)를 사용합니다. SQL Server에 암호화가 구성되지 않은 경우 SQL Server 데이터베이스에 대한 요청을 수행하는 RDS for PostgreSQL 클라이언트가 암호화되지 않은 상태로 폴백됩니다.

`rds.force_ssl` 파라미터를 설정하여 RDS for SQL Server DB 인스턴스에 대한 연결에 암호화를 적용할 수 있습니다. 자세한 방법은 [DB 인스턴스 연결이 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 구성과 관련된 자세한 내용은 [Microsoft SQL Server DB 인스턴스와 함께 SSL 사용](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 DB 인스턴스에서 안전하게 실행할 수 있습니다. PostgreSQL용 신뢰할 수 있는 언어 확장(TLE)을 사용하면 PostgreSQL 기능 확장을 위해 문서화된 접근 방식을 따르는 PostgreSQL 확장을 생성할 수 있습니다. 자세한 내용은 PostgreSQL 설명서에서 [Packaging Related Objects into an Extension](https://www.postgresql.org/docs/current/extend-extensions.html)을 참조하세요.

TLE의 주요 이점 중 하나는 PostgreSQL 인스턴스의 기반이 되는 파일 시스템에 대한 액세스를 제공하지 않는 환경에서 사용할 수 있다는 것입니다. 이전에는 새 확장을 설치하려면 파일 시스템에 액세스해야 했습니다. TLE는 이러한 제약을 제거합니다. TLE는 RDS for PostgreSQL DB 인스턴스에서 실행되는 데이터베이스를 포함하여 모든 PostgreSQL 데이터베이스를 위한 새 확장을 생성할 수 있는 개발 환경을 제공합니다.

TLE는 TLE를 사용하여 만든 확장의 안전하지 않은 리소스에 대한 액세스를 방지하도록 설계되었습니다. 런타임 환경은 확장 결함이 미치는 영향을 단일 데이터베이스 연결로 제한합니다. 또한 TLE는 데이터베이스 관리자에게 확장을 설치할 수 있는 사용자를 세밀하게 제어할 수 있도록 하며, 확장을 실행하기 위한 권한 모델을 제공합니다.

TLE는 다음 RDS for PostgreSQL 버전에서 지원됩니다.
+  버전 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에서 확장 생성을 지원합니다. 다른 PostgreSQL 확장을 설치하는 것과 동일한 방식으로 RDS for PostgreSQL DB 인스턴스에 `pg_tle` 확장을 설치합니다. `pg_tle`가 설정되면 개발자는 이를 사용하여 *TLE 확장*이라는 새 PostgreSQL 확장을 생성할 수 있습니다.

 

다음 주제에는 신뢰할 수 있는 언어 확장 설정 방법 및 자체 TLE 확장 생성 시작 방법에 대한 정보가 나와 있습니다.

**Topics**
+ [용어](PostgreSQL_trusted_language_extension-terminology.md)
+ [PostgreSQL용 신뢰할 수 있는 언어 확장을 사용하기 위한 요구 사항](PostgreSQL_trusted_language_extension-requirements.md)
+ [RDS for PostgreSQL DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정](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 설명서의 [Trusted and Untrusted 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 DB 엔진 업그레이드](USER_UpgradeDBInstance.PostgreSQL.md)를 참조하세요.
  + PostgreSQL을 실행하는 Amazon RDS DB 인스턴스가 아직 없는 경우 새로 생성할 수 있습니다. 자세한 내용은 RDS for PostgreSQL DB 인스턴스의 경우 [PostgreSQL DB 인스턴스 생성 및 해당 인스턴스에 연결](CHAP_GettingStarted.CreatingConnecting.PostgreSQL.md)을 참조하세요.  
+ **`rds_superuser` 권한 필요** - `pg_tle` 확장을 설정하고 구성하려면 데이터베이스 사용자 역할에 `rds_superuser` 역할의 권한이 있어야 합니다. 기본적으로 이 역할은 를 생성한 `postgres` 사용자에게 부여됩니다. RDS for PostgreSQL DB 인스턴스 
+ **사용자 지정 DB 파라미터 그룹 필요** - RDS for PostgreSQL DB 인스턴스는 사용자 지정 DB 파라미터 그룹을 사용하여 구성해야 합니다. 
  +  RDS for PostgreSQL DB 인스턴스가 사용자 지정 DB 파라미터 그룹을 사용하여 구성되지 않은 경우, 파라미터 그룹을 하나 생성하여 RDS for PostgreSQL DB 인스턴스에 연결해야 합니다. 단계에 대한 간략한 요약은 [사용자 지정 DB 파라미터 그룹 생성 및 적용](#PostgreSQL_trusted_language_extension-requirements-create-custom-params) 섹션을 참조하세요.
  +  RDS for PostgreSQL DB 인스턴스가 이미 사용자 지정 DB 파라미터 그룹을 사용하여 구성되어 있는 경우 신뢰할 수 있는 언어 확장을 설정할 수 있습니다. 자세한 내용은 [RDS for PostgreSQL DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정](PostgreSQL_trusted_language_extension-setting-up.md)을 참조하세요.

## 사용자 지정 DB 파라미터 그룹 생성 및 적용
<a name="PostgreSQL_trusted_language_extension-requirements-create-custom-params"></a>

다음 단계를 사용하여 사용자 지정 DB 파라미터 그룹을 생성하고 이를 사용하도록 RDS for PostgreSQL DB 인스턴스를 구성합니다.

### 콘솔
<a name="PostgreSQL_trusted_language_extension-requirements-custom-parameters.CON"></a>

**사용자 지정 DB 파라미터 그룹을 생성하고 RDS for PostgreSQL DB 인스턴스에 사용하는 방법**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 Amazon RDS 콘솔을 엽니다.

1. Amazon RDS 메뉴에서 Parameter groups(파라미터 그룹)를 선택합니다.

1. **Create parameter group**(파라미터 그룹 생성)을 선택합니다.

1. **Parameter group details**(파라미터 그룹 세부 정보) 페이지에서 다음 정보를 입력합니다.
   + **Parameter group family**(파라미터 그룹 패밀리)에서 postgres14를 선택합니다.
   + **Type**(유형)에서 DB Parameter Group을 선택합니다.
   + **Group name**(그룹 이름)에서 작업 컨텍스트에서 의미 있는 파라미터 그룹 이름을 지정합니다.
   + **Description**(설명)에 다른 팀원이 쉽게 찾을 수 있도록 유용한 설명을 입력합니다.

1. **Create**(생성)를 선택합니다. 사용자 지정 DB 파라미터 그룹이 AWS 리전에 생성됩니다. 이제 다음 단계에 따라 파라미터 그룹을 사용하도록 RDS for PostgreSQL DB 인스턴스를 수정할 수 있습니다.

1. Amazon RDS 메뉴에서 **Databases**(데이터베이스)를 선택합니다.

1. 나열된 항목 중에서 TLE와 함께 사용할 RDS for PostgreSQL DB 인스턴스를 선택한 다음 **Modify**(수정)를 선택합니다.

1.  DB 인스턴스 설정 수정 페이지의 추가 구성 섹션에서 **데이터베이스 옵션**을 찾고 선택기에서 사용자 지정 DB 파라미터 그룹을 선택합니다.

1. **Continue**(계속)를 선택하여 변경 내용을 저장합니다.

1. **Apply immediately**(즉시 적용)를 선택하면 TLE를 사용하도록 RDS for PostgreSQL DB 인스턴스를 계속 설정할 수 있습니다.

신뢰할 수 있는 언어 확장을 사용하도록 시스템을 계속 설정하려면 [RDS for PostgreSQL DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정](PostgreSQL_trusted_language_extension-setting-up.md) 섹션을 참조하세요.

 DB 파라미터 그룹은 [Amazon RDS DB 인스턴스용 DB 파라미터 그룹](USER_WorkingWithDBInstanceParamGroups.md) 섹션을 참조하세요.

### AWS CLI
<a name="PostgreSQL_trusted_language_extension-requirements-custom-parameters-CLI"></a>

기본 AWS 리전으로 AWS CLI를 구성하면 CLI 명령을 사용할 때 `--region` 인수를 지정하지 않아도 됩니다. 자세한 내용은 *AWS Command Line Interface 사용 설명서*의 [구성 기초](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config) 섹션을 참조하세요.

**사용자 지정 DB 파라미터 그룹을 생성하고 RDS for PostgreSQL DB 인스턴스에 사용하는 방법**

1. [create-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-parameter-group.html) AWS CLI 명령을 사용하여 사용자 AWS 리전의 postgres14를 기반으로 사용자 지정 DB 파라미터 그룹을 만들 수 있습니다. 

   대상 LinuxmacOS, 또는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"
   ```

   사용자 지정 DB 파라미터 그룹은 AWS 리전에서 사용할 수 있으므로 파라미터 그룹을 사용하도록 RDS for PostgreSQL DB 인스턴스를 수정할 수 있습니다.

1. [modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html) AWS CLI 명령을 사용하여 사용자 지정 DB 파라미터 그룹을 RDS for PostgreSQL DB 인스턴스에 적용합니다. 이 명령은 활성 인스턴스를 즉시 재부팅합니다.

   대상 LinuxmacOS, 또는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 DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정](PostgreSQL_trusted_language_extension-setting-up.md) 섹션을 참조하세요.

자세한 내용은 [Amazon RDS의 파라미터 그룹](USER_WorkingWithParamGroups.md) 단원을 참조하세요.

# RDS for PostgreSQL DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정
<a name="PostgreSQL_trusted_language_extension-setting-up"></a>

다음 단계에서는 사용자의 RDS for PostgreSQL DB 인스턴스가 사용자 지정 DB 파라미터 그룹에 연결되어 있다고 가정합니다. 이러한 단계에 AWS Management Console 또는 AWS CLI를 사용할 수 있습니다.

 RDS for PostgreSQL DB 인스턴스에 신뢰할 수 있는 언어 확장을 설정하는 경우 특정 데이터베이스 권한이 있는 데이터베이스 사용자가 사용할 수 있도록 특정 데이터베이스에 설치합니다.

## 콘솔
<a name="PostgreSQL_trusted_language_extension-setting-up.CON"></a>

**신뢰할 수 있는 언어 확장 설정 방법**

`rds_superuser` 그룹(역할)의 구성원인 계정을 사용하여 다음 단계를 수행합니다.

1. [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)에서 AWS Management Console에 로그인한 후 Amazon RDS 콘솔을 엽니다.

1. 탐색 창에서 RDS for PostgreSQL DB 인스턴스를 선택합니다.

1. 의 **구성** 탭을 엽니다. RDS for PostgreSQL DB 인스턴스 인스턴스 세부 정보 중에서 **파라미터 그룹** 링크를 찾습니다.

1. 링크를 선택하여 와 연결된 사용자 지정 파라미터를 엽니다. RDS for PostgreSQL DB 인스턴스 

1. **파라미터** 검색 필드에 `shared_pre`를 입력하여 `shared_preload_libraries` 파라미터를 찾습니다.

1. **파라미터 편집**을 선택하여 속성 값에 액세스합니다.

1. **값** 필드의 목록에 `pg_tle`를 추가합니다. 쉼표를 사용하여 값 목록에서 항목을 구분합니다.  
![\[pg_tle가 추가된 shared_preload_libraries 파라미터 이미지.\]](http://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pg_tle.png)

1. RDS for PostgreSQL DB 인스턴스를 재부팅하여 `shared_preload_libraries` 파라미터 변경 사항이 적용되도록 합니다.

1. 인스턴스를 사용할 수 있게 되면 `pg_tle`가 초기화되었는지 확인합니다. `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결하고 다음 명령을 실행합니다.

   ```
   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. PostgreSQL DB 인스턴스를 설정할 때 RDS for PostgreSQL DB 인스턴스를 위해 만든 기본 사용자 이름에 `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>

기본 AWS 리전으로 AWS CLI를 구성하면 CLI 명령을 사용할 때 `--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 DB 인스턴스를 재부팅하고 `pg_tle` 라이브러리를 초기화합니다.

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 인스턴스를 사용할 수 있게 되면 `pg_tle`가 초기화되었는지 확인할 수 있습니다. `psql`을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결하고 다음 명령을 실행합니다.

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pg_tle
   (1 row)
   ```

   `pg_tle`이 초기화되었으므로 이제 확장을 생성할 수 있습니다.

   ```
   CREATE EXTENSION pg_tle;
   ```

1. PostgreSQL DB 인스턴스를 설정할 때 RDS for PostgreSQL DB 인스턴스를 위해 만든 기본 사용자 이름에 `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 확장을 설정하는 것과 동일한 방식으로 RDS for PostgreSQL DB 인스턴스에 설치하는 PostgreSQL 확장입니다. PgAdmin 클라이언트 도구에 있는 예제 데이터베이스의 다음 이미지에서 `pg_tle` 확장을 구성하는 일부 구성 요소를 볼 수 있습니다.

![\[TLE 개발 키트를 구성하는 일부 구성 요소를 보여 주는 이미지.\]](http://docs.aws.amazon.com/ko_kr/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는 확장 설치, 등록, 관리를 위한 12개 이상의 도우미 함수를 제공합니다. 이러한 함수에 대한 자세한 내용은 [PostgreSQL용 신뢰할 수 있는 언어 확장에 대한 함수 참조](PostgreSQL_trusted_language_extension-functions-reference.md) 섹션을 참조하세요.

`pg_tle` 확장의 기타 구성 요소에는 다음이 포함됩니다.
+ **`pgtle_admin` 역할** - `pg_tle` 확장이 설치될 때 `pgtle_admin` 역할이 생성됩니다. 이 역할은 권한이 부여되므로 그에 따라 취급되어야 합니다. 데이터베이스 사용자에게 `pgtle_admin` 역할을 부여할 때는 *최소 권한* 원칙을 따르는 것이 좋습니다. 즉, 새 TLE 확장을 생성, 설치, 관리할 수 있는 데이터베이스 사용자에게만 `pgtle_admin` 역할을 부여합니다(예: `postgres`).
+ **`pgtle.feature_info` 테이블** - `pgtle.feature_info` 테이블은 TLE, 후크, 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>

`pg_tle` 확장이 설치된 RDS for PostgreSQL DB 인스턴스에서 TLE를 사용하여 생성한 확장을 설치할 수 있습니다. `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>

다음 예제는 다양한 공식을 사용하여 거리를 계산하는 몇 가지 SQL 함수가 포함된 `pg_distance`라는 TLE 확장을 생성하는 방법을 보여 줍니다. 목록에서 맨해튼 거리를 계산하는 함수와 유클리드 거리를 계산하는 함수를 찾을 수 있습니다. 이러한 공식의 차이에 대한 자세한 내용은 Wikipedia의 [Taxicab geometry](https://en.wikipedia.org/wiki/Taxicab_geometry)와 [Euclidean geometry](https://en.wikipedia.org/wiki/Euclidean_geometry)를 참조하세요.

[RDS for PostgreSQL DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정](PostgreSQL_trusted_language_extension-setting-up.md)에 설명된 대로 `pg_tle` 확장을 설정한 경우 자체 RDS for PostgreSQL DB 인스턴스에서 이 예제를 사용할 수 있습니다.

**참고**  
이 절차를 수행하려면 `pgtle_admin` 역할의 권한이 있어야 합니다.

**예제 TLE 확장을 생성하는 방법**

다음 단계에서는 `labdb`라는 예제 데이터베이스를 사용합니다. 이 데이터베이스는 `postgres` 기본 사용자가 소유합니다. `postgres` 역할에는 `pgtle_admin` 역할의 권한도 있습니다.

1. `psql`을 사용하여 에 연결합니다. RDS for PostgreSQL DB 인스턴스  

   ```
   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 확장을 테스트하려면 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 설명서에서 [Function Volatility Categories](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 DB 인스턴스에 연결합니다.

   ```
   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>

다른 PostgreSQL 확장과 동일한 방식으로 `DROP EXTENSION` 명령을 사용하여 TLE 확장을 삭제할 수 있습니다. 확장을 삭제해도 확장을 구성하는 설치 파일은 제거되지 않으므로 사용자가 확장을 다시 생성할 수 있습니다. 확장 및 해당 설치 파일을 제거하려면 다음 2단계 프로세스를 수행하세요.

**TLE 확장을 삭제하고 해당 설치 파일을 제거하는 방법**

1. `psql` 또는 다른 클라이언트 도구를 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

   ```
   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 DB 인스턴스에 연결합니다.

   ```
   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 DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정](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` 확인 후크는 켜기, 해제 또는 필수로 설정할 수 있습니다. 사용 가능한 `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` 테이블에 포함된 암호로 암호를 설정하지 못하도록 합니다. 이 테이블에는 가장 일반적으로 사용되지만 쉽게 깰 수 있는 상위 10개 암호가 나와 있습니다.

이 예제를 RDS for PostgreSQL DB 인스턴스에서 설정하려면 신뢰할 수 있는 언어 확장이 이미 설치되어 있어야 합니다. 자세한 내용은 [RDS for PostgreSQL DB 인스턴스에서 신뢰할 수 있는 언어 확장 설정](PostgreSQL_trusted_language_extension-setting-up.md)을 참조하세요.

**암호 확인 후크 예제를 설정하는 방법**

1. `psql`을 사용하여 에 연결합니다. RDS for PostgreSQL DB 인스턴스 

   ```
   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로 작업할 다른 터미널 세션을 엽니다. 암호 확인 후크를 켜려면 사용자 지정 DB 파라미터 그룹을 수정해야 합니다. 이렇게 하려면 다음 예제에서와 같이 [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` 세션을 열고 데이터베이스를 쿼리하여 password\$1check 후크가 켜졌는지 확인합니다.

   ```
   labdb=> SHOW pgtle.enable_password_check;
   pgtle.enable_password_check
   -----------------------------
   on
   (1 row)
   ```

이제 password-check 후크가 활성 상태입니다. 다음 예제와 같이 새 역할을 생성하고 잘못된 암호 중 하나를 사용하여 이를 테스트할 수 있습니다.

```
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` 동작도 password\$1check 후크의 영향을 받는다는 것을 보여 줍니다.

```
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 확장을 생성하거나 업데이트하는 데 필요한 권한은 지정된 데이터베이스에서 다른 객체를 만드는 데 필요한 권한과 동일합니다.
+ `trusted` - TLE 확장의 경우 이 값은 항상 `false`입니다.
+ `relocatable` - TLE 확장의 경우 이 값은 항상 `false`입니다.
+ `schema` - TLE 확장이 설치된 스키마의 이름을 지정합니다.
+ `requires` - 이 TLE 확장에 필요한 다른 확장의 이름을 포함하는 배열입니다.
+ `description` - TLE 확장에 대한 자세한 설명입니다.

출력 값에 대한 자세한 내용은 PostgreSQL 설명서에서 [Packaging Related Objects into an Extension > Extension Files](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 확장에 대한 자세한 내용은 PostgreSQL 설명서에서 [Packaging Related Objects into an Extension](https://www.postgresql.org/docs/current/extend-extensions.html)의 [Extension Files](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` 함수는 지정된 내부 PostgreSQL 기능을 `pgtle.feature_info` 테이블에 추가합니다. 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 확장의 이름입니다. 이 이름은 지정된 데이터베이스에서 사용할 TLE 확장을 로드하기 위해 `CREATE EXTENSION`과 함께 사용되는 이름과 같습니다.

### 출력
<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 확장은 제거하지 않습니다. TLE 확장을 제거하려면 명시적으로 `DROP EXTENSION`을 호출해야 합니다. 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` 함수는 TLE 확장에서 지정된 업데이트 경로를 제거한다는 점에서 `uninstall_update_path`와 비슷합니다. 하지만 업데이트 경로가 존재하지 않는 경우 이 함수는 오류 메시지를 표시하지 않습니다. 대신 함수는 `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 확장에 사용할 수 있는 암호 확인 후크에 대해 알아보려면 다음 설명서를 참조하세요. 클라이언트 인증 후크를 포함하여 사용 가능한 후크에 대한 자세한 내용은 [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(message digest 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`는 암호 확인 후크가 활성 상태인지 여부를 제어합니다. 암호 확인 후크에서 세 가지 설정이 가능합니다.
+ `off` - `passcheck` 암호 확인 후크를 해제합니다. 이것이 기본값입니다.
+ `on` - 테이블과 비교해 암호를 검사할 수 있도록 `passcode` 암호 확인 후크를 켭니다.
+ `require` - 암호 확인 후크를 정의해야 합니다.

### 사용 노트
<a name="passcheck_hook-usage"></a>

`passcheck` 후크를 켜거나 해제하려면 RDS for PostgreSQL DB 인스턴스에 대한 사용자 지정 DB 파라미터 그룹을 수정해야 합니다.

대상 LinuxmacOS, 또는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"
```