DeployEasy
Menu
ProductionTrung bình

Backup và restore PostgreSQL production bằng pg_dump

Hướng dẫn backup PostgreSQL bằng pg_dump, định dạng custom, pg_restore, lịch cron, kiểm tra restore và lưu bản sao ngoài VPS.

· 7 phút đọc · 1.517 từ
Mục lục bài viết

Backup database không hoàn thành khi một file .dump được tạo ra. Một hệ thống backup đáng tin cậy phải trả lời được:

Backup có chạy không?
File có đầy đủ không?
Lưu ở đâu?
Giữ bao lâu?
Ai nhận cảnh báo?
Restore mất bao lâu?
Đã thử restore chưa?

Các phương pháp backup PostgreSQL

Tài liệu PostgreSQL chia ba hướng chính:

  1. SQL dump.
  2. File system level backup.
  3. Continuous archiving và point-in-time recovery.

Bài này tập trung vào pg_dump, phù hợp nhiều dự án vừa và nhỏ.

pg_dump là gì?

pg_dump xuất một database thành script SQL hoặc archive.

Ưu điểm:

  • Không cần dừng database.
  • Có thể chuyển giữa kiến trúc máy.
  • Thường restore được sang PostgreSQL mới hơn.
  • Có thể chọn schema/table.
  • Dễ dùng.

Hạn chế:

  • Restore database lớn có thể lâu.
  • Không cung cấp PITR một mình.
  • Chỉ dump một database.
  • Global roles cần xử lý riêng.

Kiểm tra phiên bản

psql --version
pg_dump --version

Kiểm tra server:

SELECT version();

Nên dùng pg_dump có version tương thích với server.

Các định dạng

Plain SQL

pg_dump database_name > backup.sql

Restore:

psql database_name < backup.sql

Dễ đọc nhưng ít linh hoạt hơn.

Custom format

pg_dump -Fc database_name > backup.dump

Restore bằng pg_restore.

Custom format hỗ trợ lựa chọn object và quy trình restore linh hoạt.

Directory format

pg_dump -Fd -j 4 -f backup_dir database_name

Có thể dump và restore song song.

Backup cơ bản

pg_dump \
  -U deployeasy \
  -h 127.0.0.1 \
  -p 5432 \
  -Fc \
  -d deployeasy \
  -f deployeasy.dump

Tránh đưa password trực tiếp trong command line.

Có thể dùng:

  • .pgpass.
  • User backup riêng.
  • Secret manager.
  • Peer authentication phù hợp.

File .pgpass

~/.pgpass

Format:

hostname:port:database:username:password

Ví dụ:

127.0.0.1:5432:deployeasy:backup_user:SECRET

Permission:

chmod 600 ~/.pgpass

Không commit file này.

User backup

Nguyên tắc:

  • User riêng.
  • Chỉ cấp quyền cần.
  • Password riêng.
  • Không dùng superuser nếu không cần.
  • Test dump đủ schema và dữ liệu.

Nếu thiếu quyền, dump có thể lỗi hoặc thiếu object.

Script backup

Tạo:

sudo nano /usr/local/bin/backup-deployeasy-postgres
#!/usr/bin/env bash

set -Eeuo pipefail

BACKUP_DIR="/var/backups/deployeasy-postgres"
DATABASE_HOST="127.0.0.1"
DATABASE_PORT="5432"
DATABASE_NAME="deployeasy"
DATABASE_USER="backup_user"

TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
OUTPUT="$BACKUP_DIR/${DATABASE_NAME}-${TIMESTAMP}.dump"
TEMP_OUTPUT="${OUTPUT}.tmp"

mkdir -p "$BACKUP_DIR"

pg_dump \
  --host="$DATABASE_HOST" \
  --port="$DATABASE_PORT" \
  --username="$DATABASE_USER" \
  --dbname="$DATABASE_NAME" \
  --format=custom \
  --file="$TEMP_OUTPUT"

