はじめに

データベースのバックアップは、本番運用において最も重要なタスクの一つです。ハードウェア障害、人的ミスによるデータ削除、ランサムウェア攻撃など、データ損失のリスクは常に存在しています。適切なバックアップ戦略を持たないシステムは、いつ致命的な障害に見舞われてもおかしくありません。

PostgreSQLには複数のバックアップ手法が用意されており、それぞれに特徴と用途があります。本記事では、論理バックアップ(pg_dump/pg_dumpall)と物理バックアップ(pg_basebackup)の違いを理解し、要件に応じたバックアップ戦略を設計・実装できるようになることを目指します。

本記事で扱うトピックは以下の通りです。

  • 論理バックアップと物理バックアップの違い
  • pg_dump/pg_dumpallによる論理バックアップとリストア
  • pg_basebackupによる物理バックアップとリストア
  • cronを使ったバックアップの自動化
  • 要件に応じたバックアップ戦略の設計

この記事を読むことで、以下のことができるようになります。

  • 論理バックアップと物理バックアップの違いを説明できる
  • pg_dumpとpg_dumpallを使って論理バックアップを取得・リストアできる
  • pg_basebackupを使って物理バックアップを取得・リストアできる
  • cronを使ってバックアップを自動化できる
  • システム要件に応じた適切なバックアップ戦略を設計できる

前提条件

  • PostgreSQL 14以降がインストールされていること
  • psqlでデータベースに接続できること
  • Linuxの基本的なコマンド操作ができること
  • スーパーユーザー権限(postgres)でアクセスできること

バックアップの種類と特徴

PostgreSQLのバックアップは、大きく「論理バックアップ」と「物理バックアップ」の2種類に分類されます。それぞれの特徴を理解することが、適切なバックアップ戦略を設計する第一歩です。

論理バックアップと物理バックアップの比較

項目 論理バックアップ 物理バックアップ
ツール pg_dump / pg_dumpall pg_basebackup
出力形式 SQL文またはカスタム形式 データディレクトリのコピー
取得単位 テーブル / データベース / クラスタ全体 クラスタ全体のみ
バックアップサイズ 圧縮可能で小さい データディレクトリと同等
バックアップ速度 データ量に比例(遅い) 高速(ファイルコピー)
リストア速度 SQL実行のため遅い 高速(ファイル配置)
ポイントインタイムリカバリ 不可 WALと組み合わせて可能
異なるバージョンへの移行 可能 不可(同一バージョンのみ)
異なるアーキテクチャへの移行 可能 不可(同一アーキテクチャのみ)
部分リストア 可能(テーブル単位) 不可(クラスタ全体のみ)

論理バックアップの特徴

論理バックアップは、データベースの内容をSQL文(CREATE TABLE、INSERT文など)やカスタム形式で出力する方式です。

主なメリットは以下の通りです。

  • 柔軟なリストア: 特定のテーブルやスキーマのみをリストアできる
  • バージョン間移行: 異なるPostgreSQLバージョン間でデータを移行できる
  • プラットフォーム間移行: 異なるOS・アーキテクチャ間でデータを移行できる
  • 圧縮効率: テキストベースのため高い圧縮率を実現できる

一方、デメリットもあります。

  • バックアップ・リストアに時間がかかる: 大規模データベースでは数時間かかることもある
  • ポイントインタイムリカバリ不可: バックアップ時点の状態にしか戻せない
  • サーバー負荷: バックアップ中はCPU・I/O負荷が発生する

物理バックアップの特徴

物理バックアップは、PostgreSQLのデータディレクトリを丸ごとコピーする方式です。

主なメリットは以下の通りです。

  • 高速なバックアップ・リストア: ファイルコピーのため論理バックアップより高速
  • ポイントインタイムリカバリ(PITR): WALアーカイブと組み合わせることで任意の時点に復元可能
  • レプリケーション構築: ストリーミングレプリカの初期構築に使用できる

