Amazon RDS for PostgreSQL에서 "No space left on device” 또는 "DiskFull" 오류 원인을 식별하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2019년 4월 16일

작은 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(Write Ahead Log) 로그
  • 사용되지 않은 복제본 슬롯
  • 너무 오래 보관된 DB 로그(오류 파일)
  • 중지된 교차 리전 읽기 전용 복제본
  • RDS DB 인스턴스의 일관된 상태를 지원하는 다른 DB 또는 Linux 파일

해결 방법

Amazon CloudWatch에서 FreeStorageSpace 지표를 사용하여 DB 스토리지 공간을 모니터링합니다. 여유 스토리지 공간에 대한 Amazon CloudWatch 경보를 설정하여 공간이 줄어들기 시작하면 알림을 수신합니다. 경보를 수신하면 스토리지 문제에 대해 가능성 있는 과거의 원인을 검토할 수 있습니다. 또한 log_temp_files에서 로그를 모니터링하여 임시 파일이 생성된 시점과 방법을 확인하는 것이 좋습니다. DB 인스턴스가 여전히 예상보다 많은 스토리지를 사용하는 경우 다음을 확인합니다.

  • DB 로그 파일 크기
  • 임시 파일의 존재
  • 트랜잭션 로그 디스크 사용량의 지속적 증가
  • 교차 리전 읽기 전용 복제본
  • 작동하지 않는 행의 잘못된 제거 또는 블로트
  • 분리된 파일의 존재

DB 로그 파일 크기 확인

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

임시 파일 확인

임시 파일은 백엔드 또는 세션 연결당 저장되는 파일이며, 리소스 풀 또는 버퍼로 사용됩니다. 이러한 파일은 공유 리소스 공간과는 별도로 저장됩니다. 다음과 비슷하게 후속 명령 실행의 델타를 사용하여 이러한 파일을 검토할 수 있습니다.

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 문서에서 Monitoring Database Activity를 참조하십시오.

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

TransactionLogsDiskUsage에 대한 CloudWatch 지표는 트랜잭션 WAL에서 사용한 디스크 공간을 나타냅니다. 다음 조건은 트랜잭션 로그 디스크 사용량을 늘릴 수 있습니다.

  • 많은 DB 로드(추가 WAL을 생성하는 쓰기 및 업데이트)
  • 가득 찬 스토리지 상태의 읽기 전용 복제본(기본 인스턴스에 트랜잭션 로그 보존)
  • 복제본 슬롯

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

rds.logical_replication 파라미터 값을 1로 설정하면 AWS DMS는 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 및 v11

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
----------------------------------------------------------------+--------------------+--------
xc36ufspjql35djp_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

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

다음과 비슷한 명령을 실행하여 쿼리를 삭제할 수 있습니다.

psql=> select pg_drop_replication_slot('xc36ufspjql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d');

교차 리전 읽기 전용 복제본

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

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

postgres=# select * from pg_replication_slots;

복제본 지연 시간 CloudWatch 지표 및 이벤트 외에도, 소스 인스턴스에서 pg_stat_replication 보기를 사용하여 복제본의 통계를 확인할 수 있습니다. 자세한 내용은 PostgreSQL 문서에서 pg_stat_replication을 참조하십시오.

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

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

작동하지 않는 행이 정리되지 않은 경우 데이터 파일에 그대로 남아 있고(트랜잭션에는 보이지 않음), 디스크 공간에 영향을 미칠 수 있습니다. 테이블에 DELETEUPDATE 작업이 많으면 작동하지 않는 튜플이 많은 디스크 공간을 사용할 수 있으며, 이로 인해 때때로 PostgreSQL에서 블로트라고 하는 상황이 발생합니다.

VACUUM 작업은 작동하지 않는 튜플이 차지하는 스토리지를 재확보할 수 있습니다. 자주 업데이트하는 테이블에서 정기적으로 vacuum 또는 autovacuum 작업을 수행하는 것이 모범 사례입니다. 자세한 내용은 PostgreSQL 문서에서 VACUUM을 참조하십시오.

예상되는 작동하지 않는 튜플 수를 확인하려면 pg_stat_all_tables 보기를 사용합니다. 자세한 내용은 PostgreSQL 문서에서 pg_stat_all_tables view를 참조하십시오. 다음 예제에는 작동하지 않는 튜플이 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.    결과를 기록합니다. 차이가 상당할 것입니다.

객체를 합산하여 얻어진 검색된 데이터베이스 크기와 파일이 차지하는 데이터베이스 크기 사이에 차이가 상당한 경우 분리된 파일이 스토리지 공간을 사용하고 있을 수 있습니다.


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

AWS에서 개선해야 할 부분이 있습니까?


도움이 필요하십니까?