PostgreSQLのストリーミングレプリケーションを構築する手順|pg_basebackupからスタンバイ昇格まで

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtipsデーターベース管理 > PostgreSQLのストリーミングレプリケーションを構築する手順|pg_basebackupからスタンバイ昇格まで
「pg_basebackupは正常終了したのに、プライマリ側のpg_stat_replicationに何も表示されない」「PostgreSQL 12以降でrecovery.confが廃止されたと聞いたが、代わりに何を設定すればよいのか分からない」——こうした疑問をそのままにしていると、本番環境のレプリケーション構築で同じ場所で詰まることになります。

PostgreSQLのストリーミングレプリケーションは、WAL(Write-Ahead Log)をプライマリからスタンバイへリアルタイムで転送し続け、データの複製を維持する仕組みです。RDS・Aurora・Cloud SQLのようなマネージドサービスがボタン1つでリードレプリカを作れるのに対し、Linuxサーバーを自前で運用する環境では、設定の意味を理解していないと障害時に即座に対処できません。

この記事では、Rocky Linux 9 / PostgreSQL 16 の2台構成(プライマリ1台・スタンバイ1台)を例に、ストリーミングレプリケーションの全手順を実際のコマンド出力とともに解説します。pg_basebackupでのベースバックアップ取得、standby.signalによる自動レプリケーション開始、pg_stat_replicationでの同期確認、そして障害時のスタンバイ昇格(フェイルオーバー)まで一気通貫でカバーします。

この記事のポイント

・pg_basebackup -R でstandby.signalとprimary_conninfoが自動生成される
・プライマリ側はwal_level・max_wal_senders・pg_hba.confの3か所を設定する
・pg_stat_replicationのstateが「streaming」になれば同期成立の合図
・スタンバイ昇格はpg_ctl promoteまたはSELECT pg_promote()で実行できる


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

ストリーミングレプリケーションの仕組みと構成イメージ

ストリーミングレプリケーションでは、プライマリサーバーがWAL(トランザクションログ)をWAL送信プロセス(walsender)経由でスタンバイへ継続的に転送します。スタンバイ側はWAL受信プロセス(walreceiver)で受け取り、データに適用することでプライマリと同じ状態を維持します。

構成はシンプルで、必要なのはLinuxサーバー2台とPostgreSQLのみです。

プライマリ:読み書き可能。WALを生成してスタンバイへ送信する。
スタンバイ:読み取り専用(hot_standby=on の場合)。WALを受信してリカバリ状態で動作する。

PostgreSQL 12以降は、これまでの recovery.conf が廃止されています。代わりに、データディレクトリ直下に空のファイル「standby.signal」を置くことでスタンバイモードに入ります。接続先プライマリの情報は postgresql.auto.conf の primary_conninfo に書きます。pg_basebackup に -R オプションを付けると、この2ファイルを自動生成してくれるため、手動作業の手間を大幅に減らせます。

この記事で使う検証環境は以下のとおりです。

・OS: Rocky Linux 9.4
・PostgreSQL: 16.4(PGDGリポジトリ)
・プライマリ: 192.168.10.101(ホスト名: pg-primary)
・スタンバイ: 192.168.10.102(ホスト名: pg-standby)
・データディレクトリ: /var/lib/pgsql/16/data

構築前の確認事項(OS・ポート・PostgreSQLバージョン)

作業を始める前に、両サーバーで以下を確認します。

PostgreSQLのバージョンが一致しているか確認する

プライマリとスタンバイのメジャーバージョンは同一でなければなりません(マイナーバージョンのズレは許容されますが、できれば揃えてください)。

# 両サーバーで実行して同じメジャーバージョンであることを確認する psql --version psql (PostgreSQL) 16.4

ポート5432がプライマリで待受中かを確認する

スタンバイからの接続を受け付けるため、プライマリの5432番ポートが開いている必要があります。Linux ポート確認の全コマンドで詳しく解説していますが、ss コマンドで素早く確認できます。

# プライマリ側で実行 ss -tlnp | grep 5432 LISTEN 0 128 0.0.0.0:5432 0.0.0.0:* users:(("postgres",pid=2341,fd=5)) LISTEN 0 128 [::]:5432 [::]:* users:(("postgres",pid=2341,fd=5))

0.0.0.0:5432 と [::]:5432 の両方が LISTEN になっていれば問題ありません。

ファイアウォールでスタンバイからの5432番アクセスを許可する

