Categories
Database Backup

**

프로덕션 환경에서 PostgreSQL을 관리하는 데이터베이스 관리자(DBA)와 DevOps 엔지니어에게 0에 가까운 복구 시점 목표(RPO)를 달성하는 것은 최우선 과제입니다. PostgreSQL의 재해 복구 및 시점 복구(PITR) 기능의 핵심은 WAL(Write-Ahead Logging)입니다. WAL은 데이터 파일에 기록되기 전에 트랜잭션을 로깅하여 ACID 준수를 보장하며, WAL 아카이빙(archiving)은 장기 백업 및 복제를 위해 이러한 로그를 보존하는 메커니즘입니다.

그러나 WAL 아카이빙 설정은 한 번 설정하고 잊어버려도 되는 작업이 아닙니다. 잘못된 구성, 조용한 실패(silent failure), 아키텍처에 대한 오해는 치명적인 데이터 손실, 스플릿 브레인(split-brain) 시나리오 또는 완전한 데이터베이스 중단으로 이어질 수 있습니다.

이 종합 가이드에서는 PostgreSQL WAL 아카이빙 아키텍처를 살펴보고, 데이터 손실을 초래하는 가장 일반적인 함정을 식별하며, 데이터베이스의 복원력을 유지하기 위한 프로덕션급 모범 사례를 설명합니다.

PostgreSQL WAL 아키텍처 이해

함정을 살펴보기 전에 PostgreSQL이 트랜잭션 로그를 처리하는 방식을 이해하는 것이 중요합니다.

PostgreSQL은 모든 수정 사항을 pg_wal 디렉토리(버전 10 이전에는 pg_xlog)에 위치한 WAL 세그먼트(기본값 16MB 파일)에 기록합니다. 모든 트랜잭션은 LSN(Log Sequence Number)으로 표시되어 순차적으로 기록됩니다.

WAL 세그먼트가 가득 차면 PostgreSQL은 새 세그먼트로 전환합니다. pg_wal 디렉토리가 무한정 커지는 것을 방지하기 위해, PostgreSQL은 충돌 복구나 복제에 더 이상 필요하지 않은 오래된 WAL 세그먼트를 재활용하거나 제거합니다.

WAL 아카이빙은 이 재활용 프로세스를 가로챕니다. archive_mode가 활성화되면 PostgreSQL은 사용자 정의 archive_command를 실행하거나(PostgreSQL 15 이상에서는 archive_library 활용) 완료된 WAL 세그먼트를 삭제하거나 덮어쓰기 전에 안전한 보조 위치로 복사합니다.

시점 복구(PITR)를 수행하려면 다음 두 가지 구성 요소가 필요합니다.
1. 유효한 베이스 백업.
2. 베이스 백업 시점부터 목표 복구 시간까지의 끊김 없는 아카이브된 WAL 파일 체인.

WAL 체인이 끊기면 PITR은 실패합니다.

프로덕션을 위한 WAL 아카이빙 구성

WAL 아카이빙을 활성화하려면 postgresql.conf 파일을 수정해야 합니다. 기본 구성에는 wal_level 설정, archive_mode 활성화, archive_command 정의가 필요합니다.

# postgresql.conf
wal_level = replica             # 아카이빙을 위해서는 'replica' 또는 'logical'이 필요함
archive_mode = on               # 아카이버 프로세스 활성화
archive_command = 'test ! -f /mnt/nfs/archive/%f && cp %p /mnt/nfs/archive/%f'
archive_timeout = 600           # 10분마다 강제로 WAL 전환

archive_command에서:
* %p는 아카이브할 WAL 파일의 전체 경로를 나타냅니다.
* %f는 WAL 파일의 파일 이름을 나타냅니다.

위의 구성은 간단해 보이지만, 엔터프라이즈 환경에서 단순한 쉘 명령에 의존하는 것은 상당한 위험을 초래합니다.

WAL 아카이빙의 일반적인 함정

함정 1: archive_command의 “조용한 성공(Silent Success)”

PostgreSQL은 전적으로 archive_command의 종료 코드에 의존합니다. 명령이 0을 반환하면 PostgreSQL은 WAL 파일이 안전하게 아카이브되었다고 가정하고 원본 파일을 재활용합니다.

흔한 실수는 데이터가 영구 저장소에 안전하게 플러시되지 않았음에도 0을 반환하는 명령을 사용하는 것입니다. 예를 들어, 단순한 cp 명령은 데이터가 대상 서버의 OS 페이지 캐시에 도달하자마자 성공을 반환할 수 있습니다. 캐시가 디스크에 플러시되기 전에 대상 서버의 전원이 꺼지면 WAL 파일은 손실되지만, PostgreSQL은 이미 로컬 복사본을 삭제한 상태가 됩니다.

위험: 재해 복구 시나리오에서만 발견되는 WAL 체인 단절 및 PITR 수행 불가능.

