Chuyển đến nội dung chính

PostgreSQL のバックアップと復元の総合ガイド

Duy Tran13分
PostgreSQL のバックアップと復元の総合ガイド

バックアップはなぜ重要ですか?

技術的な詳細に入る前に、実話を振り返ってみましょう。ベトナムのテクノロジー系スタートアップ企業は、適切なバックアップがなかったため、すべての顧客データを失ったことがあります。結果?顧客の信頼を回復するのに半年かかり、倒産寸前だった。

バックアップは単なる技術的な仕事ではなく、ビジネスを保護するための戦略です。

パート 1: PostgreSQL のバックアップ方法

1.1. pg_dump による論理バックアップ

これは最も一般的な方法であり、ほとんどの場合に適しています。

単一データベースをバックアップする

# Format SQL plain text (dễ đọc, dễ edit)
pg_dump -U postgres -d myapp_db > myapp_backup.sql

Format 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.sql

Chỉ 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/bash

Script: 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
--verbose

Check 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.sql

Chỉ 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 -P

Bướ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_restored

Restore 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.dump

Restore 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/bash

Script: 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/bash

Script: 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.sh

Incremental 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/bash

Script: 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 fi

Kiể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 fi

Kiể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/bash

Script: 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.sql

Hoặ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 postgresql

Kiể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/ mydb

Hoặ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.dump

Solution 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.sql

Sau đó 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 postgresql

Bướ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 pgbackrest

Config /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.sql

Restore

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

結論

バックアップと復元は単なる技術的な作業ではなく、企業のデータ保護戦略の重要な部分です。覚えておくべきいくつかの重要な点:

  1. 常に復元をテストする - バックアップがテストされていない = バックアップなし
  2. すべてを自動化する - 手動バックアップを忘れずに実行することに依存しないでください。
  3. 3-2-1 ルールに従う - 3 コピー、2 メディア タイプ、1 オフサイト
  4. 監視と警告 - 問題が発生した場合はすぐに知ることができます
  5. すべてを文書化する - 新しいチームは復元方法も知っておく必要があります

最終チェックリスト

  • [ ] バックアップ スクリプトが作成され、テストされました
  • [ ] Crontab/systemd タイマーが設定されました
  • [ ] モニタリングとアラートが設定されました
  • [ ] 復元は少なくとも 1 回テストされています
  • [ ] ドキュメントが作成されました
  • [ ] チームはバックアップ/復元プロセスのトレーニングを受けています
  • [ ] オフサイトバックアップが設定されました
  • [ ] 保持ポリシーが明確に定義されている

参照元:

この記事の最終更新日: 2024 年 12 月