一方、デメリットもあります。

  • クラスタ全体のみ: 特定のテーブルだけをリストアすることはできない
  • バージョン依存: 同一のPostgreSQLメジャーバージョン間でのみ使用可能
  • アーキテクチャ依存: 同一のCPUアーキテクチャ・OS間でのみ使用可能

バックアップ方式の選択指針

どちらのバックアップ方式を選ぶかは、システム要件によって決まります。

flowchart TD
    A[バックアップ方式の選択] --> B{PITR<br/>ポイントインタイムリカバリ<br/>が必要か}
    B -->|はい| C[物理バックアップ<br/>pg_basebackup + WAL]
    B -->|いいえ| D{バージョンまたは<br/>プラットフォーム間<br/>移行が必要か}
    D -->|はい| E[論理バックアップ<br/>pg_dump]
    D -->|いいえ| F{部分リストア<br/>が必要か}
    F -->|はい| E
    F -->|いいえ| G{データベース規模}
    G -->|小〜中規模<br/>100GB未満| H[論理バックアップ<br/>運用がシンプル]
    G -->|大規模<br/>100GB以上| I[物理バックアップ<br/>高速性重視]

多くの本番環境では、両方のバックアップを併用することが推奨されます。物理バックアップで迅速な復旧を可能にしつつ、論理バックアップで柔軟な移行オプションを確保するという戦略です。

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

pg_dumpは、単一のデータベースを論理バックアップするためのツールです。最も基本的なバックアップ方法として広く使われています。

pg_dumpの基本構文

pg_dumpの基本的な使い方は以下の通りです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 基本構文
pg_dump [オプション] [データベース名]

# 最もシンプルな例(標準出力にSQL形式で出力)
pg_dump mydb

# ファイルに出力
pg_dump mydb > backup.sql

# 接続情報を指定
pg_dump -h localhost -p 5432 -U postgres mydb > backup.sql

出力形式の種類

pg_dumpは複数の出力形式をサポートしています。用途に応じて適切な形式を選択してください。

形式 オプション 特徴 リストアツール
プレーンSQL -Fp(デフォルト) 人間が読めるSQL文 psql
カスタム -Fc 圧縮されたバイナリ形式 pg_restore
ディレクトリ -Fd 並列バックアップ/リストア対応 pg_restore
tar -Ft tar形式のアーカイブ pg_restore

本番運用ではカスタム形式(-Fc)の使用を推奨します。圧縮によりファイルサイズが小さくなり、pg_restoreで柔軟なリストアオプションが使えるためです。

pg_dumpの実践的な使用例

実際の運用で使用するオプションを組み合わせた例を示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# カスタム形式で圧縮バックアップ(推奨)
pg_dump -h localhost -p 5432 -U postgres \
  -Fc -f /backup/mydb_$(date +%Y%m%d_%H%M%S).dump mydb

# 並列バックアップ(大規模データベース向け)
# -j オプションで並列ジョブ数を指定
pg_dump -h localhost -p 5432 -U postgres \
  -Fd -j 4 -f /backup/mydb_$(date +%Y%m%d) mydb

# 特定のスキーマのみバックアップ
pg_dump -h localhost -p 5432 -U postgres \
  -Fc -n public -f /backup/mydb_public.dump mydb

# 特定のテーブルのみバックアップ
pg_dump -h localhost -p 5432 -U postgres \
  -Fc -t users -t orders -f /backup/mydb_tables.dump mydb

# 特定のテーブルを除外してバックアップ
pg_dump -h localhost -p 5432 -U postgres \
  -Fc -T audit_logs -T temporary_data -f /backup/mydb_exclude.dump mydb

# データのみバックアップ(スキーマ除外)
pg_dump -h localhost -p 5432 -U postgres \
  -Fc --data-only -f /backup/mydb_data.dump mydb

# スキーマのみバックアップ(データ除外)
pg_dump -h localhost -p 5432 -U postgres \
  -Fc --schema-only -f /backup/mydb_schema.dump mydb

