

# 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을 처리할 수 있도록 더 많은 시스템 리소스를 할당하는 것을 고려합니다.