완화 방법: 아카이빙 스크립트가 동기식 쓰기를 강제하도록 합니다. 표준 쉘 명령을 사용하는 경우 데이터 플러시를 보장하는 도구를 활용하거나, 전송 후 파일 크기와 체크섬을 확인하는 래퍼 스크립트를 작성하십시오.

함정 2: pg_wal 파티션 소진 (WAL Bloat)

네트워크 중단, 잘못된 권한 또는 대상 디스크가 가득 차서 archive_command가 실패(0이 아닌 종료 코드 반환)하면, PostgreSQL은 pg_wal 디렉토리에 WAL 파일을 유지하고 명령을 무기한 재시도합니다.

이는 아카이브되지 않은 WAL을 삭제하지 않음으로써 데이터 손실을 방지하지만, 심각한 가용성 위험을 초래합니다. pg_wal 디렉토리가 100% 가득 찬 파티션에 있으면 PostgreSQL은 PANIC을 발생시키고 충돌합니다. 공간이 확보될 때까지 데이터베이스는 다시 시작되지 않습니다.

위험: pg_wal 파티션이 가득 차서 발생하는 완전한 데이터베이스 중단.

완화 방법:
1. 항상 pg_wal을 전용 디스크 파티션에 배치하십시오.
2. pg_wal 디렉토리 크기에 대한 적극적인 모니터링을 구현하십시오.
3. pg_stat_archiver 뷰를 모니터링하여 실패하는 아카이브 명령을 즉시 감지하십시오.

함정 3: 불완전한 베이스 백업

베이스 백업은 백업 프로세스 중에 생성된 WAL 파일 없이는 쓸모가 없습니다. 파일 시스템 수준의 스냅샷을 찍거나 WAL 스트리밍(-X stream) 없이 pg_basebackup을 사용하는 경우, 백업 시작과 종료 사이에 생성된 WAL 파일이 성공적으로 아카이브되었는지 확인해야 합니다.

아카이버가 지연되거나 실패하여 해당 특정 WAL 파일이 손실되면 베이스 백업을 일관된 상태로 복구할 수 없습니다.

위험: 손상되었거나 복구 불가능한 베이스 백업.

완화 방법: pg_basebackup -X stream을 사용하여 백업 페이로드 자체에 필요한 WAL 파일을 포함하거나, 베이스 백업과 WAL 세그먼트 간의 종속성을 자동으로 관리하는 엔터프라이즈 백업 솔루션을 활용하십시오.

함정 4: 타임라인 혼동 및 스플릿 브레인 시나리오

대기 서버가 기본 서버로 승격되면 PostgreSQL은 “타임라인 ID”(WAL 파일 이름의 첫 부분, 예: 0000000200000001000000A4)를 증가시킵니다. 이는 새 기본 서버가 이전 기본 서버의 WAL 기록을 덮어쓰는 것을 방지합니다.

그러나 이전 기본 서버가 적절한 펜싱(fencing) 없이 실수로 시작되면(스플릿 브레인 시나리오), 이전 타임라인을 사용하여 동일한 아카이브 위치로 WAL 파일을 푸시하려고 시도할 수 있습니다. archive_command가 파일을 무분별하게 덮어쓰면 아카이브 저장소가 손상될 수 있습니다.

위험: 덮어쓰여진 WAL 파일, 손상된 아카이브 및 복구 불가능한 데이터베이스.

완화 방법: archive_command는 기존 파일을 절대로 덮어쓰지 않아야 합니다. 앞서 언급한 기본 구성에서 test ! -f /mnt/nfs/archive/%f를 사용하여 파일이 이미 존재하면 명시적으로 실패하도록 설정한 점을 참고하십시오.

데이터 손실 위험 완화: 프로덕션 모범 사례

PostgreSQL 아카이빙 전략을 강화하려면 다음 모범 사례를 구현하십시오.

1. 아카이버 프로세스 네이티브 모니터링

PostgreSQL은 아카이빙 프로세스의 성공 및 실패를 추적하는 내장 뷰 pg_stat_archiver를 제공합니다. 이 뷰를 관찰 가능성 스택(예: Prometheus, Datadog 또는 Zabbix)에 통합해야 합니다.

SELECT 
    archived_count,
    last_archived_wal,
    last_archived_time,
    failed_count,
    last_failed_wal,
    last_failed_time,
    stats_reset
FROM pg_stat_archiver;

구성할 경고 임계값:
* failed_count가 증가하면 경고.
* now()last_archived_time의 차이가 RPO 임계값(예: 15분)을 초과하면 경고. 단, archive_timeout이 설정되지 않은 경우 트래픽이 적은 데이터베이스는 자연스럽게 지연이 발생할 수 있음을 유의하십시오.

2. archive_timeout 활용

쓰기 볼륨이 낮은 데이터베이스에서는 16MB WAL 파일이 채워지는 데 몇 시간이 걸릴 수 있습니다. 채워지기 전까지는 아카이브되지 않습니다. 서버가 충돌하고 로컬 디스크가 손실되면 몇 시간 분량의 트랜잭션을 잃게 됩니다.