pg_dumpの重要なオプション一覧

運用でよく使用するオプションをまとめます。

オプション 説明
-h, –host 接続先ホスト
-p, –port 接続先ポート
-U, –username 接続ユーザー名
-W, –password パスワード入力を強制
-F, –format 出力形式(p/c/d/t)
-f, –file 出力ファイル名
-j, –jobs 並列ジョブ数(ディレクトリ形式のみ)
-n, –schema 指定スキーマのみ対象
-N, –exclude-schema 指定スキーマを除外
-t, –table 指定テーブルのみ対象
-T, –exclude-table 指定テーブルを除外
–data-only データのみ出力
–schema-only スキーマのみ出力
-v, –verbose 詳細な進捗を表示
-Z, –compress 圧縮レベル(0-9)

pg_dumpallによるクラスタ全体のバックアップ

pg_dumpallは、PostgreSQLクラスタ全体(すべてのデータベースとグローバルオブジェクト)をバックアップするツールです。

pg_dumpallの特徴

pg_dumpallはpg_dumpとは異なり、以下のグローバルオブジェクトも含めてバックアップできます。

  • ロール(ユーザーとグループ)
  • テーブルスペース
  • すべてのデータベース

ただし、pg_dumpallはプレーンSQL形式でしか出力できないため、カスタム形式のメリット(圧縮、並列リストア、部分リストア)は享受できません。

pg_dumpallの使用例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# クラスタ全体のバックアップ
pg_dumpall -h localhost -p 5432 -U postgres \
  > /backup/cluster_$(date +%Y%m%d_%H%M%S).sql

# グローバルオブジェクトのみバックアップ(ロールとテーブルスペース)
pg_dumpall -h localhost -p 5432 -U postgres \
  --globals-only > /backup/globals_$(date +%Y%m%d).sql

# ロールのみバックアップ
pg_dumpall -h localhost -p 5432 -U postgres \
  --roles-only > /backup/roles_$(date +%Y%m%d).sql

# 圧縮して保存
pg_dumpall -h localhost -p 5432 -U postgres | gzip > /backup/cluster.sql.gz

pg_dumpallとpg_dumpの使い分け

実務では、pg_dumpallとpg_dumpを組み合わせて使用することが多いです。

1
2
3
4
5
6
# グローバルオブジェクトはpg_dumpallで取得
pg_dumpall -h localhost -U postgres --globals-only > /backup/globals.sql

# 各データベースはpg_dumpでカスタム形式で取得
pg_dump -h localhost -U postgres -Fc mydb1 > /backup/mydb1.dump
pg_dump -h localhost -U postgres -Fc mydb2 > /backup/mydb2.dump

この方式のメリットは以下の通りです。

  • グローバルオブジェクト(ロール、テーブルスペース)を漏れなくバックアップできる
  • 各データベースはカスタム形式で取得できるため、並列リストアや部分リストアが可能
  • 特定のデータベースのみを個別にリストアできる

論理バックアップからのリストア

バックアップを取得しただけでは意味がありません。実際にリストアできることを確認することが重要です。

psqlによるプレーンSQL形式のリストア

プレーンSQL形式(.sql)のバックアップは、psqlコマンドでリストアします。

1
2
3
4
5
6
7
8
9
# データベースを新規作成してリストア
createdb -h localhost -U postgres mydb_restored
psql -h localhost -U postgres -d mydb_restored -f /backup/mydb.sql

# gzip圧縮されたファイルからリストア
gunzip -c /backup/mydb.sql.gz | psql -h localhost -U postgres -d mydb_restored

# エラーが発生しても継続(本番では非推奨)
psql -h localhost -U postgres -d mydb_restored -f /backup/mydb.sql --set ON_ERROR_STOP=off

pg_restoreによるカスタム形式のリストア

カスタム形式(.dump)やディレクトリ形式のバックアップは、pg_restoreコマンドでリストアします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 基本的なリストア
createdb -h localhost -U postgres mydb_restored
pg_restore -h localhost -U postgres -d mydb_restored /backup/mydb.dump

