PostgreSQLには標準で pg_dump と pg_restore というツールが付属しています。MySQLの
mysqldump に相当する論理バックアップツールですが、カスタム形式(-Fc)・ディレクトリ形式(-Fd)・並列バックアップ(-j N)・並列リストアなど、より柔軟な運用オプションを備えています。この記事では、pg_dump / pg_restore の実践的な使い方をRHEL 9.4 / Ubuntu 24.04 LTS(PostgreSQL 16)の実環境出力例を交えて解説します。単一DBのダンプから全DB一括バックアップ(pg_dumpall)・cronによる自動化・別サーバーへの移行・リストア失敗時の対処まで網羅します。
この記事のポイント
・pg_dump -Fc(カスタム形式)が本番運用での推奨フォーマット
・pg_dump -Fd -j N でディレクトリ形式の並列バックアップも可能(大規模DB向け)
・pg_restore -j N で並列リストアするとリストア時間を大幅短縮できる
・全DBを一括バックアップするにはpg_dumpallを使う
・cronで自動化する際は.pgpassファイルでパスワードを安全に管理する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
論理バックアップとは何か——pg_dumpが守れる範囲と守れない範囲
pg_dumpは 論理バックアップ ツールです。テーブル定義・データ・インデックス・シーケンスなどのDB内容をSQL文や独自形式で書き出します。物理バックアップ(ファイルシステムレベルのコピー)とは異なる特性を持ちます。論理バックアップが得意なこと:
・特定のデータベース・テーブルだけを取り出せる
・異なるPostgreSQLバージョン間での移行に使える
・異なるOS・アーキテクチャへの移行が可能
・圧縮率が高い(カスタム形式で自動圧縮)
論理バックアップの限界:
・ダンプ取得時点のスナップショットのため、その後のトランザクションは含まれない
・テラバイト級の超大規模DBではダンプ・リストアに時間がかかる
・ポイントインタイムリカバリ(PITR)はWALアーカイブと組み合わせた物理バックアップが適切
一般的なWebサービスやバッチシステムのデータベース(数GB~数十GB規模)では、pg_dumpによる論理バックアップが十分な選択肢です。
バックアップ前のひと手間:テーブルサイズとデッドタプルの確認
大量のDELETE・UPDATEが繰り返される環境では、テーブルにデッドタプル(削除済みの行)が蓄積してダンプファイルが肥大化することがあります。定期バックアップの前に以下のクエリでテーブル状態を確認し、膨張が目立つ場合はVACUUMをかけておくと、ダンプサイズと所要時間を削減できます。
-- デッドタプルが多いテーブルを確認(上位10件) SELECT schemaname, tablename, n_dead_tup, n_live_tup, to_char(last_autovacuum, 'YYYY-MM-DD HH24:MI') AS last_autovacuum FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 10;
schemaname | tablename | n_dead_tup | n_live_tup | last_autovacuum ------------+--------------+------------+------------+--------------------- public | order_items | 48203 | 195820 | 2026-08-23 03:12 public | sessions | 21400 | 63500 | 2026-08-23 03:12 public | products | 412 | 15800 | 2026-08-24 01:30
n_dead_tup がライブ行数の20%を超えているテーブルは、バックアップ前にVACUUMをかけておくと効果的です。VACUUMはautovacuumが自動で処理しますが、バルクDELETE直後など急を要する場合は sudo -u postgres vacuumdb -d mydb -t order_items で個別に実行できます。pg_dumpの基本的な使い方
1. 単一データベースをプレーンSQLでバックアップする
最もシンプルなバックアップ方法です。出力はSQL文のテキストファイルになります。# postgresユーザーに切り替えて実行 sudo -u postgres pg_dump mydb > /var/lib/pgsql/backup/mydb_20260824.sql # -f オプションで出力ファイルを指定する書き方でも同じ結果 sudo -u postgres pg_dump mydb -f /var/lib/pgsql/backup/mydb_20260824.sql
$ head -16 /var/lib/pgsql/backup/mydb_20260824.sql -- -- PostgreSQL database dump -- -- Dumped from database version 16.3 -- Dumped by pg_dump version 16.3 SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; SELECT pg_catalog.set_config('search_path', '', false); SET check_function_bodies = false; SET xmloption = content; SET client_min_messages = warning; SET row_security = off;
2. カスタム形式(-Fc)でバックアップする(推奨)
本番環境では カスタム形式(-Fc) を使うことを強く推奨します。理由は以下の3つです。・自動圧縮でファイルサイズがプレーンSQLの約30~50%に抑えられる
・pg_restoreで特定のテーブルだけを選択してリストアできる
・並列リストア(-j N)が使えて大規模DBでも短時間で復元できる
# カスタム形式でダンプ(拡張子は .dump が慣例) sudo -u postgres pg_dump -Fc mydb -f /var/lib/pgsql/backup/mydb_20260824.dump # ファイルサイズを確認(プレーンSQLより大幅に小さい) ls -lh /var/lib/pgsql/backup/mydb_20260824.dump -rw-r--r-- 1 postgres postgres 4.2M Aug 24 09:00 /var/lib/pgsql/backup/mydb_20260824.dump
・-Fc: カスタム形式(圧縮済み・pg_restore専用)
・-Fp: プレーンSQL形式(テキスト・psqlでリストア可能、デフォルト)
・-Fd: ディレクトリ形式(-j N による並列バックアップに対応)
・-t テーブル名: 特定のテーブルだけをダンプ
・-s: スキーマ(テーブル定義)のみダンプ(データなし)
・-a: データのみダンプ(スキーマなし)
・-Z 0~9: 圧縮レベル(0=無圧縮、9=最大圧縮、デフォルトは6)
特定テーブルだけをバックアップする場合:
# ordersテーブルだけをカスタム形式でダンプ sudo -u postgres pg_dump -Fc -t orders mydb -f /var/lib/pgsql/backup/mydb_orders_20260824.dump
3. ディレクトリ形式(-Fd)で並列バックアップする(大規模DB向け)
数十GB以上の大規模DBでバックアップ時間を短縮したい場合は、ディレクトリ形式(-Fd) と -j N を組み合わせた並列バックアップが有効です。各テーブルのデータを複数のファイルに分割して並列に書き出します。# ディレクトリ形式で4並列バックアップ(-f にはディレクトリ名を指定) sudo -u postgres pg_dump -Fd -j 4 mydb -f /var/lib/pgsql/backup/mydb_20260824_dir # バックアップ先ディレクトリの中身を確認 ls /var/lib/pgsql/backup/mydb_20260824_dir/ toc.dat 3716.dat.gz 3717.dat.gz 3718.dat.gz 3719.dat.gz
ディレクトリ形式のリストアも -j N が使えます(後述)。カスタム形式(-Fc)よりも大規模DBでのバックアップ・リストア速度が優れている場面が多いため、数十GB以上の環境では検討する価値があります。
4. 全データベースを一括バックアップする(pg_dumpall)
複数のデータベースとロール情報・テーブルスペース設定を含む全体バックアップには pg_dumpall を使います。# 全データベースとロール情報をダンプ(プレーンSQL形式のみ対応) sudo -u postgres pg_dumpall -f /var/lib/pgsql/backup/all_databases_20260824.sql # ファイルサイズを確認 ls -lh /var/lib/pgsql/backup/all_databases_20260824.sql -rw-r--r-- 1 postgres postgres 28M Aug 24 09:05 /var/lib/pgsql/backup/all_databases_20260824.sql
psql コマンドで行います。ロール情報だけを別途バックアップしたい場合:
# ロール(ユーザー・グループ)定義のみを取り出す sudo -u postgres pg_dumpall -g -f /var/lib/pgsql/backup/roles_20260824.sql
pg_restoreで復元する手順
1. カスタム形式(-Fc)のダンプを復元する
カスタム形式のダンプはpg_restore コマンドでリストアします。リストア先のデータベースをあらかじめ作成しておく必要があります。# リストア先DBを作成 sudo -u postgres createdb mydb_restore # pg_restoreでリストア(-d でリストア先DBを指定) sudo -u postgres pg_restore -d mydb_restore /var/lib/pgsql/backup/mydb_20260824.dump # 完了後にデータ件数を確認 sudo -u postgres psql -d mydb_restore -c "SELECT schemaname, tablename, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC LIMIT 5;" schemaname | tablename | n_live_tup --------------+-------------+------------ public | orders | 125847 public | users | 45231 public | products | 3812 public | categories | 148 public | sessions | 87654 (5 rows)
# -j 4 で4並列リストア(CPUコア数に合わせて調整。-Fc/-Fd形式のみ対応) sudo -u postgres pg_restore -d mydb_restore -j 4 /var/lib/pgsql/backup/mydb_20260824.dump # ディレクトリ形式(-Fd)のリストアも同様 sudo -u postgres pg_restore -d mydb_restore -j 4 /var/lib/pgsql/backup/mydb_20260824_dir/
# ordersテーブルのみをリストア(カスタム形式の利点) sudo -u postgres pg_restore -d mydb_restore -t orders /var/lib/pgsql/backup/mydb_20260824.dump
2. プレーンSQL(-Fp)ダンプを復元する
プレーンSQL形式のダンプはpg_restore ではなく psql コマンドでリストアします。# プレーンSQL形式のリストア(リストア先DBを事前に作成しておく) sudo -u postgres createdb mydb_restore sudo -u postgres psql -d mydb_restore -f /var/lib/pgsql/backup/mydb_20260824.sql # pg_dumpall の全DB一括ダンプをリストア(DB作成コマンドも含まれる) sudo -u postgres psql -f /var/lib/pgsql/backup/all_databases_20260824.sql
3. 別サーバーへデータを移行する
pg_dumpとpg_restoreはパイプで接続できるため、ダンプファイルを作成せずに旧サーバーから新サーバーへ直接転送できます。# 旧サーバーで実行: カスタム形式でダンプしてSSH経由で新サーバーへ転送 sudo -u postgres pg_dump -Fc mydb | ssh new-server "sudo -u postgres pg_restore -d mydb_new -" # または新サーバー側から旧サーバー(192.168.1.10)に接続してpg_dumpを実行 pg_dump -h 192.168.1.10 -U postgres -Fc mydb | pg_restore -d mydb_new -
cronで自動バックアップを設定する
1. .pgpassでパスワードを安全に管理する
cronでpg_dumpを自動実行する場合、パスワードをシェルスクリプト内に直接書くのは避けるべきです。PostgreSQLが提供する .pgpass ファイルを使うと、パスワードをファイルとして安全に管理できます。# postgresユーザーのホームディレクトリに .pgpass を作成 # 形式: hostname:port:database:username:password echo "localhost:5432:mydb:backup_user:バックアップ用パスワード" > /var/lib/pgsql/.pgpass chmod 600 /var/lib/pgsql/.pgpass chown postgres:postgres /var/lib/pgsql/.pgpass
2. バックアップシェルスクリプトを作成する
# /usr/local/bin/pg_backup.sh として作成 #!/bin/bash BACKUP_DIR="/var/lib/pgsql/backup" DB_NAME="mydb" DATE=$(date +%Y%m%d) BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${DATE}.dump" # バックアップ取得(カスタム形式) pg_dump -U backup_user -Fc "${DB_NAME}" -f "${BACKUP_FILE}" # 7日より古いバックアップを削除(世代管理) find "${BACKUP_DIR}" -name "${DB_NAME}_*.dump" -mtime +7 -delete # バックアップサイズをログに記録 ls -lh "${BACKUP_FILE}" >> "${BACKUP_DIR}/backup.log"
# スクリプトに実行権限を付与 chmod 755 /usr/local/bin/pg_backup.sh chown postgres:postgres /usr/local/bin/pg_backup.sh # postgresユーザーのcrontabに登録(毎日02:00に実行) sudo -u postgres crontab -e # 以下の1行を追加して保存 0 2 * * * /usr/local/bin/pg_backup.sh
3. バックアップファイルの整合性を確認する
定期的にリストアテストを行うのが理想ですが、最低限ダンプファイルが破損していないかを確認できます。# カスタム形式の内容一覧を表示(エラーなく表示できれば破損なし) sudo -u postgres pg_restore -l /var/lib/pgsql/backup/mydb_20260824.dump | head -20 ; ; Archive created at 2026-08-24 02:00:15 JST ; dbname: mydb ; TOC Entries: 38 ; Compression: 6 ; Dump Version: 1.14-0 ; Format: CUSTOM ; Integer: 4 bytes ; Offset: 8 bytes ; Dumped from database version: 16.3 ; Dumped by pg_dump version: 16.3 ; ; Selected TOC Entries: ; 225; 1259 16384 TABLE public orders postgres 226; 1259 16392 TABLE public users postgres 227; 1259 16401 TABLE public products postgres 228; 1259 16410 TABLE public categories postgres 229; 1259 16419 TABLE public sessions postgres
pg_dump の終了コードを確認する仕組みを入れておくと安心です。# pg_dumpの終了コードをチェックしてメール通知する例 pg_dump -U backup_user -Fc "${DB_NAME}" -f "${BACKUP_FILE}" if [ $? -ne 0 ]; then echo "pg_dump failed on $(date)" | mail -s "BACKUP ERROR: ${DB_NAME}" admin@example.com fi
トラブルシュートとエラー対処
1. pg_dump: error: connection to server on socket failed
原因: PostgreSQLサービスが停止しているか、実行ユーザーにソケット接続権限がない。対処:
systemctl status postgresql-16 でサービスの状態を確認し、停止していれば起動する。また、pg_dumpを実行しているユーザーが postgres ロールとして接続できるかを psql で確認する。# サービス状態の確認 systemctl status postgresql-16 # RHEL 9.4での正常な出力例 * postgresql-16.service - PostgreSQL 16 Database Server Loaded: loaded (/usr/lib/systemd/system/postgresql-16.service; enabled) Active: active (running) since Sun 2026-08-24 09:00:01 JST; 2h 5min ago # 接続確認 sudo -u postgres psql -c "\conninfo" You are connected to database "postgres" as user "postgres" via socket in "/var/run/postgresql" at port "5432".
2. pg_restore: error: could not execute query: ERROR: relation already exists
原因: リストア先のデータベースに同名のテーブルが既に存在している。対処1:
pg_restore --clean オプションを付けると、オブジェクト作成前に DROP 文を発行してくれる(最も手軽)。対処2: リストア先DBを一度削除して再作成してからリストアする(確実)。
# --clean で既存オブジェクトをDROPしてから再作成 sudo -u postgres pg_restore --clean -d mydb_restore /var/lib/pgsql/backup/mydb_20260824.dump # または リストア先DBを削除→再作成してからリストア(より確実) sudo -u postgres dropdb mydb_restore sudo -u postgres createdb mydb_restore sudo -u postgres pg_restore -d mydb_restore /var/lib/pgsql/backup/mydb_20260824.dump
3. pg_dump: error: query failed: ERROR: permission denied for table xxx
原因: バックアップに使っているユーザーが、対象テーブルへのSELECT権限を持っていない。対処:
postgres スーパーユーザーでダンプを実行するか、バックアップ専用ユーザーに必要な権限を付与する。# バックアップ専用ユーザーにSELECT権限を付与する例 sudo -u postgres psql -d mydb mydb=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO backup_user; GRANT mydb=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO backup_user; ALTER DEFAULT PRIVILEGES
4. 「No space left on device」でダンプが途中で失敗する
原因: バックアップ先ディスクの容量不足、またはinode枯渇。対処:
df -h でディスク空き容量を、df -i でinode使用率を確認する。カスタム形式(-Fc)は自動圧縮が効くためプレーンSQLより大幅にファイルサイズを削減できる。古い世代のバックアップを削除して空き容量を確保するか、バックアップ先を別ディスクに変更する。また、ディスク残量の確認にはバックアップ実行前のチェックも効果的です。
# バックアップ前にディスク空き容量と想定ダンプサイズを確認 df -h /var/lib/pgsql/backup # 実際のDBサイズを確認(ダンプ後のファイルサイズの目安になる) sudo -u postgres psql -c "SELECT pg_size_pretty(pg_database_size('mydb'));" pg_size_pretty ---------------- 8543 MB (1 row)
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| 単一DBをカスタム形式でバックアップ | pg_dump -Fc mydb -f mydb.dump |
| 単一DBをプレーンSQLでバックアップ | pg_dump mydb -f mydb.sql |
| 特定テーブルだけをバックアップ | pg_dump -Fc -t テーブル名 mydb -f tbl.dump |
| ディレクトリ形式で並列バックアップ | pg_dump -Fd -j 4 mydb -f mydb_dir/ |
| 全DBを一括バックアップ | pg_dumpall -f all_db.sql |
| カスタム形式ダンプをリストア | pg_restore -d mydb mydb.dump |
| 並列リストアで高速化 | pg_restore -d mydb -j 4 mydb.dump |
| プレーンSQLダンプをリストア | psql -d mydb -f mydb.sql |
| ダンプ内容の一覧表示(破損確認) | pg_restore -l mydb.dump |
| 既存オブジェクトをDROPしてリストア | pg_restore --clean -d mydb mydb.dump |
Linux Master Pro Seminar の詳細を見る >>
<PR>手元に置いて学びを深める1冊
PostgreSQL実践入門 ──アーキテクチャ、運用監視、性能改善
まず無料メルマガで学ぶのが第一歩、加えてpg_dump・pg_restoreを含むバックアップ設計から性能改善まで体系的に身につけるなら本書が一冊目の選択肢になる。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 次のページへ:PostgreSQLのVACUUMとautovacuum運用設計|テーブル肥大化とXID周回を防ぐ設定の考え方
- 前のページへ:pg_hba.confで接続認証を設計する方法|PostgreSQLに接続できない原因の切り分けとscram-sha-256設定
- この記事の属するカテゴリ:データーベース管理へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます