명령어/DB

[PostgreSQL] pg_dump 백업, '떴다'로 끝내지 말고 복원까지 검증하기

jykim23 2026. 7. 30. 22:17
반응형

설치·접속: PostgreSQL 설치와 접속

부제: 필요한 테이블만 골라 병렬로 뜨고, 빈 DB에 되살려 행 수까지 맞는지 확인하는 논리 백업 실전

# 핵심 3테이블만 커스텀 포맷(-Fc)으로 백업
pg_dump -Fc -t users -t orders -t products -f /tmp/m8_core.dump shop
ls -la /tmp/m8_core.dump
-rw-rw-r-- 1 postgres postgres 9366 Jul 17 14:45 /tmp/m8_core.dump

-Fc(커스텀 포맷)는 압축·부분 복원·병렬 복원이 되는 실무 기본형이고, -t로 원하는 테이블만 골라 담을 수 있다. 그런데 백업 파일이 생겼다고 안심하면 안 된다. 정말 복원되는지 확인하지 않은 백업은 백업이 아니다. 빈 DB에 되살려 행 수가 원본과 같은지까지 봐야 진짜 검증이다.

createdb m8_verify
pg_restore -d m8_verify -j 2 /tmp/m8_core.dump           # -j 2: 병렬 복원
psql m8_verify -c "SELECT (SELECT count(*) FROM users) AS users,
                          (SELECT count(*) FROM orders) AS orders,
                          (SELECT count(*) FROM products) AS products;"
dropdb m8_verify
 users | orders | products
-------+--------+----------
    50 |    200 |       20

원본 shop의 행 수(users 50, orders 200, products 20)와 정확히 일치한다. 이렇게 별도 DB에 복원해 카운트를 맞춰 보는 절차를 백업 스크립트에 붙여 두면, 어느 날 진짜 복구가 필요할 때 "파일은 있는데 안 열린다"는 최악을 피한다. 논리 백업(pg_dump)은 이렇게 테이블 단위로 유연하게 뜨고 되살리는 게 강점이고, 클러스터 전체를 파일째 복제하는 물리 백업(pg_basebackup)과는 용도가 다르다.

이렇게도 쓴다

디렉토리 포맷으로 CPU를 여러 개 써서 병렬 백업한다. (조합: -Fd -j)

pg_dump -Fd -j 4 shop -f /tmp/m8_shopdir   # 큰 DB를 4배 빠르게

 

특정 대형 테이블만 빼고 나머지를 뜬다. (조합: -T 제외 패턴)

pg_dump -Fc -T 'm5_*' -T 'log_*' shop -f /tmp/core.dump

 

복원 전에 덤프 안에 뭐가 들었는지 목차를 본다. (조합: pg_restore -l)

pg_restore -l /tmp/m8_core.dump | grep 'TABLE DATA'

 

목차에서 원하는 항목만 골라 부분 복원한다. (조합: -L 목록 파일)

pg_restore -l /tmp/m8_core.dump > toc.txt   # 필요없는 줄 삭제 후
pg_restore -L toc.txt -d target /tmp/m8_core.dump

 

데이터는 빼고 스키마 틀만 떠서 테스트 DB를 만든다. (조합: --schema-only)

pg_dump --schema-only shop | psql -d shop_test

 

날짜별 압축 파일로 cron에 얹는다. (조합: date + cron)

0 3 * * * pg_dump -Fc shop -f /backup/shop_$(date +\%F).dump
반응형