# データベース作成も含めてリストア(-Cオプション)
pg_restore -h localhost -U postgres -C -d postgres /backup/mydb.dump

# 並列リストア(大規模データベース向け)
pg_restore -h localhost -U postgres -d mydb_restored -j 4 /backup/mydb.dump

# 特定のテーブルのみリストア
pg_restore -h localhost -U postgres -d mydb_restored \
  -t users -t orders /backup/mydb.dump

# スキーマのみリストア(データなし)
pg_restore -h localhost -U postgres -d mydb_restored \
  --schema-only /backup/mydb.dump

# データのみリストア(既存のスキーマに対して)
pg_restore -h localhost -U postgres -d mydb_restored \
  --data-only /backup/mydb.dump

# 既存オブジェクトを削除してからリストア
pg_restore -h localhost -U postgres -d mydb_restored \
  --clean --if-exists /backup/mydb.dump

pg_restoreの重要なオプション

オプション 説明
-d, –dbname リストア先データベース
-C, –create データベースを作成してからリストア
-c, –clean リストア前に既存オブジェクトを削除
–if-exists DROP時にIF EXISTSを付加
-j, –jobs 並列ジョブ数
-t, –table 指定テーブルのみリストア
-n, –schema 指定スキーマのみリストア
–schema-only スキーマのみリストア
–data-only データのみリストア
-l, –list アーカイブの内容を一覧表示
-L, –use-list 指定したリストに基づいてリストア
-v, –verbose 詳細な進捗を表示

リストア内容の事前確認

本番環境へのリストア前に、バックアップの内容を確認することが重要です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# アーカイブの内容を一覧表示
pg_restore -l /backup/mydb.dump

# 出力例:
# ;
# ; Archive created at 2026-01-03 12:00:00 JST
# ;     dbname: mydb
# ;     TOC Entries: 42
# ;     Compression: -1
# ;
# ; Selected TOC Entries:
# ;
# 200; 1259 16385 TABLE public users postgres
# 201; 1259 16392 TABLE public orders postgres
# 202; 1259 16399 TABLE public products postgres
# ...

# 特定のオブジェクトを除外したリストアリストを作成
pg_restore -l /backup/mydb.dump > /tmp/restore.list
# エディタでrestore.listを編集し、不要な行をコメントアウト
pg_restore -h localhost -U postgres -d mydb_restored \
  -L /tmp/restore.list /backup/mydb.dump

pg_basebackupによる物理バックアップ

pg_basebackupは、PostgreSQLクラスタ全体の物理バックアップを取得するためのツールです。WALアーカイブと組み合わせることで、ポイントインタイムリカバリ(PITR)が可能になります。

pg_basebackupの前提設定

pg_basebackupを使用するには、PostgreSQLサーバー側で以下の設定が必要です。

1
2
3
# postgresql.confの設定
wal_level = replica                # または'logical'
max_wal_senders = 3                # レプリケーション接続の最大数

また、pg_hba.confでレプリケーション接続を許可する必要があります。

1
2
3
4
5
# pg_hba.conf
# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   replication     postgres                                peer
host    replication     postgres        127.0.0.1/32            scram-sha-256
host    replication     postgres        ::1/128                 scram-sha-256

設定変更後はPostgreSQLを再起動してください。

1
sudo systemctl restart postgresql

pg_basebackupの基本構文

1
2
3
4
5
6
7
8
9
# 基本構文
pg_basebackup [オプション] -D <出力ディレクトリ>

# 最もシンプルな例
pg_basebackup -h localhost -U postgres -D /backup/base

# 進捗表示とチェックサム検証付き
pg_basebackup -h localhost -U postgres -D /backup/base \
  -P -v --checkpoint=fast

pg_basebackupの実践的な使用例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 標準的な物理バックアップ(推奨設定)
pg_basebackup -h localhost -p 5432 -U postgres \
  -D /backup/base_$(date +%Y%m%d_%H%M%S) \
  -Ft -z -P --checkpoint=fast

# オプション説明:
# -Ft: tar形式で出力
# -z: gzip圧縮
# -P: 進捗表示
# --checkpoint=fast: 即座にチェックポイントを実行

# tar形式でWALも含めて取得(PITR用)
pg_basebackup -h localhost -U postgres \
  -D /backup/base \
  -Ft -z -P --checkpoint=fast \
  -X stream

# プレーン形式(直接使えるデータディレクトリとして出力)
pg_basebackup -h localhost -U postgres \
  -D /backup/base \
  -Fp -P --checkpoint=fast \
  -X stream

pg_basebackupの重要なオプション

オプション 説明
-D, –pgdata 出力ディレクトリ
-h, –host 接続先ホスト
-p, –port 接続先ポート
-U, –username 接続ユーザー
-F, –format 出力形式(p: プレーン、t: tar)
-z, –gzip gzip圧縮(tar形式のみ)
-Z, –compress 圧縮レベル(0-9)
-P, –progress 進捗表示
-v, –verbose 詳細表示
–checkpoint チェックポイント方式(fast/spread)
-X, –wal-method WAL取得方式(none/fetch/stream)
-R, –write-recovery-conf リカバリ設定を自動生成

WAL取得方式の選択

pg_basebackupの-Xオプションでは、WAL(Write-Ahead Log)の取得方式を指定できます。

方式 説明 用途
none WALを取得しない 別途WALアーカイブがある場合
fetch バックアップ完了後にWALを取得 小規模環境
stream バックアップと並行してWALをストリーム取得 推奨(WAL取りこぼしなし)

stream方式を使用する場合、max_wal_sendersの値を1つ追加で確保する必要があります。

物理バックアップからのリストア

物理バックアップからのリストアは、論理バックアップよりも手順が複雑ですが、リストア時間は大幅に短縮されます。

プレーン形式からのリストア

プレーン形式(-Fp)で取得したバックアップは、そのままデータディレクトリとして使用できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 1. PostgreSQLを停止
sudo systemctl stop postgresql

# 2. 既存のデータディレクトリをバックアップ(念のため)
sudo mv /var/lib/postgresql/16/main /var/lib/postgresql/16/main.old

# 3. バックアップを配置
sudo cp -r /backup/base /var/lib/postgresql/16/main

# 4. 所有者を変更
sudo chown -R postgres:postgres /var/lib/postgresql/16/main

# 5. PostgreSQLを起動
sudo systemctl start postgresql

tar形式からのリストア

tar形式(-Ft)で取得したバックアップは、展開してから使用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 1. PostgreSQLを停止
sudo systemctl stop postgresql

# 2. 既存のデータディレクトリをバックアップ
sudo mv /var/lib/postgresql/16/main /var/lib/postgresql/16/main.old

# 3. 新しいデータディレクトリを作成
sudo mkdir /var/lib/postgresql/16/main

# 4. バックアップを展開
sudo tar xzf /backup/base.tar.gz -C /var/lib/postgresql/16/main

# 5. WALを展開(別ファイルの場合)
sudo tar xzf /backup/pg_wal.tar.gz -C /var/lib/postgresql/16/main/pg_wal

# 6. 所有者を変更
sudo chown -R postgres:postgres /var/lib/postgresql/16/main

# 7. PostgreSQLを起動
sudo systemctl start postgresql

ポイントインタイムリカバリ(PITR)

ポイントインタイムリカバリ(PITR: Point-In-Time Recovery)は、物理バックアップとWALアーカイブを組み合わせることで、任意の時点にデータベースを復元する機能です。

PITRの仕組み

flowchart LR
    A[ベースバックアップ<br/>1/1 00:00] --> B[WALアーカイブ]
    B --> C[リカバリ対象時点<br/>1/3 14:30]
    
    subgraph PITR
        D[ベースバックアップを<br/>リストア] --> E[WALを順次適用]
        E --> F[指定時点で停止]
    end