archive_timeout = 600(10분)을 설정하면 WAL 파일이 가득 차지 않았더라도 PostgreSQL이 새 WAL 파일로 전환하고 현재 파일을 아카이브하도록 강제합니다. 이는 부분적으로 채워진 WAL 파일로 인해 저장소 사용량이 약간 증가하는 대신, RPO가 10분을 초과하지 않도록 보장합니다.

3. archive_library로 전환 (PostgreSQL 15+)

과거에는 archive_command가 모든 단일 WAL 파일에 대해 새로운 쉘 프로세스를 생성했습니다. 분당 수백 개의 WAL 파일을 생성하는 고처리량 환경에서는 쉘 프로세스를 포크(fork)하는 오버헤드가 성능 병목 현상이 됩니다.

PostgreSQL 15는 archive_library 매개변수를 도입하여 동적으로 로드된 C 모듈이 WAL 아카이빙을 처리할 수 있게 했습니다. 이는 쉘 포크 오버헤드를 제거하고 훨씬 더 강력하고 고성능인 아카이빙 메커니즘을 제공합니다. PostgreSQL 15 이상을 사용하는 경우 사용자 정의 아카이브 모듈을 지원하는 백업 도구를 찾으십시오.

4. 정기적인 시점 복구 테스트

테스트되지 않은 백업은 백업이 아니라 희망 사항일 뿐입니다. WAL 아카이빙이 올바르게 작동하고, WAL 체인이 끊기지 않았으며, 베이스 백업이 일관된지 확인하는 유일한 방법은 정기적이고 자동화된 PITR 테스트를 수행하는 것입니다.

임시 인스턴스를 가동하고, 베이스 백업을 복원하고, restore_command를 구성하여 아카이브에서 가져오도록 한 다음 특정 타임스탬프로 복구하십시오. 데이터베이스가 일관된 상태에 도달하고 연결을 허용하는지 확인하십시오.

CloudSave를 통한 엔터프라이즈 백업 및 복구

archive_command를 위한 사용자 정의 쉘 스크립트 관리, WAL 중복 제거 처리, 트랜잭션 로그를 위한 안전한 오프사이트 저장소 보장은 IT 팀에게 운영상의 부담이 될 수 있습니다.

이 지점에서 CloudSave는 엔터프라이즈 PostgreSQL 환경에 상당한 가치를 제공합니다. CloudSave는 PostgreSQL의 네이티브 백업 및 WAL 아카이빙 API와 직접 통합되어 위에서 논의한 수동 함정을 제거합니다.

취약한 bash 스크립트를 작성하는 대신, CloudSave는 다음과 같은 강력한 에이전트 기반 또는 에이전트리스 통합을 제공합니다:
* 전송 보장: 표준 쉘 명령을 안전한 오프사이트 또는 클라우드 저장소로의 검증된 체크섬 검증 전송으로 대체합니다.
* WAL Bloat 방지: pg_wal 디렉토리를 능동적으로 모니터링하고 파티션이 소진되기 훨씬 전에 관리자에게 경고합니다.
* PITR 자동화: 직관적인 인터페이스를 통해 시점 복구를 간소화합니다. 복구하려는 정확한 분을 선택하면 CloudSave가 자동으로 올바른 베이스 백업을 검색하고 해당 상태에 도달하는 데 필요한 정확한 WAL 파일 시퀀스를 스트리밍합니다.
* 타임라인 처리: PostgreSQL 타임라인 기록을 지능적으로 관리하여 장애 조치 및 스플릿 브레인 시나리오가 백업 저장소를 손상시키지 않도록 합니다.

WAL 관리의 무거운 작업을 CloudSave로 오프로드함으로써 DBA는 RPO 및 RTO SLA가 엔터프라이즈급 플랫폼에 의해 보호된다는 사실을 알고 쿼리 최적화 및 데이터베이스 성능에 집중할 수 있습니다.

결론

PostgreSQL WAL 아카이빙은 데이터베이스 재해 복구의 중추입니다. 한 디렉토리에서 다른 디렉토리로 파일을 복사하는 개념은 간단해 보이지만, 조용한 실패, 디스크 소진, 타임라인 분기 등의 엣지 케이스는 데이터 무결성에 심각한 위험을 초래합니다.

pg_wal의 아키텍처를 이해하고, 파괴적인 archive_command 구성을 엄격히 피하며, pg_stat_archiver를 모니터링하고, CloudSave와 같은 엔터프라이즈 백업 플랫폼을 활용함으로써 하드웨어 장애, 인적 오류, 치명적인 중단 상황에서도 커밋된 트랜잭션을 하나도 잃지 않고 생존할 수 있는 탄력적인 PostgreSQL 인프라를 구축할 수 있습니다.

데이터 손실을 초래하는 PostgreSQL WAL 아카이빙의 일반적인 함정을 알아보세요. 전문가 DBA 모범 사례, 구성 팁, 엔터프라이즈 데이터베이스를 위한 안정적인 시점 복구(PITR) 보장 방법을 배울 수 있습니다.