Fullmoon System

PostgreSQL 백업 복원 검증: 역할·확장·시퀀스까지 확인하는 절차

AI Editter

백업 파일이 있고 pg_restore가 끝났는데 앱에서 permission denied가 나거나 신규 등록 때 기본키 충돌이 난다면 복원 검사가 덜 끝난 상태입니다. 데이터 행뿐 아니라 역할·소유권·확장·시퀀스와 앱의 연결 설정도 확인해야 합니다.

여기서는 직접 관리하는 PostgreSQL의 논리 백업을 별도 시험 DB에 복원하는 상황을 다룹니다. 실행 중인 운영 DB에 덮어쓰는 절차가 아닙니다. 관리형 DB는 권한과 지원 확장에 제약이 있으므로 제공자 문서를 추가로 확인합니다.

pg_dump가 담는 범위부터 확인

한 DB의 pg_dump와 클러스터 전체의 역할·테이블스페이스 설정은 범위가 다릅니다. pg_dump 문서와 pg_dumpall 문서를 기준으로 필요한 백업을 구분합니다.

대상준비할 자료
DB 스키마·데이터해당 DB의 논리 백업
역할·권한 관계필요한 역할 정의와 멤버십
확장설치 가능한 확장 버전·외부 파일
앱 연결호스트·DB명·사용자·TLS·비밀 저장소
DB 밖 파일업로드·첨부·외부 객체와 일관된 시점
시점 복구별도의 물리 백업·WAL 보존 설계

논리 백업 파일 하나로 임의의 과거 시각까지 PITR할 수 있다고 가정하지 않습니다. 복구 목표에 따라 백업 방식 자체가 달라집니다.

덤프 생성과 목록 확인

다음은 libpq 연결 서비스가 미리 설정된 환경의 예시입니다. service 이름은 각 환경에서 정의해야 하며 비밀번호를 명령행에 쓰지 않습니다.

pg_dump --dbname=service=backup_source \
  --format=custom --file=app-backup.dump
pg_restore --list app-backup.dump

pg_dump 종료 코드를 검사하고 파일 크기·해시·생성 시각·서버 버전을 함께 기록합니다. 목록 조회는 파일을 읽을 수 있다는 검사이지 전체 복원 성공을 증명하지 않습니다.

클라이언트와 서버 버전 호환도 확인합니다. 특히 더 최신 서버를 오래된 pg_dump로 백업하려고 하면 지원되지 않을 수 있습니다. 마이그레이션이라면 대상 주요 버전의 호환성 시험을 따로 수행합니다.

역할과 확장을 준비한 시험 DB에 복원

새롭고 비어 있는 시험 DB를 준비합니다. 실제 소유권·ACL을 유지할 시험이면 필요한 역할을 먼저 만들고, 다른 소유자로 단순 복원할 시험이면 no-owner·no-acl의 의미를 명시적으로 선택합니다. 권한을 생략한 복원 결과로 운영 권한이 검증됐다고 말할 수는 없습니다.

pg_restore --dbname=service=restore_target \
  --exit-on-error --single-transaction app-backup.dump

restore_target이 운영 DB가 아닌지 접속 정보와 DB 이름으로 확인한 뒤 실행합니다. 단일 트랜잭션은 실패 시 부분 복원을 피하는 데 유용하지만 대용량 복원의 시간·자원·잠금 특성은 따로 검토해야 합니다. pg_restore 옵션에 따라 병렬 복원 등과 조합 제약도 있습니다.

복원 후 조회할 항목

SELECT extname, extversion
FROM pg_extension ORDER BY extname;

SELECT schemaname, tablename, tableowner
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;

핵심 테이블의 정확한 건수, 날짜 범위, 금액 합계, 최근 업무 ID를 원본 백업 기준값과 비교합니다. 통계의 추정 행 수를 정확한 건수와 혼동하지 않습니다. 대형 DB는 모든 집계 비용을 고려해 핵심 영역부터 검증하되 검사 범위를 기록합니다.

앱 계정으로 연결해 SELECT뿐 아니라 시험 데이터 INSERT·UPDATE·DELETE를 수행합니다. 관리자 계정의 성공은 앱 권한의 성공을 대신하지 않습니다.

시퀀스는 실제 쓰기 시험에서 드러난다

정상적인 전체 논리 백업에는 시퀀스 상태도 포함될 수 있지만 부분 복원·수동 적재·일부 객체 제외가 있었다면 데이터 최대 ID와 시퀀스가 어긋날 수 있습니다.

SELECT pg_get_serial_sequence('public.orders', 'id');

테이블·컬럼 이름을 실제 값으로 바꿉니다. 연결된 시퀀스를 확인한 뒤 데이터 범위와 설정을 비교합니다. 운영 중 MAX(id)만 읽어 무조건 setval을 실행하면 동시 쓰기와 충돌할 수 있으므로 일괄 보정 명령을 그대로 적용하지 않습니다.

시험 DB에서 새 행을 넣었을 때 키가 충돌하지 않는지, 앱이 ID를 반환받고 관련 행을 생성하는지 검사합니다. 트랜잭션을 롤백해도 시퀀스 증가가 되돌아가지 않는 점을 감안해 번호 공백 자체를 복원 실패로 판단하지 않습니다.

복구 시간을 측정하는 마지막 단계

복원 명령 실행 시간뿐 아니라 파일 다운로드, 역할·확장 준비, 검증, 앱 접속 전환까지 시간을 측정합니다. 메일·결제·웹훅이 나가지 않는 격리된 시험 환경에서 진행합니다.

복원 보고서에는 백업 시각, 검증한 데이터 범위, 누락한 외부 자원, 실제 소요 시간, 실패했던 항목을 남깁니다. 다음 장애 때 필요한 것은 “백업 성공” 알림보다 이 자료를 따라 복구할 수 있다는 증거입니다.

관련 절차: PostgreSQL 느린 쿼리 분석: EXPLAIN ANALYZE를 읽는 순서