Skip to content
VDS · 데이터베이스

데이터베이스 백업

MySQL과 PostgreSQL 덤프를 예약하고, 머신 외부로 옮기고, 백업이 실제로 복원되는지 확인하는 방법이에요.

업데이트 2026년 8월 23일

VPS에는 자동 머신 백업이나 상태 스냅샷이 없어요. 직접 복사하지 않은 데이터는 단일 인스턴스에만 존재하죠. 데이터베이스 덤프를 가장 먼저 설정해야 하는데, 데이터를 복원할 곳이 어디에도 없는 반면 사이트는 처음부터 다시 배포할 수 있기 때문이에요.

수동 덤프

PostgreSQL:

pg_dump -Fc -U shop -h 127.0.0.1 shop > /srv/backups/shop-$(date +%F).dump
pg_dumpall -U postgres --roles-only > /srv/backups/roles.sql

MySQL과 MariaDB:

mysqldump --single-transaction --quick --routines --events \
  -u root shop | gzip > /srv/backups/shop-$(date +%F).sql.gz

--single-transaction은 테이블을 잠그지 않고 일관된 InnoDB 덤프를 생성해요. 이 옵션이 없으면 내보내는 동안 사이트가 멈춰요. PostgreSQL의 -Fc 포맷은 압축되며 개별 테이블을 복원할 수 있어요.

비밀번호를 명령줄에 넣지 마세요. ~/.pgpass 또는 ~/.my.cnf를 600 권한으로 만드세요.

예약 실행

mkdir -p /srv/backups && chmod 700 /srv/backups
crontab -e
20 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1

/usr/local/bin/db-backup.sh 스크립트:

#!/bin/bash
set -euo pipefail
DEST=/srv/backups
STAMP=$(date +%F-%H%M)
pg_dump -Fc -U shop -h 127.0.0.1 shop > "$DEST/shop-$STAMP.dump.tmp"
mv "$DEST/shop-$STAMP.dump.tmp" "$DEST/shop-$STAMP.dump"
find "$DEST" -name '*.dump' -mtime +14 -delete

임시 파일에 쓴 뒤 이름을 바꾸는 게 중요해요. 덤프가 중단되더라도 잘린 파일을 완전한 백업으로 착각하지 않게 해줘요. set -euo pipefail은 조용히 계속 진행하는 대신 첫 오류에서 스크립트를 멈춰요.

백업을 머신 밖으로 옮기기

같은 디스크에 있는 사본은 마이그레이션 실수, 랜섬웨어, 또는 “액세스” 탭에서의 OS 재설치로부터 지켜주지 않아요. 덤프를 외부로 보내세요:

rsync -az --delete /srv/backups/ backup@other-host:/store/vds/

또는 rclone을 통해 S3 호환 스토리지로 보내도 돼요. 최대 500 Mbit/s의 대역폭과 티어별 디스크 쓰기 제한인 코어당 60 MB/s를 염두에 두세요.

복원 확인

한 번도 복원해보지 않은 백업은 백업이 아니에요.

createdb -U postgres shop_check
pg_restore -U postgres -d shop_check /srv/backups/shop-2026-08-23.dump
psql -U postgres -d shop_check -c "SELECT count(*) FROM users;"
dropdb -U postgres shop_check

MySQL의 경우: gunzip -c dump.sql.gz | mysql -u root shop_check.

한 달에 한 번 실행하고 확인 날짜를 기록하세요.

흔한 실수

증상원인
덤프가 몇 킬로바이트에 불과함스크립트가 인증 단계에서 실패했고 오류가 /dev/null로 사라짐
디스크 공간 부족mtime 기준으로 오래된 백업을 삭제하지 않음
권한 문제로 복원 실패역할이 덤프되지 않음 — --roles-only가 필요함
Cron이 조용하고 백업이 없음Cron에 PATH가 없음 — 절대 경로를 사용하세요
밤에 사이트가 느려짐덤프가 디스크를 두고 경쟁함 — 시간을 옮기고 --quick을 추가하세요

서로 다른 위치에 최소 두 개의 사본을 유지하고 덤프 크기를 모니터링하세요. 크기가 급격히 줄어들면 전체 데이터베이스가 덤프되지 않았다는 뜻이에요.