バックアップはなぜ重要ですか?
技術的な詳細に入る前に、実話を振り返ってみましょう。ベトナムのテクノロジー系スタートアップ企業は、適切なバックアップがなかったため、すべての顧客データを失ったことがあります。結果?顧客の信頼を回復するのに半年かかり、倒産寸前だった。
バックアップは単なる技術的な仕事ではなく、ビジネスを保護するための戦略です。
パート 1: PostgreSQL のバックアップ方法
1.1. pg_dump による論理バックアップ
これは最も一般的な方法であり、ほとんどの場合に適しています。
単一データベースをバックアップする
# 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/
フォーマットを比較します。
| フォーマット | 利点 | 短所 | いつ使用するか |
|---|---|---|---|
| プレーン SQL (-F p) | 読みやすく、編集しやすい | 圧縮なし、復元が遅い | データベースが小さいため、コンテンツを表示する必要がある |
| カスタム (-F c) | 優れた圧縮、選択的復元 | 直接読み取れない | ほとんどの場合 |
| ディレクトリ (-F d) | 並行バックアップ、最速 | 大量のファイルを必要とする | 大規模なデータベース (>100GB) |
| タール (-F t) | 圧縮可能 | 並行して復元しないでください | ほとんど使用されない |
選択的バックアップ
# 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
実践例:バックアップデータベースの構築
#!/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. pg_dumpall を使用してクラスター全体をバックアップします。
すべてのデータベース、ロール、テーブルスペースをバックアップする必要がある場合:
# 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
pg_dumpall をいつ使用するか?
- PostgreSQL サーバー全体を新しいマシンに移行する場合
- ユーザー権限とロールの両方をバックアップする必要がある場合
- 相互に関連するデータベースが多数ある場合
1.3.ベースバックアップを使用した物理バックアップ
これはファイル システム レベルでのバックアップ方法であり、非常に大規模なデータベースに適しています。
# 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
利点:
- 大規模なデータベース (TB レベル) では非常に高速
- ポイントインタイムリカバリ (PITR) のサポート
- レプリケーションに使用可能
短所:
- 論理バックアップよりも複雑
- クラスター全体をバックアップする必要があり、個々のデータベースを選択することはできません
- 復元時には同じ PostgreSQL バージョンが必要です
パート 2: PostgreSQL の復元
2.1. SQLファイルから復元
# 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 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.完全なスクリプトを復元する
#!/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
パート 3: 戦略とベストプラクティス
3.1.バックアップ戦略 3-2-1
バックアップにおける黄金律は次のとおりです。
- 3 データのコピー
- 2 さまざまなメディアタイプ (ディスクやクラウドなど)
- 1 オフサイト バージョン (別の物理的な場所)
実装例:
#!/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.バックアップスケジュール
さまざまな環境に推奨されるバックアップ スケジュール:
開発:
# Crontab: Backup hàng ngày lúc 2 giờ sáng
0 2 * * * /scripts/backup_dev.sh
ステージング:
# Backup mỗi 6 giờ
0 */6 * * * /scripts/backup_staging.sh
制作:
# 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. systemd タイマーによる自動化
# /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
タイマーを有効にする:
sudo systemctl enable postgresql-backup.timer
sudo systemctl start postgresql-backup.timer
3.4.監視と警告
バックアップを確認するスクリプト:
#!/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.復元のテスト
重要: 復元をテストしたことがない場合、バックアップは役に立ちません。
#!/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"
パート 4: トラブルシューティング
4.1.バックアップ時の一般的なエラー
エラー: 「許可が拒否されました」
# 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;
エラー: 「サーバーに接続できませんでした」
# 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
エラー: バックアップに時間がかかりすぎました
# 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.復元時の一般的なエラー
エラー: 「データベースはすでに存在します」
# 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
エラー: 「ロールが存在しません」
# Solution: Restore roles trước pg_dumpall --roles-only > roles.sql psql -f roles.sqlSau đó restore data
pg_restore -d mydb backup.dump
エラー: ディスク容量が不足しています
# 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
パート 5: 高度なトピック
5.1.ポイントインタイムリカバリ (PITR)
PITR を使用すると、データベースを過去の特定の時点に復元できます。
WAL アーカイブをセットアップします。
# 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
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. pgBackRest による継続的アーカイブ
pgBackRest は、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. 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
結論
バックアップと復元は単なる技術的な作業ではなく、企業のデータ保護戦略の重要な部分です。覚えておくべきいくつかの重要な点:
- 常に復元をテストする - バックアップがテストされていない = バックアップなし
- すべてを自動化する - 手動バックアップを忘れずに実行することに依存しないでください。
- 3-2-1 ルールに従う - 3 コピー、2 メディア タイプ、1 オフサイト
- 監視と警告 - 問題が発生した場合はすぐに知ることができます
- すべてを文書化する - 新しいチームは復元方法も知っておく必要があります
最終チェックリスト
- [ ] バックアップ スクリプトが作成され、テストされました
- [ ] Crontab/systemd タイマーが設定されました
- [ ] モニタリングとアラートが設定されました
- [ ] 復元は少なくとも 1 回テストされています
- [ ] ドキュメントが作成されました
- [ ] チームはバックアップ/復元プロセスのトレーニングを受けています
- [ ] オフサイトバックアップが設定されました
- [ ] 保持ポリシーが明確に定義されている
参照元:
この記事の最終更新日: 2024 年 12 月