# プライマリ側でfirewalldを使っている場合 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.102/32" port protocol="tcp" port="5432" accept' firewall-cmd --reload # 設定確認 firewall-cmd --list-all | grep rich

プライマリサーバーを設定する

プライマリ側の変更は3か所です。postgresql.conf でWAL送信を有効化し、pg_hba.conf でスタンバイからの接続を許可し、レプリケーション専用ロールを作成します。

1. postgresql.confでWAL送信設定を有効化する

postgresql.conf を開き、以下の3パラメータを設定します。

# /var/lib/pgsql/16/data/postgresql.conf # WALの記録レベルをreplicaに上げる(デフォルトはreplica、念のため明示する) wal_level = replica # WAL送信プロセスの最大数(スタンバイ台数+余裕を持たせる) max_wal_senders = 5 # スタンバイが遅延した際に溜め置くWALの最大サイズ(PostgreSQL 13以降) wal_keep_size = 256

wal_keep_size の単位はMBです。256 と書くと256MBになります。スタンバイが一時的にプライマリから切り離された際に、WALセグメントが削除されてスタンバイが追いつけなくなる事態を防ぐためのバッファです。

PostgreSQL 12以前を使っている場合は wal_keep_segments(セグメント数指定)が使われていましたが、13以降は wal_keep_size に統一されています。

2. pg_hba.confでレプリケーション接続を許可する

pg_hba.conf の末尾にレプリケーション専用の許可行を追加します。

# /var/lib/pgsql/16/data/pg_hba.conf の末尾に追加 # TYPE DATABASE USER ADDRESS METHOD host replication replicator 192.168.10.102/32 scram-sha-256

DATABASE列に "replication" と書くのが重要なポイントです。通常のデータベース名ではなく、レプリケーション接続専用のキーワードです。ADDRESS列には、スタンバイサーバーのIPアドレスを/32(単一ホスト)で指定します。

pg_hba.conf の詳細な設定方法は別記事「pg_hba.confで接続認証を設計する方法」でも解説しています。

3. レプリケーションロールを作成してサービスを再起動する

スタンバイがプライマリへ接続する専用ロールを作成します。

# プライマリ側でpsqlに接続して実行する sudo -u postgres psql -- REPLICATION属性を持つロールを作成する CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strong_password_here'; -- 作成確認 \du replicator List of roles Role name | Attributes ------------+------------------------------------------------------------- replicator | Replication postgres=# \q

ロール作成後、postgresql.conf と pg_hba.conf の変更を反映させます。

# pg_hba.confはreloadで反映できるが、postgresql.confはrestartが必要なパラメータもある # wal_level・max_wal_senders の変更はrestartが必須 sudo systemctl restart postgresql-16 # 起動確認 sudo systemctl status postgresql-16 * postgresql-16.service - PostgreSQL 16 Database Server Loaded: loaded (/usr/lib/systemd/system/postgresql-16.service; enabled) Active: active (running) since Tue 2026-08-26 09:30:12 JST; 3s ago

pg_basebackupでスタンバイサーバーを構築する

スタンバイ側の構築はpg_basebackupコマンド1本で完結します。-R オプションを付けることで、standby.signal の作成と primary_conninfo の書き込みまで自動的に行われます。

1. スタンバイ側のデータディレクトリを空にする

pg_basebackupはデータディレクトリが空でないと失敗します。initdb で作成済みのディレクトリがある場合は先に停止・クリアしてください。

# スタンバイ側で実行する # PostgreSQLが動いていれば先に停止する sudo systemctl stop postgresql-16 # データディレクトリを空にする(既存データが消えるため慎重に) sudo rm -rf /var/lib/pgsql/16/data/* # ディレクトリが空になったことを確認 sudo ls -la /var/lib/pgsql/16/data/ total 0

2. pg_basebackupを実行してベースバックアップを取得する

スタンバイサーバー上でpg_basebackupを実行し、プライマリのデータを丸ごとコピーします。

# スタンバイ側で postgres ユーザーとして実行する sudo -u postgres pg_basebackup \ -h 192.168.10.101 \ -U replicator \ -D /var/lib/pgsql/16/data \ -R \ -Xs \ -P Password: (replicatorのパスワードを入力) 32456/32456 kB (100%), 1/1 tablespace

各オプションの意味を説明します。

-h 192.168.10.101:プライマリのIPアドレス
-U replicator:先ほど作成したレプリケーションロール
-D /var/lib/pgsql/16/data:バックアップの出力先(スタンバイのデータディレクトリ)
-R:standby.signal と primary_conninfo を自動生成する(最重要オプション)
-Xs:バックアップ中にWALをストリーミングで取得する(WALが欠落しない)
-P:進捗をパーセントで表示する