PITRの流れは以下の通りです。

  1. ベースバックアップをリストア
  2. アーカイブされたWALを順次適用(リプレイ)
  3. 指定した時点(時刻、トランザクションID、リカバリポイント)で停止
  4. 通常運用を再開

WALアーカイブの設定

PITRを実現するには、WALアーカイブを有効にする必要があります。

1
2
3
# postgresql.confの設定
archive_mode = on
archive_command = 'cp %p /backup/wal_archive/%f'

より堅牢な構成では、archive_commandにrsyncやクラウドストレージへのアップロードコマンドを指定します。

1
2
3
4
5
# S3へのアーカイブ例(AWS CLI使用)
archive_command = 'aws s3 cp %p s3://my-backup-bucket/wal/%f'

# リモートサーバーへのアーカイブ例
archive_command = 'rsync -a %p backup-server:/backup/wal_archive/%f'

設定変更後はPostgreSQLを再起動してください。

1
sudo systemctl restart postgresql

PITRの実行手順

特定の時点に復元する手順を示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1. PostgreSQLを停止
sudo systemctl stop postgresql

# 2. 既存のデータディレクトリをバックアップ
sudo mv /var/lib/postgresql/16/main /var/lib/postgresql/16/main.old

# 3. ベースバックアップをリストア
sudo mkdir /var/lib/postgresql/16/main
sudo tar xzf /backup/base.tar.gz -C /var/lib/postgresql/16/main

# 4. リカバリ設定ファイルを作成
sudo cat > /var/lib/postgresql/16/main/postgresql.auto.conf << 'EOF'
restore_command = 'cp /backup/wal_archive/%f %p'
recovery_target_time = '2026-01-03 14:30:00+09'
recovery_target_action = 'promote'
EOF

# 5. リカバリシグナルファイルを作成
sudo touch /var/lib/postgresql/16/main/recovery.signal

# 6. 所有者を変更
sudo chown -R postgres:postgres /var/lib/postgresql/16/main

# 7. PostgreSQLを起動(リカバリが自動的に開始される)
sudo systemctl start postgresql

# 8. リカバリの進捗を確認
sudo tail -f /var/log/postgresql/postgresql-16-main.log

リカバリターゲットの指定方法

リカバリを停止する時点を指定するオプションは複数あります。

パラメータ 説明
recovery_target_time 指定時刻まで復元 ‘2026-01-03 14:30:00+09’
recovery_target_xid 指定トランザクションIDまで復元 ‘12345678’
recovery_target_lsn 指定LSNまで復元 ‘0/1234567’
recovery_target_name 指定リストアポイントまで復元 ‘before_migration’
recovery_target_inclusive ターゲットを含むか on / off
recovery_target_action リカバリ完了後のアクション pause / promote / shutdown

リストアポイントの作成

重要な作業の前にリストアポイントを作成しておくと、PITRで簡単にその時点に戻ることができます。

1
2
3
4
5
6
7
-- リストアポイントを作成
SELECT pg_create_restore_point('before_migration');

-- 結果例:
--  pg_create_restore_point
-- -------------------------
--  0/12345678

バックアップの自動化

手動でバックアップを実行することは現実的ではありません。cronを使ってバックアップを自動化する方法を解説します。

cronによる論理バックアップの自動化

まず、バックアップスクリプトを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/bin/bash
# /usr/local/bin/pg_backup.sh

# 設定
BACKUP_DIR="/backup/postgresql"
RETENTION_DAYS=7
DATABASES="mydb1 mydb2"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/pg_backup.log"

# ログ関数
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE"
}

log "=== バックアップ開始 ==="

# バックアップディレクトリの作成
mkdir -p "$BACKUP_DIR"

