Amazon RDS for PostgreSQL에서 "No space left on device” 또는 "DiskFull" 오류가 발생하는 이유는 무엇입니까?

최종 업데이트 날짜: 2022년 6월 15일

소규모의 Amazon Relational Database Service(Amazon RDS) for PostgreSQL 데이터베이스가 있습니다. 그런데 인스턴스의 스토리지 여유 공간이 줄어들고 다음 오류가 발생했습니다.

"Error message: PG::DiskFull: ERROR: could not extend file "base/16394/5139755": No space left on device. HINT: Check free disk space."

DiskFull 오류를 해결하고 가득 찬 스토리지 문제를 방지하려면 어떻게 해야 합니까?

간략한 설명

Amazon RDS DB 인스턴스 스토리지는 다음 항목에서 사용됩니다.

  • PostgreSQL 트랜잭션으로 생성된 임시 테이블
  • 데이터 파일
  • 미리 쓰기 로그(WAL 로그)
  • 복제본 슬롯
  • 너무 오래 보관된 DB 로그(오류 파일)
  • RDS DB 인스턴스의 일관된 상태를 지원하는 다른 DB 또는 Linux 파일

해결 방법

1.    Amazon CloudWatch에서 FreeStorageSpace 지표를 사용하여 DB 스토리지 공간을 모니터링합니다. 스토리지 여유 공간에 대한 CloudWatch 경보를 설정하면 공간이 줄어들기 시작할 때 알림을 수신합니다. 경보를 수신하면 앞서 언급한 스토리지 문제의 원인을 검토합니다.

2.    DB 인스턴스가 여전히 예상보다 많은 스토리지를 사용하는 경우 다음을 확인합니다.

  • DB 로그 파일 크기
  • 임시 파일의 존재
  • 트랜잭션 로그 디스크 사용량의 지속적 증가
  • 복제본 슬롯:
    • 물리적 복제본 슬롯은 PostgreSQL 14.1 이상 버전에서 실행되는 경우에만 교차 리전 읽기 전용 복제본 또는 동일 리전 읽기 전용 복제본에 의해 생성됩니다.
    • 복제본 또는 구독자에 대해 논리적 복제본 슬롯이 생성됨
  • 작동하지 않는 행의 잘못된 제거 또는 블로트
  • 분리된 파일의 존재

DB 로그 파일 크기 확인

기본적으로 PostgreSQL 오류 로그 파일의 보존 값은 4,320분(3일)입니다. 큰 로그 파일은 워크로드가 크기 때문에 더 많은 공간을 사용할 수 있습니다. DB 인스턴스에 연결된 DB 파라미터 그룹에서 rds.log_retention_period 파라미터를 사용하여 시스템 로그의 보존 기간을 변경할 수 있습니다. 예를 들어, 값을 1,440으로 설정하면 로그는 1일 동안 보존됩니다. 자세한 내용은 PostgreSQL 데이터베이스 로그 파일을 참조하세요.

또한 DB 파라미터 그룹의 오류 보고 및 로깅 파라미터를 변경하여 과도한 로깅을 줄일 수 있습니다. 그러면 로그 파일 크기가 줄어듭니다. 자세한 내용은 오류 보고 및 로깅을 참조하세요.

임시 파일 확인

임시 파일은 백엔드 또는 세션 연결별로 저장되는 파일입니다. 이러한 파일은 리소스 풀로 사용됩니다. 다음과 유사한 명령을 실행하여 임시 파일 통계를 검토합니다.

psql> SELECT datname, temp_files AS "Temporary files",temp_bytes AS "Size of temporary files" FROM pg_stat_database ;

중요: pg_stat_database 보기의 temp_filestemp_bytes 열은 집계(누적)에서 통계를 수집합니다. 이러한 카운터는 서버 시작 시 복구에 의해서만 재설정되므로 이는 의도적으로 설계된 것입니다. 예를 들어 카운터는 즉시 종료, 서버 충돌 또는 시점 복구(PITR) 후에 재설정됩니다. 이러한 이유로 출력만 검토하는 것보다 파일의 개수와 크기 측면에서 이러한 파일의 증가를 모니터링하는 것이 좋습니다.

임시 파일은 정렬, 해시 또는 임시 쿼리 결과에 대해 생성됩니다. 로그 항목은 임시 파일이 삭제될 때 각 임시 파일에 대해 생성됩니다. 단일 쿼리에서 사용하는 임시 공간 생성을 추적하려면 사용자 지정 파라미터 그룹에서 log_temp_files를 설정합니다. 이 파라미터는 임시 파일 이름 및 크기의 로깅을 제어합니다. log_temp_files 값을 0으로 설정하면 모든 임시 파일 정보가 기록됩니다. 파라미터를 양의 값으로 설정하면 지정된 KB 이상인 파일 크기만 기록됩니다. 기본 설정은 -1이며 임시 파일의 로깅을 비활성화합니다.

