PostgreSQLをpg_dumpとpg_restoreでバックアップする手順|論理バックアップの取得と復元の実務

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Linuxtips > データーベース管理 > PostgreSQLをpg_dumpとpg_restoreでバックアップする手順|論理バックアップの取得と復元の実務
「pg_dumpでバックアップを取っているはずなのに、復元できなかった」「カスタム形式とプレーンSQL、どちらを使えばいいのか迷う」——PostgreSQLのバックアップ・リストア手順で悩む現場エンジニアは少なくないはずです。

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ファイルでパスワードを安全に管理する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

論理バックアップとは何か——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

出力された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 の目安はCPUコア数と同じか、少し少なめの値です。並列数を増やすほどバックアップは速くなりますが、DBサーバーのCPU・IO負荷も上がります。本番稼働中に実行する場合は -j 2~4 程度から試してください。

ディレクトリ形式のリストアも -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

pg_dumpall の出力はプレーン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)

並列リストアで時間を短縮する(大規模DBで有効):

# -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

バックアップ後のファイルサイズが著しく小さい(数KB程度)場合は、ダンプが途中で失敗している可能性があります。スクリプトの末尾で 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)

カスタム形式(-Fc)のダンプサイズは、圧縮率にもよりますが実DBサイズの30~50%程度になることが多いです。上記の例なら約2.5GB~4.3GBが必要です。バックアップ先に余裕があることを確認してから実行してください。

本記事のまとめ

やりたいこと コマンド
単一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
pg_dumpのカスタム形式(-Fc)はファイルサイズ・選択的リストア・並列化のすべての面でプレーンSQLより優れています。数十GB以上の大規模DBではディレクトリ形式(-Fd)+並列バックアップも検討してください。まだプレーンSQL形式を使っている場合は、次回のバックアップからカスタム形式に切り替えることを検討してください。cronによる自動化と組み合わせて、定期的なリストアテストも忘れずに行いましょう。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアがpg_dump・pg_restoreを含むLinuxサーバー上でのデータベース運用スキルを実践形式で教えます。
Linux Master Pro Seminar の詳細を見る >>

<PR>手元に置いて学びを深める1冊

PostgreSQL実践入門 ──アーキテクチャ、運用監視、性能改善

まず無料メルマガで学ぶのが第一歩、加えてpg_dump・pg_restoreを含むバックアップ設計から性能改善まで体系的に身につけるなら本書が一冊目の選択肢になる。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。