Tại Sao Backup Quan Trọng?
Trước khi đi vào chi tiết kỹ thuật, hãy cùng nhìn lại một câu chuyện có thật: Một startup công nghệ tại Việt Nam từng mất toàn bộ dữ liệu khách hàng vì không có backup đúng cách. Hệ quả? Họ mất 6 tháng để phục hồi niềm tin từ khách hàng và gần như phá sản.
Backup không chỉ là một công việc kỹ thuật, mà là một chiến lược bảo vệ doanh nghiệp của bạn.
Phần 1: Các Phương Pháp Backup PostgreSQL
1.1. Logical Backup với pg_dump
Đây là phương pháp phổ biến nhất, phù hợp cho hầu hết các trường hợp.
Backup một database đơn lẻ
# Format SQL plain text (dễ đọc, dễ edit) pg_dump -U postgres -d myapp_db > myapp_backup.sqlFormat custom (nén tốt, restore linh hoạt)
pg_dump -U postgres -d myapp_db -F c -f myapp_backup.dump
Format directory (backup song song, nhanh nhất)
pg_dump -U postgres -d myapp_db -F d -j 4 -f myapp_backup_dir/
So sánh các format:
| Format | Ưu điểm | Nhược điểm | Khi nào dùng |
|---|---|---|---|
| Plain SQL (-F p) | Dễ đọc, edit được | Không nén, restore chậm | Database nhỏ, cần xem nội dung |
| Custom (-F c) | Nén tốt, restore chọn lọc | Không đọc được trực tiếp | Hầu hết các trường hợp |
| Directory (-F d) | Backup song song, nhanh nhất | Tốn nhiều files | Database lớn (>100GB) |
| Tar (-F t) | Nén được | Không restore song song | Ít dùng |
Backup có chọn lọc
# Chỉ backup schema (cấu trúc tables, indexes, constraints) pg_dump -U postgres -d myapp_db --schema-only > schema.sqlChỉ backup data
pg_dump -U postgres -d myapp_db --data-only > data.sql
Backup một table cụ thể
pg_dump -U postgres -d myapp_db -t users -t orders > important_tables.sql
Backup tất cả trừ table logs (thường rất lớn)
pg_dump -U postgres -d myapp_db -T logs > backup_no_logs.sql
Backup theo schema
pg_dump -U postgres -d myapp_db -n public -n reporting > selected_schemas.sql
Ví dụ thực tế: Backup database production
#!/bin/bashScript: backup_production.sh
DB_NAME="myapp_production" DB_USER="postgres" DB_HOST="localhost" BACKUP_DIR="/backups/postgresql" DATE=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_${DATE}.dump"
Tạo thư mục nếu chưa có
mkdir -p $BACKUP_DIR
Backup với compression level 9
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME
-F c -Z 9
-f $BACKUP_FILE
--verboseCheck kết quả
if [ $? -eq 0 ]; then echo "✓ Backup thành công: $BACKUP_FILE" SIZE=$(du -h $BACKUP_FILE | cut -f1) echo "✓ Kích thước: $SIZE" else echo "✗ Backup thất bại!" exit 1 fi
Xóa backup cũ hơn 7 ngày
find $BACKUP_DIR -name "${DB_NAME}_*.dump" -mtime +7 -delete
echo "✓ Đã xóa backup cũ hơn 7 ngày"
1.2. Backup toàn bộ cluster với pg_dumpall
Khi bạn cần backup tất cả databases, roles, và tablespaces:
# Backup toàn bộ pg_dumpall -U postgres > all_databases.sqlChỉ backup global objects (roles, tablespaces)
pg_dumpall -U postgres --globals-only > globals.sql
Chỉ backup roles
pg_dumpall -U postgres --roles-only > roles.sql
Khi nào dùng pg_dumpall?
- Khi migrate toàn bộ PostgreSQL server sang máy mới
- Khi cần backup cả user permissions và roles
- Khi có nhiều databases liên quan đến nhau
1.3. Physical Backup với Base Backup
Đây là phương pháp backup ở mức file system, phù hợp cho databases rất lớn.
# Bước 1: Tạo base backup pg_basebackup -U postgres -D /backups/base -F tar -z -PBước 2: Configure WAL archiving (trong postgresql.conf)
wal_level = replica archive_mode = on archive_command = 'test ! -f /backups/wal/%f && cp %p /backups/wal/%f' max_wal_senders = 3
Ưu điểm:
- Rất nhanh cho database lớn (TB-level)
- Hỗ trợ Point-in-Time Recovery (PITR)
- Có thể dùng cho replication
Nhược điểm:
- Phức tạp hơn logical backup
- Phải backup cả cluster, không thể chọn database riêng lẻ
- Yêu cầu cùng phiên bản PostgreSQL khi restore
Phần 2: Restore PostgreSQL
2.1. Restore từ SQL file
# Tạo database mới (nếu cần) createdb -U postgres myapp_db_restoredRestore từ SQL file
psql -U postgres -d myapp_db_restored < myapp_backup.sql
Restore với error handling
psql -U postgres -d myapp_db_restored
-v ON_ERROR_STOP=1
--echo-errors
< myapp_backup.sql
2.2. Restore từ Custom/Directory format
# Restore cơ bản pg_restore -U postgres -d myapp_db myapp_backup.dumpRestore với clean (xóa objects cũ trước)
pg_restore -U postgres -d myapp_db -c myapp_backup.dump
Restore song song (nhanh hơn nhiều)
pg_restore -U postgres -d myapp_db -j 4 myapp_backup.dump
Restore chỉ một table
pg_restore -U postgres -d myapp_db -t users myapp_backup.dump
Restore vào database mới
pg_restore -U postgres -d postgres -C myapp_backup.dump
2.3. Restore Script hoàn chỉnh
#!/bin/bashScript: restore_database.sh
BACKUP_FILE=$1 NEW_DB_NAME=$2
if [ -z "$BACKUP_FILE" ] || [ -z "$NEW_DB_NAME" ]; then echo "Usage: $0 <backup_file> <new_db_name>" exit 1 fi
echo "→ Kiểm tra file backup..." if [ ! -f "$BACKUP_FILE" ]; then echo "✗ File không tồn tại: $BACKUP_FILE" exit 1 fi
echo "→ Tạo database mới: $NEW_DB_NAME" createdb -U postgres $NEW_DB_NAME
if [ $? -ne 0 ]; then echo "✗ Không thể tạo database" exit 1 fi
echo "→ Đang restore..." pg_restore -U postgres -d $NEW_DB_NAME -j 4 --verbose $BACKUP_FILE
if [ $? -eq 0 ]; then echo "✓ Restore thành công!" echo "→ Thông tin database:" psql -U postgres -d $NEW_DB_NAME -c "\dt" else echo "✗ Restore thất bại!" exit 1 fi
Phần 3: Strategies và Best Practices
3.1. Chiến lược Backup 3-2-1
Đây là quy tắc vàng trong backup:
- 3 bản copies của dữ liệu
- 2 loại media khác nhau (ví dụ: disk và cloud)
- 1 bản offsite (ở vị trí vật lý khác)
Ví dụ implementation:
#!/bin/bashScript: backup_strategy_321.sh
DB_NAME="myapp_production" LOCAL_BACKUP="/backups/local" NAS_BACKUP="/mnt/nas/backups" DATE=$(date +%Y%m%d_%H%M%S) BACKUP_NAME="${DB_NAME}_${DATE}.dump"
Backup 1: Local disk
echo "→ Creating local backup..." pg_dump -U postgres -d $DB_NAME -F c -f "$LOCAL_BACKUP/$BACKUP_NAME"
Backup 2: NAS (different media)
echo "→ Copying to NAS..." cp "$LOCAL_BACKUP/$BACKUP_NAME" "$NAS_BACKUP/"
Backup 3: Cloud (offsite) - AWS S3
echo "→ Uploading to S3..." aws s3 cp "$LOCAL_BACKUP/$BACKUP_NAME"
s3://mycompany-backups/postgresql/
--storage-class STANDARD_IA
echo "✓ 3-2-1 backup completed!"
3.2. Backup Schedule
Đề xuất lịch backup cho các môi trường khác nhau:
Development:
# Crontab: Backup hàng ngày lúc 2 giờ sáng
0 2 * * * /scripts/backup_dev.sh
Staging:
# Backup mỗi 6 giờ
0 */6 * * * /scripts/backup_staging.sh
Production:
# Full backup: Mỗi ngày lúc 2 giờ sáng 0 2 * * * /scripts/full_backup_prod.shIncremental backup: Mỗi giờ
0 * * * * /scripts/incremental_backup_prod.sh
WAL archiving: Continuous
3.3. Tự động hóa với systemd timer
# /etc/systemd/system/postgresql-backup.service [Unit] Description=PostgreSQL Backup Service After=postgresql.service
[Service] Type=oneshot User=postgres ExecStart=/usr/local/bin/backup_postgres.sh StandardOutput=journal StandardError=journal
# /etc/systemd/system/postgresql-backup.timer [Unit] Description=PostgreSQL Daily Backup Timer[Timer] OnCalendar=daily OnCalendar=02:00 Persistent=true
[Install] WantedBy=timers.target
Enable timer:
sudo systemctl enable postgresql-backup.timer
sudo systemctl start postgresql-backup.timer
3.4. Monitoring và Alerting
Script kiểm tra backup:
#!/bin/bashScript: check_backup_health.sh
BACKUP_DIR="/backups/postgresql" MAX_AGE_HOURS=24 SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
Tìm backup mới nhất
LATEST_BACKUP=$(find $BACKUP_DIR -name "*.dump" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" ")
if [ -z "$LATEST_BACKUP" ]; then MESSAGE="⚠️ CẢNH BÁO: Không tìm thấy backup nào!" curl -X POST -H 'Content-type: application/json'
--data "{"text":"$MESSAGE"}"
$SLACK_WEBHOOK exit 1 fiKiểm tra tuổi của backup
BACKUP_TIME=$(stat -c %Y "$LATEST_BACKUP") CURRENT_TIME=$(date +%s) AGE_HOURS=$(( ($CURRENT_TIME - $BACKUP_TIME) / 3600 ))
if [ $AGE_HOURS -gt $MAX_AGE_HOURS ]; then MESSAGE="⚠️ CẢNH BÁO: Backup quá cũ! Age: ${AGE_HOURS}h\nFile: $LATEST_BACKUP" curl -X POST -H 'Content-type: application/json'
--data "{"text":"$MESSAGE"}"
$SLACK_WEBHOOK exit 1 fiKiểm tra kích thước backup (phải > 0)
SIZE=$(stat -c %s "$LATEST_BACKUP") if [ $SIZE -eq 0 ]; then MESSAGE="⚠️ CẢNH BÁO: Backup có kích thước 0 bytes!\nFile: $LATEST_BACKUP" curl -X POST -H 'Content-type: application/json'
--data "{"text":"$MESSAGE"}"
$SLACK_WEBHOOK exit 1 fi
echo "✓ Backup health check passed" echo " Latest: $LATEST_BACKUP" echo " Age: ${AGE_HOURS}h" echo " Size: $(du -h $LATEST_BACKUP | cut -f1)"
3.5. Testing Restore
QUAN TRỌNG: Backup không có giá trị nếu bạn chưa bao giờ test restore!
#!/bin/bashScript: test_restore.sh
BACKUP_FILE=$1 TEST_DB="test_restore_$(date +%s)"
echo "→ Testing restore from: $BACKUP_FILE"
Tạo test database
createdb -U postgres $TEST_DB
Restore
pg_restore -U postgres -d $TEST_DB $BACKUP_FILE
Kiểm tra
TABLES=$(psql -U postgres -d $TEST_DB -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public'")
if [ $TABLES -gt 0 ]; then echo "✓ Restore test PASSED: $TABLES tables restored"
# Verify data psql -U postgres -d $TEST_DB -c "SELECT tablename, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC LIMIT 10"else echo "✗ Restore test FAILED: No tables found" fi
Cleanup
dropdb -U postgres $TEST_DB
echo "✓ Test completed and cleaned up"
Phần 4: Troubleshooting
4.1. Lỗi thường gặp khi Backup
Lỗi: "permission denied"
# Solution: Chạy với user có quyền sudo -u postgres pg_dump mydb > backup.sqlHoặc grant quyền
GRANT CONNECT ON DATABASE mydb TO backup_user; GRANT SELECT ON ALL TABLES IN SCHEMA public TO backup_user;
Lỗi: "could not connect to server"
# Kiểm tra PostgreSQL đang chạy sudo systemctl status postgresqlKiểm tra port
netstat -tlnp | grep 5432
Kiểm tra pg_hba.conf
sudo vim /etc/postgresql/14/main/pg_hba.conf
Lỗi: Backup quá lâu
# Solution: Dùng format directory với parallel pg_dump -F d -j 8 -f backup_dir/ mydbHoặc exclude tables lớn
pg_dump -T large_log_table mydb > backup.sql
4.2. Lỗi thường gặp khi Restore
Lỗi: "database already exists"
# Solution 1: Drop database cũ dropdb mydb createdb mydb pg_restore -d mydb backup.dumpSolution 2: Dùng flag -c (clean)
pg_restore -c -d mydb backup.dump
Lỗi: "role does not exist"
# Solution: Restore roles trước pg_dumpall --roles-only > roles.sql psql -f roles.sqlSau đó restore data
pg_restore -d mydb backup.dump
Lỗi: Out of disk space
# Check disk space trước khi restore df -hƯớc tính kích thước cần thiết (thường 2-3x backup file)
du -h backup.dump
Phần 5: Advanced Topics
5.1. Point-in-Time Recovery (PITR)
PITR cho phép bạn restore database về một thời điểm cụ thể trong quá khứ.
Setup WAL archiving:
# postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'test ! -f /wal_archive/%f && cp %p /wal_archive/%f'
archive_timeout = 300 # Force WAL rotation every 5 minutes
Thực hiện PITR:
# Bước 1: Stop PostgreSQL sudo systemctl stop postgresqlBước 2: Restore base backup
rm -rf /var/lib/postgresql/14/main/* tar -xzf /backups/base.tar.gz -C /var/lib/postgresql/14/main/
Bước 3: Tạo recovery.conf (PostgreSQL < 12) hoặc recovery.signal (>= 12)
cat > /var/lib/postgresql/14/main/recovery.signal << EOF restore_command = 'cp /wal_archive/%f %p' recovery_target_time = '2024-01-15 14:30:00' recovery_target_action = 'promote' EOF
Bước 4: Start PostgreSQL
sudo systemctl start postgresql
5.2. Continuous Archiving với pgBackRest
pgBackRest là công cụ backup enterprise-grade cho PostgreSQL:
# Cài đặt sudo apt-get install pgbackrestConfig /etc/pgbackrest/pgbackrest.conf
[global] repo1-path=/var/lib/pgbackrest repo1-retention-full=2
[mydb] pg1-path=/var/lib/postgresql/14/main
Full backup
pgbackrest --stanza=mydb --type=full backup
Incremental backup
pgbackrest --stanza=mydb --type=incr backup
Restore
pgbackrest --stanza=mydb restore
5.3. Backup với Docker
# Backup PostgreSQL trong Docker docker exec my_postgres_container pg_dump -U postgres mydb > backup.sqlRestore
docker exec -i my_postgres_container psql -U postgres mydb < backup.sql
Docker Compose với automated backups
version: '3.8' services: postgres: image: postgres:14 volumes: - postgres_data:/var/lib/postgresql/data
backup: image: prodrigestivill/postgres-backup-local environment: POSTGRES_HOST: postgres POSTGRES_DB: mydb POSTGRES_USER: postgres POSTGRES_PASSWORD: password SCHEDULE: "@daily" volumes: - ./backups:/backups
Kết Luận
Backup và restore không chỉ là một task kỹ thuật đơn thuần, mà là một phần quan trọng trong chiến lược bảo vệ dữ liệu của doanh nghiệp. Một số điểm quan trọng cần nhớ:
- Luôn test restore - Backup chưa test = không có backup
- Automate everything - Đừng dựa vào việc nhớ chạy backup thủ công
- Follow 3-2-1 rule - 3 copies, 2 media types, 1 offsite
- Monitor và alert - Biết ngay khi có vấn đề
- Document everything - Team mới cũng phải biết cách restore
Checklist cuối cùng
- [ ] Backup script đã được viết và test
- [ ] Crontab/systemd timer đã được setup
- [ ] Monitoring và alerting đã được cấu hình
- [ ] Restore đã được test ít nhất 1 lần
- [ ] Documentation đã được viết
- [ ] Team đã được training về quy trình backup/restore
- [ ] Offsite backup đã được setup
- [ ] Retention policy đã được định nghĩa rõ ràng
Nguồn tham khảo:
- PostgreSQL Official Documentation - Backup and Restore
- pgBackRest Documentation
- PostgreSQL Backup Best Practices
Bài viết này được cập nhật lần cuối: Tháng 12, 2024