mv "$TEMP_OUTPUT" "$OUTPUT"

find "$BACKUP_DIR" \
  -type f \
  -name "${DATABASE_NAME}-*.dump" \
  -mtime +14 \
  -delete

echo "Backup created: $OUTPUT"

Permission:

sudo chmod 750 /usr/local/bin/backup-deployeasy-postgres

Dùng file tạm rồi rename giúp tránh coi file dở dang là backup hợp lệ.

Chạy thử

/usr/local/bin/backup-deployeasy-postgres

Kiểm tra:

ls -lh /var/backups/deployeasy-postgres
file /var/backups/deployeasy-postgres/*.dump

Xem nội dung archive

pg_restore --list backup.dump | less

Đây chưa phải bằng chứng restore hoàn chỉnh, nhưng giúp xác nhận archive có mục lục.

Lên lịch cron

crontab -e

Chạy 02:30 mỗi ngày:

30 2 * * * /usr/local/bin/backup-deployeasy-postgres >> /var/log/deployeasy-backup.log 2>&1

Cron có PATH hạn chế; dùng đường dẫn tuyệt đối nếu cần.

Systemd timer là lựa chọn khác với log và trạng thái rõ hơn.

Không lưu duy nhất trên VPS

Nếu VPS bị xóa hoặc ổ đĩa hỏng, backup cùng máy cũng mất.

Mô hình đơn giản:

Database production
Backup local ngắn hạn
Backup object storage hoặc máy khác

Có thể tham khảo nguyên tắc 3-2-1:

3 bản dữ liệu
2 loại phương tiện
1 bản ở vị trí khác

Backup trong Docker Compose

mkdir -p backups

docker compose exec -T database \
  pg_dump \
  -U deployeasy \
  -d deployeasy \
  -Fc \
  > "backups/deployeasy-$(date +%Y%m%d-%H%M%S).dump"

-T tắt pseudo-TTY, phù hợp với binary archive.

Restore vào database test

Tạo database:

createdb \
  -U postgres \
  deployeasy_restore_test

Restore:

pg_restore \
  -U postgres \
  -d deployeasy_restore_test \
  --clean \
  --if-exists \
  backup.dump

--clean drop object trước khi tạo. Chỉ dùng trên database test hoặc khi hiểu tác động.

Restore plain SQL

createdb deployeasy_restore_test
psql deployeasy_restore_test < backup.sql

Restore trong Docker

docker compose exec database \
  createdb \
  -U deployeasy \
  deployeasy_restore_test
docker compose exec -T database \
  pg_restore \
  -U deployeasy \
  -d deployeasy_restore_test \
  --clean \
  --if-exists \
  < backup.dump

Không test trực tiếp vào production.

Kiểm tra restore

Không chỉ nhìn exit code.

Kiểm tra:

SELECT COUNT(*) FROM users;
SELECT COUNT(*) FROM orders;

So sánh:

  • Số bảng.
  • Row count quan trọng.
  • Index.
  • Constraint.
  • Function.
  • Sequence.
  • Permission.
  • Smoke test ứng dụng.

Cách tốt là chạy staging bằng database vừa restore.

Roles và global objects

pg_dump không dump toàn bộ global objects như roles.

Dùng:

pg_dumpall --globals-only > globals.sql

File có thể chứa thông tin nhạy cảm. Bảo vệ và review trước khi restore.

Backup toàn cluster

pg_dumpall > cluster.sql

Phù hợp một số hệ thống nhỏ nhưng ít linh hoạt và có thể rất lớn.

Compression

Plain SQL:

pg_dump deployeasy | gzip > deployeasy.sql.gz

Restore:

gunzip -c deployeasy.sql.gz | psql deployeasy_restore_test

Custom format đã có cơ chế compression theo tùy chọn/version; không cần nén hai lần nếu không có lý do.

Mã hóa backup

Nếu backup chứa dữ liệu nhạy cảm:

  • Dùng công cụ mã hóa được phê duyệt.
  • Lưu khóa tách khỏi backup.
  • Có quy trình khôi phục khóa.
  • Test decrypt.
  • Rotate key.

Backup mã hóa mà mất khóa cũng là mất dữ liệu.

Retention

Ví dụ:

Daily:  14 bản
Weekly: 8 bản
Monthly: 12 bản

Chọn theo:

  • Dung lượng.
  • Quy định.
  • Tốc độ thay đổi.
  • RPO.
  • Chi phí.

Không chỉ giữ một bản mới nhất vì lỗi logic có thể đã tồn tại trước lúc backup.

RPO và RTO

RPO

Lượng dữ liệu tối đa chấp nhận mất.

Backup mỗi 24 giờ có thể dẫn tới RPO gần 24 giờ.

RTO

Thời gian mục tiêu để khôi phục dịch vụ.

Nếu restore thực tế mất 4 giờ thì không thể chỉ ghi RTO 15 phút mà chưa thay kiến trúc.

Point-in-time recovery

Nếu cần phục hồi tới một thời điểm cụ thể, pg_dump định kỳ chưa đủ. Cần xem:

  • WAL archive.
  • Base backup.
  • Continuous archiving.
  • PITR.
  • Monitoring archive.
  • Restore test.

Managed database có PITR có thể giảm việc vận hành, nhưng vẫn phải hiểu retention và quy trình restore.

Backup trước migration

Trước migration quan trọng:

  1. Chạy backup.
  2. Xác minh file.
  3. Copy offsite.
  4. Test migration trên bản restore.
  5. Đo lock và thời gian.
  6. Chuẩn bị rollback/forward fix.

Backup không làm migration tự động an toàn.

Monitoring backup

Theo dõi:

  • Exit code.
  • File mới nhất.
  • Kích thước bất thường.
  • Upload offsite.
  • Dung lượng storage.
  • Restore test gần nhất.
  • Thời gian chạy.

File 0 byte hoặc nhỏ bất thường phải tạo cảnh báo.

Lỗi thường gặp

Version mismatch

Dùng client pg_dump phù hợp hoặc mới hơn theo khả năng hỗ trợ.

Permission denied

Backup user thiếu quyền.

Backup quá nhỏ

Kiểm tra log, database name, schema và pg_restore --list.

Restore thiếu role

Dump global objects hoặc tạo role trước.

Object already exists

Dùng database trống hoặc --clean --if-exists sau khi hiểu tác động.

Hết ổ đĩa

df -h
du -sh /var/backups/*

Không để backup làm đầy production disk.

Checklist

[ ] Xác định RPO và RTO
[ ] Dùng custom format
[ ] User backup riêng
[ ] Password được bảo vệ
[ ] File tạm trước rename
[ ] Retention rõ
[ ] Bản sao ngoài VPS
[ ] Mã hóa khi cần
[ ] Backup global roles
[ ] Monitoring file mới nhất
[ ] Cảnh báo lỗi
[ ] Restore vào DB test
[ ] Smoke test ứng dụng
[ ] Đo thời gian restore
[ ] Backup trước migration

Câu hỏi thường gặp

Copy Docker volume có phải backup không?

Copy file khi PostgreSQL đang chạy có thể không nhất quán. Dùng phương pháp PostgreSQL hỗ trợ.

Backup mỗi ngày có đủ không?

Phụ thuộc RPO. Nếu không thể mất 24 giờ dữ liệu, cần tần suất cao hơn hoặc PITR.

Có cần test restore không?

Có. Restore test là cách chứng minh backup sử dụng được.

Kết luận

Backup đáng tin cậy là quy trình được kiểm tra, không phải chỉ một file. Hãy lưu ngoài VPS, cảnh báo khi lỗi và thực hành restore định kỳ.

Nguồn tham khảo

Đọc tiếp