또한 쿼리의 EXPLAIN ANALYZE를 사용하여 디스크 정렬을 검토할 수 있습니다. 로그 출력을 검토하는 경우 사용자 쿼리로 생성된 임시 파일 크기를 확인할 수 있습니다. 자세한 내용은 PostgreSQL 설명서의 데이터베이스 활동 모니터링을 참조하세요.

트랜잭션 로그 디스크 사용량의 지속적 증가 확인

TransactionLogsDiskUsage에 대한 CloudWatch 지표는 트랜잭션 WAL에서 사용한 디스크 공간을 나타냅니다. 다음과 같은 이유로 트랜잭션 로그 디스크 사용량이 증가할 수 있습니다.

  • 많은 DB 로드(추가 WAL을 생성하는 쓰기 및 업데이트)
  • 스트리밍 읽기 전용 복제본 지연(동일한 리전의 복제본) 또는 스토리지가 가득 찬 상태의 읽기 전용 복제본
  • 복제본 슬롯

복제본 슬롯은 AWS Database Migration Service(AWS DMS)의 논리적 디코딩 기능의 일부로 생성될 수 있습니다. 논리적 복제본의 경우 슬롯 파라미터 rds.logical_replication1로 설정됩니다. 복제본 슬롯은 소비자가 파일을 외부에서 사용할 때까지 WAL 파일을 보존합니다. 예를 들어 pg_recvlogical, ETL(추출, 전환, 적재) 작업 또는 AWS DMS에서 이러한 작업을 사용할 수도 있습니다.

rds.logical_replication 파라미터 값을 1로 설정하면 AWS RDS는 wal_level, max_wal_senders, max_replication_slotsmax_connections 파라미터를 설정합니다. 이러한 파라미터를 변경하면 WAL 생성이 증가할 수 있습니다. 논리 슬롯을 사용하는 경우에만 rds.logical_replication 파라미터를 설정하는 것이 가장 좋습니다. 이 파라미터가 1로 설정되어 있고 논리적 복제본 슬롯이 존재하지만 복제본 슬롯에서 보존하는 WAL 파일의 소비자가 없는 경우 트랜잭션 로그 디스크 사용량이 증가할 수 있습니다. 또한 이로 인해 스토리지 여유 공간도 지속적으로 감소합니다.

다음 쿼리를 실행하여 복제본 슬롯의 존재 여부 및 크기를 확인합니다.

PostgreSQL v9

psql=> select slot_name, pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(),restart_lsn)) as 
replicationSlotLag, active from pg_replication_slots ;

PostgreSQL v10 이상

psql=> select slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) as replicationSlotLag, 
active from pg_replication_slots ;

사용되지 않는 복제본 슬롯(활성 상태가 False)을 식별한 후 다음 쿼리를 실행하여 복제본 슬롯을 삭제합니다.

psql=>select pg_drop_replication_slot('Your_slotname_name');

참고: AWS DMS 태스크가 소비자이고 더 이상 필요하지 않은 경우 그 태스크를 삭제하고 복제본 슬롯을 수동으로 삭제합니다.

샘플 출력:

--------------
                      
slot_name                            | replicationslotlag | active
----------------------------------------------------------------+--------------------+--------
xc36u    jql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d | 129 GB            | f
7pajuy7htthd7sqn_00013322_a27bcebf_7d0f_4124_b336_92d0fb9f5130 | 704 MB             | t
zp2tkfo4ejw3dtlw_00013322_03e77862_689d_41c5_99ba_021c8a3f851a | 624 MB             | t

이 예제에서 슬롯 이름 xc36u    jql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d의 활성 상태는 False입니다. 따라서 이 슬롯은 현재 사용되지 않고, 이로 인해 129GB의 트랜잭션 파일이 사용되고 있습니다.

다음 명령을 실행하여 쿼리를 삭제합니다.

psql=> select pg_drop_replication_slot('xc36u    jql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d');

교차 리전 읽기 전용 복제본

교차 리전 읽기 전용 복제본을 사용하는 경우 물리적 복제본 슬롯이 기본 인스턴스에서 생성됩니다. 교차 리전 읽기 전용 복제본에 장애가 발생하면 기본 DB 인스턴스의 스토리지 공간이 영향을 받을 수 있습니다. 이는 WAL 파일이 읽기 전용 복제본으로 복제되지 않기 때문에 발생합니다. CloudWatch 지표, 가장 오래된 복제 슬롯 지연 및 트랜잭션 로그 디스크 사용량을 사용하여 가장 지연된 복제본보다 얼마나 지연되는지 확인할 수 있습니다. WAL 데이터에 사용되는 스토리지의 양도 확인할 수 있습니다.

교차 리전 읽기 전용 복제본의 상태를 확인하려면 pg_replication_slots를 쿼리합니다. 자세한 내용은 PostgreSQL 설명서의 pg_replication_slots 쿼리를 참조하세요. 활성 상태가 false로 반환되면 현재 복제본에 대해 슬롯이 사용되지 않습니다.