「100%」と表示されればベースバックアップの取得は完了です。

3. standby.signalとprimary_conninfoを確認する

-R オプションによって自動生成されたファイルを確認します。

# standby.signal が作成されているか確認する ls -la /var/lib/pgsql/16/data/standby.signal -rw------- 1 postgres postgres 0 Aug 26 09:42 /var/lib/pgsql/16/data/standby.signal # primary_conninfo が postgresql.auto.conf に書き込まれているか確認する cat /var/lib/pgsql/16/data/postgresql.auto.conf # Do not edit this file manually! # It will be overwritten by the ALTER SYSTEM command. primary_conninfo = 'user=replicator host=192.168.10.101 port=5432 sslmode=prefer sslcompression=0'

standby.signal は中身が空のファイルです。このファイルが存在するだけでスタンバイモードとして起動します。postgresql.auto.conf の primary_conninfo にプライマリへの接続情報が書かれていることを確認してください。

パスワードを都度入力しないよう、.pgpass ファイルで認証情報を管理する場合は以下のように設定します。

# スタンバイの postgres ユーザーのホームディレクトリに .pgpass を作成する echo "192.168.10.101:5432:replication:replicator:strong_password_here" \ | sudo -u postgres tee /var/lib/pgsql/.pgpass # パーミッションを600にする(600以外だと無視される) sudo chmod 600 /var/lib/pgsql/.pgpass sudo chown postgres:postgres /var/lib/pgsql/.pgpass

4. スタンバイを起動してpg_stat_replicationで同期を確認する

スタンバイのPostgreSQLを起動します。

# スタンバイ側で実行する sudo systemctl start postgresql-16 sudo systemctl status postgresql-16 * postgresql-16.service - PostgreSQL 16 Database Server Active: active (running) since Tue 2026-08-26 09:45:03 JST; 5s ago # スタンバイ自身がリカバリ状態にあるか確認する sudo -u postgres psql -c "SELECT pg_is_in_recovery();" pg_is_in_recovery ------------------- t (1 row)

pg_is_in_recovery() が "t"(true)を返せば、スタンバイはプライマリからWALを受け取るリカバリモードで動いています。

次にプライマリ側でレプリケーションの状態を確認します。

# プライマリ側で実行する sudo -u postgres psql -c "SELECT pid, usename, application_name, client_addr, state, sync_state FROM pg_stat_replication;" pid | usename | application_name | client_addr | state | sync_state -------+------------+------------------+----------------+-----------+------------ 14237 | replicator | walreceiver | 192.168.10.102 | streaming | async (1 row)

state が "streaming" になれば同期成立です。これはプライマリがスタンバイへWALをリアルタイム転送していることを意味します。sync_state が "async" なのは、デフォルトの非同期レプリケーションであるためで正常な動作です。

pg_stat_replication に行が表示されない場合は、スタンバイからの接続自体がプライマリへ届いていない状態です。pg_hba.conf の設定ミスやファイアウォールの問題が多いため、後述のトラブルシュートを参照してください。

PostgreSQLのレプリケーション構築は、WAL設定・pg_hba.conf・pg_basebackupの連携を正しく理解していないと障害時に手が止まります。設定の意味から障害対応の判断軸まで、現役サーバー管理者が2日間のハンズオンで直接指導します。

スタンバイをプライマリへ昇格させる(フェイルオーバー)

プライマリが障害で応答しなくなった際は、スタンバイをプライマリへ昇格させます。この操作をプロモートまたはフェイルオーバーと呼びます。

1. pg_ctl promoteまたはpg_promote()で昇格させる

昇格には2通りの方法があります。

方法A: pg_ctl promote(コマンドライン)

# スタンバイサーバー上で実行する sudo -u postgres pg_ctl promote -D /var/lib/pgsql/16/data waiting for server to promote.... done server promoted

方法B: pg_promote()(SQLから実行・PostgreSQL 12以降)

# スタンバイに接続してSQL実行でも昇格できる sudo -u postgres psql -c "SELECT pg_promote();" pg_promote ------------ t (1 row)

どちらの方法でも結果は同じです。現場では、スクリプトで自動化する場合はpg_ctl promote(戻り値で成否が判断しやすい)、手動操作やDBA権限の委譲がしやすい環境ではpg_promote()(SQLのみで完結)が選ばれます。