# グローバルオブジェクトのバックアップ
log "グローバルオブジェクトをバックアップ中..."
pg_dumpall -h localhost -U postgres --globals-only \
    > "$BACKUP_DIR/globals_$TIMESTAMP.sql" 2>> "$LOG_FILE"

if [ $? -eq 0 ]; then
    log "グローバルオブジェクトのバックアップ成功"
else
    log "エラー: グローバルオブジェクトのバックアップ失敗"
fi

# 各データベースのバックアップ
for DB in $DATABASES; do
    log "$DB をバックアップ中..."
    pg_dump -h localhost -U postgres -Fc \
        -f "$BACKUP_DIR/${DB}_$TIMESTAMP.dump" "$DB" 2>> "$LOG_FILE"
    
    if [ $? -eq 0 ]; then
        log "$DB のバックアップ成功"
    else
        log "エラー: $DB のバックアップ失敗"
    fi
done

# 古いバックアップの削除
log "古いバックアップを削除中..."
find "$BACKUP_DIR" -name "*.dump" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "*.sql" -mtime +$RETENTION_DAYS -delete

log "=== バックアップ完了 ==="

スクリプトに実行権限を付与します。

1
sudo chmod +x /usr/local/bin/pg_backup.sh

cronに登録します。

1
2
3
4
5
# postgres ユーザーのcrontabを編集
sudo -u postgres crontab -e

# 毎日午前2時にバックアップを実行
0 2 * * * /usr/local/bin/pg_backup.sh

cronによる物理バックアップの自動化

物理バックアップも同様に自動化できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
# /usr/local/bin/pg_basebackup.sh

# 設定
BACKUP_DIR="/backup/postgresql/base"
RETENTION_DAYS=7
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/pg_basebackup.log"

# ログ関数
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE"
}

log "=== 物理バックアップ開始 ==="

# バックアップディレクトリの作成
mkdir -p "$BACKUP_DIR"

# 物理バックアップの実行
log "pg_basebackupを実行中..."
pg_basebackup -h localhost -U postgres \
    -D "$BACKUP_DIR/base_$TIMESTAMP" \
    -Ft -z -P --checkpoint=fast -X stream \
    2>> "$LOG_FILE"

if [ $? -eq 0 ]; then
    log "物理バックアップ成功"
else
    log "エラー: 物理バックアップ失敗"
    exit 1
fi

# 古いバックアップの削除
log "古いバックアップを削除中..."
find "$BACKUP_DIR" -maxdepth 1 -type d -name "base_*" -mtime +$RETENTION_DAYS -exec rm -rf {} \;

log "=== 物理バックアップ完了 ==="

cronへの登録例:

1
2
# 毎週日曜日の午前3時に物理バックアップを実行
0 3 * * 0 /usr/local/bin/pg_basebackup.sh

パスワードなしでのバックアップ実行

cronでバックアップを自動実行する際、パスワード入力を回避する方法があります。

方法1: .pgpassファイルを使用

1
2
3
4
5
6
7
# postgresユーザーのホームディレクトリに.pgpassを作成
sudo -u postgres bash -c 'cat > ~/.pgpass << EOF
localhost:5432:*:postgres:your_password
EOF'

# パーミッションを設定(必須)
sudo -u postgres chmod 600 ~/.pgpass

方法2: peer認証を使用(ローカル接続の場合)

pg_hba.confでpeer認証が設定されていれば、ローカルからpostgresユーザーとして接続する際にパスワードは不要です。

1
2
# pg_hba.conf
local   all             postgres                                peer

バックアップ戦略の設計

システム要件に応じた適切なバックアップ戦略を設計することが重要です。ここでは、代表的なパターンを紹介します。

小規模システム向け戦略

データ量が少なく(数GB程度)、リカバリ時間に余裕がある環境向けの戦略です。

flowchart TD
    subgraph 日次バックアップ
        A[毎日深夜] --> B[pg_dump<br/>カスタム形式]
        B --> C[ローカルストレージ]
        C --> D[クラウドストレージに同期]
    end
    
    subgraph 保持ポリシー
        E[日次: 7日間保持]
        F[週次: 4週間保持]
        G[月次: 12ヶ月保持]
    end