postgres=# select * from pg_replication_slots;

원본 인스턴스에서 pg_stat_replication 보기를 사용하여 복제본에 대한 통계를 확인할 수도 있습니다. 자세한 내용은 PostgreSQL 설명서의 pg_stat_replication을 참조하세요.

작동하지 않는 행(튜플)의 잘못된 제거 또는 블로트

일반적인 PostgreSQL 작업에서 UPDATE로 인해 사용되지 않거나 제거된 튜플은 테이블에서 제거되지 않습니다. MVCC(Multi-Version Concurrency Control) 구현의 경우 DELETE 작업이 수행되면 행은 데이터 파일에서 즉시 제거되지 않습니다. 대신, 행은 헤더에서 xmax 필드를 설정하여 삭제된 항목으로 표시됩니다. 업데이트하면 먼저 행을 삭제할 항목으로 표시하고 삽입 작업을 수행합니다. 이 방법을 사용하면 서로 다른 트랜잭션 간에 잠금을 최소화하는 동시성을 구현할 수 있습니다. 그러면 MVCC 프로세스 중에 서로 다른 행 버전이 유지됩니다.

작동하지 않는 행이 정리되지 않은 경우 데이터 파일에 남아 있지만 트랜잭션에는 보이지 않게 유지되어, 디스크 공간에 영향을 미칠 수 있습니다. 테이블에 DELETEUPDATE 작업이 많으면 작동하지 않는 튜플이 많은 디스크 공간을 사용할 수도 있으며, 이를 때때로 PostgreSQL에서 “블로트”라고 합니다.

VACUUM 작업은 작동하지 않는 튜플이 사용하는 스토리지를 다시 사용할 수 있도록 비울 수 있지만, 이 경우 파일 시스템에 사용 가능한 스토리지가 생기지는 않습니다. VACUUM FULL 을 실행하면 파일 시스템에 사용 가능한 스토리지가 생깁니다. 그러나 VACUUM FULL 실행 중에는 테이블에 액세스 배타적 잠금이 유지됩니다. 또한 이 방법에는 테이블의 새 복사본을 작성하고 작업이 완료될 때까지 이전 복사본을 릴리스하지 않기 때문에 추가 디스크 공간이 필요합니다. 테이블 내에서 상당한 공간을 확보해야 하는 경우에만 이 방법을 사용하는 것이 좋습니다. 자주 업데이트하는 테이블에서 정기적으로 vacuum 또는 autovacuum 작업을 수행하는 것이 좋습니다. 자세한 내용은 PostgreSQL 설명서의 VACUUM을 참조하세요.

예상되는 작동하지 않는 튜플 수를 확인하려면 pg_stat_all_tables 보기를 사용합니다. 자세한 내용은 PostgreSQL 설명서의 pg_stat_all_tables 보기를 참조하세요. 다음 예시에는 작동하지 않는 튜플이 1,999,952개 있습니다(n_dead_tup).

psql => select * from pg_stat_all_tables where relname='test';
-[ RECORD 1 ]-------+------------------------------
relid               | 16395
schemaname          | public
relname             | test
seq_scan            | 3
seq_tup_read        | 5280041
idx_scan            | 
idx_tup_fetch       | 
n_tup_ins           | 2000000
n_tup_upd           | 0
n_tup_del           | 3639911
n_tup_hot_upd       | 0
n_live_tup          | 1635941
n_dead_tup          | 1999952
n_mod_since_analyze | 3999952
last_vacuum         | 
last_autovacuum     | 2018-08-16 04:49:52.399546+00
last_analyze        | 2018-08-09 09:44:56.208889+00
last_autoanalyze    | 2018-08-16 04:50:22.581935+00
vacuum_count        | 0
autovacuum_count    | 1
analyze_count       | 1
autoanalyze_count   | 1


psql => VACUUM TEST;

분리된 파일

분리된 파일은 파일이 데이터베이스 디렉터리에는 있지만, 이 파일을 가리키는 객체가 없는 경우 생길 수 있습니다. 이는 ALTER TABLE, VACUUM FULL 또는 CLUSTER와 같은 작업 중에 인스턴스에 스토리지가 부족하거나 엔진이 충돌하는 경우에 발생할 수 있습니다. 분리된 파일을 확인하려면 다음 단계를 수행합니다.

1.    각 데이터베이스에서 PostgreSQL에 로그인합니다.

2.    이러한 쿼리를 실행하여 사용된 크기와 실제 크기를 평가합니다.

# Size of the database occupied by files

psql=>SELECT pg_size_pretty(pg_database_size('DATABASE_NAME')); 


# Size of database retrieved by summing the objects (real size)
psql=> SELECT pg_size_pretty(SUM(pg_relation_size(oid))) FROM pg_class;

3.    결과를 기록합니다. 차이가 크면 분리된 파일이 스토리지 공간을 사용하고 있을 수도 있습니다.


이 문서가 도움이 되었습니까?


결제 또는 기술 지원이 필요합니까?