2. 昇格後の状態をpsqlで確認する

昇格後はpg_is_in_recovery()がfalseを返し、読み書き可能なプライマリとして動作します。

# 昇格後のスタンバイ(新プライマリ)で実行する sudo -u postgres psql -c "SELECT pg_is_in_recovery();" pg_is_in_recovery ------------------- f (1 row) # 実際に書き込みができるか確認する sudo -u postgres psql -c "CREATE TABLE failover_test (id int);" CREATE TABLE sudo -u postgres psql -c "DROP TABLE failover_test;" DROP TABLE

pg_is_in_recovery() が "f"(false)になれば昇格は完了です。standby.signal ファイルも自動的に削除されます。

昇格後に注意すること:

・旧プライマリが復旧した場合、そのままでは新プライマリに追随できません。旧プライマリを新プライマリのスタンバイとして再構成するには、pg_basebackupからやり直す必要があります。
・アプリケーションの接続先を新プライマリのIPアドレスへ切り替えてください。pgBouncer や HAProxy のような接続プールを使っている場合は、そちらの向き先変更も忘れずに行います。

「FATAL: could not connect to the primary server」が出た時の対処法

スタンバイ起動後に以下のようなエラーがジャーナルログに出る場合、原因は大抵5パターンのどれかです。

# スタンバイ側でエラーを確認する sudo journalctl -u postgresql-16 --no-pager | tail -20 FATAL: could not connect to the primary server: connection to server at "192.168.10.101", port 5432 failed: FATAL: no pg_hba.conf entry for replication connection from host "192.168.10.102", user "replicator", SSL off

原因と対処法:

pg_hba.confの設定漏れ:DATABASEに "replication"、ADDRESSにスタンバイのIPが正しく書かれているか確認してください。変更後は systemctl reload postgresql-16 で反映します。
プライマリが再起動されていない:wal_level の変更はrestartが必要です。reloadでは反映されません。
レプリケーションロールのパスワードが違う:primary_conninfo のpassword パラメータか .pgpass ファイルを確認します。
ファイアウォールでポート5432がブロックされている:プライマリで firewall-cmd --list-all を確認してください。
max_wal_sendersに達している:pg_stat_replication の行数が max_wal_senders と同数の場合、値を増やしてプライマリを再起動してください。

「FATAL: requested WAL segment has already been removed」が出る場合

# スタンバイのログに以下が出る場合はWALセグメントの欠落 FATAL: requested WAL segment 000000010000000000000005 has already been removed

スタンバイが長時間切断されている間にプライマリ側でWALセグメントが削除されたために起きます。wal_keep_size の値を増やすか、pg_basebackupからスタンバイを作り直してください。

本記事のまとめ

PostgreSQLのストリーミングレプリケーション構築で実施した手順を表にまとめます。

フェーズ 実施箇所 内容
プライマリ設定 postgresql.conf wal_level=replica、max_wal_senders=5、wal_keep_size=256
プライマリ設定 pg_hba.conf host replication replicator スタンバイIP/32 scram-sha-256
プライマリ設定 psql CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD '…'
スタンバイ構築 スタンバイ側コマンド pg_basebackup -h プライマリIP -U replicator -D データdir -R -Xs -P
スタンバイ構築 自動生成ファイル確認 standby.signal の存在・postgresql.auto.conf の primary_conninfo を確認
同期確認 プライマリ側psql pg_stat_replication の state が "streaming" になるを確認
同期確認 スタンバイ側psql SELECT pg_is_in_recovery() → t(true)を確認
フェイルオーバー スタンバイ側コマンド pg_ctl promote -D データdir または SELECT pg_promote()
昇格確認 新プライマリ側psql SELECT pg_is_in_recovery() → f(false)を確認
PostgreSQLのストリーミングレプリケーションは、pg_basebackup の -R オプションを使えばstandby.signal と primary_conninfo の手動作業が不要になり、構築の複雑さが大きく下がりました。設定の要所はプライマリ側の「WALレベル・接続許可・レプリケーションロール」の3点セットです。pg_stat_replication で streaming を確認し、pg_is_in_recovery() でスタンバイの状態を確認する、この2つを覚えておけば運用中の状態把握も迷いません。

PostgreSQLレプリケーションが構築できたら、次はLinuxサーバー全体の運用スキルを体系的に固めませんか?

レプリケーション・バックアップ・障害対応を含む現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

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

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

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

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

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

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

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

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

この記事を書いた人

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

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

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