設定例:

項目 設定
バックアップ方式 pg_dump(カスタム形式)
頻度 毎日深夜
保持期間 7日間
保存先 ローカル + クラウドストレージ
RPO(目標復旧時点) 24時間
RTO(目標復旧時間) 数時間

中規模システム向け戦略

データ量が中程度(数十GB〜数百GB)で、ある程度のリカバリ要件がある環境向けの戦略です。

flowchart TD
    subgraph 週次ベースバックアップ
        A[毎週日曜深夜] --> B[pg_basebackup]
        B --> C[物理バックアップ]
    end
    
    subgraph 日次論理バックアップ
        D[毎日深夜] --> E[pg_dump]
        E --> F[論理バックアップ]
    end
    
    subgraph 継続的WALアーカイブ
        G[リアルタイム] --> H[WALアーカイブ]
    end
    
    C --> I[クラウドストレージ]
    F --> I
    H --> I

設定例:

項目 設定
物理バックアップ 毎週日曜日にpg_basebackup
論理バックアップ 毎日pg_dump
WALアーカイブ 継続的にアーカイブ
RPO 数分〜数十分(WALアーカイブ間隔に依存)
RTO 1〜2時間

大規模・ミッションクリティカルシステム向け戦略

データ量が大きく(数TB以上)、ダウンタイムが許容されない環境向けの戦略です。

flowchart TD
    subgraph プライマリ
        A[PostgreSQL<br/>プライマリ]
    end
    
    subgraph スタンバイ
        B[同期レプリカ]
        C[非同期レプリカ]
    end
    
    subgraph バックアップ
        D[pg_basebackup<br/>日次]
        E[WALアーカイブ<br/>継続的]
    end
    
    A --> B
    A --> C
    C --> D
    A --> E
    
    subgraph 保存先
        F[プライマリサイト]
        G[DRサイト]
        H[クラウドストレージ]
    end
    
    D --> F
    D --> G
    E --> H

設定例:

項目 設定
レプリケーション 同期1台 + 非同期1台以上
物理バックアップ 非同期レプリカから日次取得
WALアーカイブ S3等に継続的アーカイブ
DRサイト 地理的に離れた場所にレプリカ配置
RPO 0〜数秒(同期レプリケーション)
RTO 数分(自動フェイルオーバー)

バックアップ戦略設計のチェックリスト

バックアップ戦略を設計する際に確認すべき項目をまとめます。

  • データ量と増加率を把握しているか
  • RPO(許容できるデータ損失量)を定義しているか
  • RTO(許容できるダウンタイム)を定義しているか
  • バックアップの保存先は冗長化されているか
  • バックアップからのリストアテストを定期的に実施しているか
  • バックアップの整合性検証を行っているか
  • バックアップの暗号化は必要か
  • 法令・コンプライアンス要件(データ保持期間等)を満たしているか
  • 障害発生時の復旧手順書は準備されているか
  • 担当者以外でも復旧作業ができるか

まとめ

本記事では、PostgreSQLのバックアップ戦略について、論理バックアップ(pg_dump/pg_dumpall)と物理バックアップ(pg_basebackup)の違いから、リストア手順、自動化、戦略設計まで解説しました。

重要なポイントを振り返ります。

  • 論理バックアップはバージョン間移行や部分リストアに適している
  • 物理バックアップは大規模データベースの高速バックアップ・リストアに適している
  • PITRを実現するには物理バックアップとWALアーカイブの組み合わせが必要
  • バックアップは自動化し、定期的にリストアテストを実施することが重要
  • システム要件(RPO/RTO)に応じたバックアップ戦略の設計が不可欠

バックアップは「取得すること」がゴールではありません。実際に障害が発生したときに、確実にリストアできることが最も重要です。定期的なリストアテストと手順書の整備を怠らないようにしてください。

参考リンク