この記事では、現在の実務内容を参考に、PostgreSQLにおける主要なバックアップ手法と、実際のリストア手順を内容をコマンド付きで解説します。開発環境から本番運用まで使える実践的な内容です。
はじめに
データベースの運用において、バックアップとリストアは最も重要なオペレーションのひとつです。PostgreSQLには複数のバックアップ手法が用意されており、用途やデータ量に応じて使い分けることが求められます。
本記事では以下の内容を記載します。
-
pg_dump/pg_dumpallによる論理バックアップ - ファイルシステムレベルの物理バックアップ
-
pg_basebackupによるベースバックアップ - 各手法のリストア手順
環境情報
PostgreSQL: 15.x
OS: Ubuntu 22.04 LTS
1. 論理バックアップ — pg_dump / pg_dumpall
論理バックアップは、SQLの形式でデータを出力する方法です。可搬性が高く、異なるバージョン間の移行にも使えます。
1-1. 単一データベースのバックアップ
# カスタム形式(推奨: 圧縮・並列リストア対応)
pg_dump -U postgres -Fc -d mydb -f mydb.dump
# プレーンSQL形式
pg_dump -U postgres -d mydb -f mydb.sql
# gzip圧縮しながら出力
pg_dump -U postgres -d mydb | gzip > mydb.sql.gz
| オプション | 説明 |
|---|---|
-U |
接続ユーザー名 |
-Fc |
カスタム形式(pg_restoreで使用) |
-Ft |
tar形式 |
-Fp |
プレーンSQL形式(デフォルト) |
-d |
対象データベース名 |
-f |
出力ファイルパス |
1-2. 特定テーブルだけをバックアップ
# テーブル指定
pg_dump -U postgres -d mydb -t users -t orders -Fc -f partial.dump
# スキーマのみ(データなし)
pg_dump -U postgres -d mydb -s -f schema_only.sql
# データのみ(スキーマなし)
pg_dump -U postgres -d mydb -a -f data_only.sql
1-3. 全データベースのバックアップ
# ロール・テーブルスペースも含めて全体バックアップ
pg_dumpall -U postgres -f all_databases.sql
# グローバルオブジェクト(ロールのみ)
pg_dumpall -U postgres --globals-only -f globals.sql
1-4. リストア手順
# カスタム形式のリストア
pg_restore -U postgres -d mydb mydb.dump
# 並列リストア(高速化)
pg_restore -U postgres -d mydb -j 4 mydb.dump
# 対象DBが存在しない場合は先に作成
createdb -U postgres mydb
pg_restore -U postgres -d mydb mydb.dump
# プレーンSQLのリストア
psql -U postgres -d mydb -f mydb.sql
# gzip圧縮ファイルのリストア
gunzip -c mydb.sql.gz | psql -U postgres -d mydb
# pg_dumpall で作成したファイルのリストア
psql -U postgres -f all_databases.sql
カスタム形式(-Fc)でダンプしたファイルは psql では読み込めません。必ず pg_restore を使用してください。
2. 物理バックアップ — ファイルシステムコピー
PostgreSQLのデータディレクトリをそのままコピーする方法です。大規模DBでは論理バックアップより高速ですが、PostgreSQLを停止する必要があります。
# PostgreSQLを停止
sudo systemctl stop postgresql
# データディレクトリをコピー
sudo rsync -av /var/lib/postgresql/15/main/ /backup/pg_data_$(date +%Y%m%d)/
# PostgreSQLを再起動
sudo systemctl start postgresql
リストア手順
# PostgreSQLを停止
sudo systemctl stop postgresql
# 既存のデータディレクトリをリネームして退避
sudo mv /var/lib/postgresql/15/main /var/lib/postgresql/15/main.bak
# バックアップからリストア
sudo rsync -av /backup/pg_data_20240601/ /var/lib/postgresql/15/main/
# 権限を修正
sudo chown -R postgres:postgres /var/lib/postgresql/15/main
# PostgreSQLを起動
sudo systemctl start postgresql
3. pg_basebackup によるオンラインバックアップ
pg_basebackup はPostgreSQLを停止せずに物理バックアップを取得できるツールです。レプリケーション接続を使用するため、pg_hba.conf の設定が必要です。
事前設定
# postgresql.conf
wal_level = test
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/wal_archive/%f'
max_wal_senders = 3
# pg_hba.conf に以下を追加
# local replication postgres trust
設定変更後にPostgreSQLを再起動します。
sudo systemctl restart postgresql
バックアップ取得
# tar形式でバックアップ(圧縮あり)
pg_basebackup -U postgres -D /backup/basebackup -Ft -z -P
# ディレクトリ形式でバックアップ
pg_basebackup -U postgres -D /backup/basebackup -Fp -P
# WALファイルも同時に含める
pg_basebackup -U postgres -D /backup/basebackup -Ft -z -Xs -P
| オプション | 説明 |
|---|---|
-D |
出力先ディレクトリ |
-Ft |
tar形式 |
-Fp |
ファイル形式(plain) |
-z |
gzip圧縮 |
-P |
進捗表示 |
-Xs |
WALをstreaming方式で取得 |
リストア手順
# PostgreSQLを停止
sudo systemctl stop postgresql
# データディレクトリを退避
sudo mv /var/lib/postgresql/15/main /var/lib/postgresql/15/main.bak
# バックアップを展開
sudo mkdir /var/lib/postgresql/15/main
sudo tar -xzf /backup/basebackup/base.tar.gz -C /var/lib/postgresql/15/main/
# 権限を修正
sudo chown -R postgres:postgres /var/lib/postgresql/15/main
# PostgreSQLを起動
sudo systemctl start postgresql
4. PITR(ポイントインタイムリカバリ)
PITRは、WALアーカイブと組み合わせることで、任意の時点にデータを復元できる強力な機能です。「誤ってDELETEしてしまった!」というケースで真価を発揮します。
設定(postgresql.conf)
wal_level = test
archive_mode = on
archive_command = 'test ! -f /var/lib/postgresql/wal_archive/%f && cp %p /var/lib/postgresql/wal_archive/%f'
リカバリ手順
① ベースバックアップを展開
sudo systemctl stop postgresql
sudo mv /var/lib/postgresql/15/main /var/lib/postgresql/15/main.bak
sudo mkdir /var/lib/postgresql/15/main
sudo tar -xzf /backup/basebackup/base.tar.gz -C /var/lib/postgresql/15/main/
② recovery.conf 相当の設定(PostgreSQL 12以降)
PostgreSQL 12以降では recovery.conf は廃止され、postgresql.conf と recovery.signal ファイルを使います。
# recovery.signal ファイルを作成(存在するだけでリカバリモードになる)
sudo touch /var/lib/postgresql/15/main/recovery.signal
postgresql.conf に追記:
restore_command = 'cp /var/lib/postgresql/wal_archive/%f %p'
# 特定の時刻まで復元する場合
recovery_target_time = '2024-06-01 12:30:00'
# 特定のトランザクションIDまで復元する場合
# recovery_target_xid = '12345'
# リカバリ完了後の動作(promote: スタンバイを昇格)
recovery_target_action = 'promote'
③ 権限修正と起動
sudo chown -R postgres:postgres /var/lib/postgresql/15/main
sudo systemctl start postgresql
リカバリが完了すると recovery.signal ファイルは自動的に削除されます。
5. バックアップ自動化スクリプト例
#!/bin/bash
# pg_backup.sh — 日次バックアップスクリプト
BACKUP_DIR="/backup/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
PG_USER="postgres"
RETENTION_DAYS=7
mkdir -p "$BACKUP_DIR"
# 全データベース一覧を取得してバックアップ
for DB in $(psql -U "$PG_USER" -tAc "SELECT datname FROM pg_database WHERE datistemplate = false;"); do
echo "Backing up database: $DB"
pg_dump -U "$PG_USER" -Fc "$DB" -f "${BACKUP_DIR}/${DB}_${DATE}.dump"
if [ $? -eq 0 ]; then
echo " -> Success: ${DB}_${DATE}.dump"
else
echo " -> FAILED: $DB" >&2
fi
done
# グローバルオブジェクトのバックアップ
pg_dumpall -U "$PG_USER" --globals-only -f "${BACKUP_DIR}/globals_${DATE}.sql"
# 古いバックアップを削除
find "$BACKUP_DIR" -name "*.dump" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "*.sql" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: $DATE"
cron に登録して毎日深夜に実行する例:
# crontab -e
0 2 * * * /usr/local/bin/pg_backup.sh >> /var/log/pg_backup.log 2>&1
6. 各手法の比較まとめ
| 手法 | オンライン | 粒度 | リストア速度 | 主な用途 |
|---|---|---|---|---|
pg_dump(カスタム形式) |
✅ | テーブル単位 | 中 | 単一DB・移行・定期バックアップ |
pg_dumpall |
✅ | DB全体 | 中 | 全DB・ロール含む一括バックアップ |
| ファイルシステムコピー | ❌ | データディレクトリ全体 | 速 | 小規模・シンプルな全体バックアップ |
pg_basebackup |
✅ | データディレクトリ全体 | 速 | 本番環境・レプリカ構築 |
| PITR(WAL + basebackup) | ✅ | 任意の時点 | 速〜中 | 障害復旧・誤操作のロールバック |
おわりに
PostgreSQLのバックアップ戦略は、用途に合わせて適切な手法を選ぶことが重要です。
-
開発・小規模環境:
pg_dumpで十分 -
本番環境:
pg_basebackup+ WALアーカイブによるPITRが推奨 - 誤操作への備え: PITRを設定しておくと任意の時点に戻れる
バックアップは取るだけでなく、定期的にリストアの動作確認をすることが運用上非常に重要です。