PostgreSQL 10以降に正式実装された論理レプリケーションは、PUBLICATION(送信側)とSUBSCRIPTION(受信側)を使ってテーブル単位で非同期複製を行います。ストリーミングレプリケーション(物理)と異なり、バージョン差のある環境間でも動作するため、メジャーバージョンアップ時のダウンタイム最小化にも応用できます。
この記事では、RHEL 9系~Rocky Linux 9を想定環境として、PostgreSQL 16を使った論理レプリケーションの構築手順を解説します。wal_levelの設定変更からPUBLICATION・SUBSCRIPTIONの作成、動作確認、テーブル追加・削除時の対応、トラブルシュートまでを1本でまとめています。
この記事のポイント
・PUBLICATION(送信側)とSUBSCRIPTION(受信側)でテーブル単位に複製を制御できる
・postgresql.confのwal_levelを「logical」に変更しないとPUBLICATIONが作成できない
・pg_stat_replication / pg_stat_subscriptionで同期状態をリアルタイムに確認できる
・バージョン差のある2台でも動作するためメジャーバージョンアップのダウンタイム短縮にも活用できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
論理レプリケーションとストリーミングレプリケーション(物理)の違い
PostgreSQLのレプリケーションには「ストリーミングレプリケーション(物理)」と「論理レプリケーション」の2種類があります。どちらを選ぶかは用途によって異なります。| 項目 | ストリーミングレプリケーション(物理) | 論理レプリケーション |
|---|---|---|
| 複製単位 | クラスター全体(全データベース・全テーブル) | テーブル単位(指定したテーブルのみ) |
| バージョン差 | 不可(同一メジャーバージョンのみ) | 可(受信側が送信側と同じかそれ以上のバージョン) |
| DDL(CREATE TABLE等) | 自動複製される | 自動複製されない(手動でスキーマを合わせる) |
| 受信側への書き込み | 不可(読み取り専用スタンバイ) | 可(通常のテーブルとして書き込みもできる) |
| 主な用途 | HAフェイルオーバー、読み取りスケールアウト | テーブル選択複製、バージョンアップ移行、データ集約 |
構築前の確認とwal_levelの設定
論理レプリケーションを有効にするには、パブリッシャー(送信側)のpostgresql.confでwal_level = logicalを設定する必要があります。デフォルト値はreplicaで、このままではPUBLICATIONを作成できません。今回の構成は以下の通りです。
| 役割 | IPアドレス(例) | 説明 |
|---|---|---|
| パブリッシャー(Publisher) | 192.168.1.10 | データの送信側。PUBLICATIONを作成するサーバー |
| サブスクライバー(Subscriber) | 192.168.1.20 | データの受信側。SUBSCRIPTIONを作成するサーバー |
1. 現在のwal_levelを確認する
パブリッシャーでpsqlを起動し、現在の設定を確認します。# パブリッシャーサーバーで実行 sudo -u postgres psql -c "SHOW wal_level;"
wal_level ----------- replica (1 row)
replicaと表示された場合は変更が必要です。すでにlogicalであれば「2. PUBLICATIONの作成」まで読み飛ばしてください。
2. postgresql.confでwal_levelをlogicalに変更する
postgresql.confを編集します。RHEL系では/var/lib/pgsql/16/data/postgresql.conf、Debian/Ubuntu系では/etc/postgresql/16/main/postgresql.confが標準のパスです。
# RHEL 9系・Rocky Linux 9の例 sudo vi /var/lib/pgsql/16/data/postgresql.conf
# 変更前(コメントアウトされていることが多い) #wal_level = replica # 変更後 wal_level = logical
3. max_wal_sendersとmax_replication_slotsを確認する
論理レプリケーションはレプリケーションスロットを使うため、max_wal_sendersとmax_replication_slotsにも余裕が必要です。PostgreSQL 16のデフォルトは10で、通常はそのままで問題ありません。
sudo -u postgres psql -c "SHOW max_wal_senders; SHOW max_replication_slots;"
0になっている場合は最低でも10に増やしてください。変更後はPostgreSQLを再起動します。
# RHEL 9系・Rocky Linux 9 sudo systemctl restart postgresql-16 # Ubuntu 24.04の場合 sudo systemctl restart postgresql
logicalになっていることを確認します。
sudo -u postgres psql -c "SHOW wal_level;"
wal_level ----------- logical (1 row)
パブリッシャー側の設定
wal_levelの変更が完了したら、送信側(パブリッシャー)の設定を行います。1. レプリケーション用ロールを作成する
PUBLICATIONを利用するには、サブスクライバーがパブリッシャーへ接続するためのロール(ユーザー)が必要です。このロールにはREPLICATION属性とテーブルへのSELECT権限が必要です。sudo -u postgres psql
-- レプリケーション用ロールの作成 CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'パスワード'; -- 対象データベースへのCONNECT権限を付与 GRANT CONNECT ON DATABASE mydb TO replicator; -- 対象スキーマ内の全テーブルへSELECT権限を付与 \c mydb GRANT SELECT ON ALL TABLES IN SCHEMA public TO replicator;
2. pg_hba.confで接続を許可する
サブスクライバーのIPアドレスからの接続を許可します。pg_hba.confに以下の2行を追加します。sudo vi /var/lib/pgsql/16/data/pg_hba.conf
# レプリケーション接続(WAL送信用) host replication replicator 192.168.1.20/32 scram-sha-256 # 通常DB接続(SUBSCRIPTION作成時のメタデータ取得用) host mydb replicator 192.168.1.20/32 scram-sha-256
sudo -u postgres psql -c "SELECT pg_reload_conf();"
3. PUBLICATIONを作成する
パブリッシャーの対象データベース(mydb)に接続し、PUBLICATIONを作成します。sudo -u postgres psql -d mydb
-- 特定テーブルのみPUBLICATIONに含める場合 CREATE PUBLICATION mypub FOR TABLE orders, products; -- データベース内の全テーブルを含める場合 -- CREATE PUBLICATION mypub FOR ALL TABLES;
SELECT * FROM pg_publication;
pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate -----------+----------+--------------+-----------+-----------+-----------+------------- mypub | 10 | f | t | t | t | t (1 row)
pubinsert / pubupdate / pubdeleteがすべてtになっていれば、INSERT・UPDATE・DELETEが複製対象として有効です。
サブスクライバー側の設定
1. テーブルスキーマをあらかじめ作成する
論理レプリケーションはDDL(テーブル定義)を自動複製しません。サブスクライバー側にあらかじめ同じ構造のテーブルを作成しておく必要があります。パブリッシャーからスキーマのみをエクスポートする方法が確実です。# パブリッシャーサーバーで実行 — スキーマのみエクスポート(データは除外) pg_dump -U postgres -d mydb --schema-only -t orders -t products > mydb_schema.sql
# サブスクライバーサーバーで実行 scp user@192.168.1.10:/path/to/mydb_schema.sql ./ # データベースの作成(存在しない場合) sudo -u postgres createdb mydb # スキーマのインポート sudo -u postgres psql -d mydb < mydb_schema.sql
2. SUBSCRIPTIONを作成する
サブスクライバーのデータベースに接続し、SUBSCRIPTIONを作成します。sudo -u postgres psql -d mydb
CREATE SUBSCRIPTION mysub CONNECTION 'host=192.168.1.10 port=5432 dbname=mydb user=replicator password=パスワード' PUBLICATION mypub;
レプリケーションの動作確認
1. パブリッシャー側でpg_stat_replicationを確認する
sudo -u postgres psql -d mydb -c "SELECT pid, usename, application_name, client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, sync_state FROM pg_stat_replication;"
pid | usename | application_name | client_addr | state | sent_lsn | replay_lsn | sync_state -------+-----------+------------------+--------------+-----------+-----------+------------+----------- 3421 | replicator| mysub | 192.168.1.20 | streaming | 0/1A00028 | 0/1A00028 | async (1 row)
state = streamingになっていれば正常に同期中です。sent_lsnとreplay_lsnが一致していれば遅延がないことを示します。
2. サブスクライバー側でpg_stat_subscriptionを確認する
sudo -u postgres psql -d mydb -c "SELECT subid, subname, pid, received_lsn, last_msg_receipt_time, latest_end_lsn FROM pg_stat_subscription;"
subid | subname | pid | received_lsn | last_msg_receipt_time | latest_end_lsn -------+---------+------+--------------+-------------------------------+--------------- 16390 | mysub | 5234 | 0/1A00028 | 2026-10-21 14:00:00.123456+09 | 0/1A00028 (1 row)
3. テストデータで動作を確かめる
パブリッシャーでINSERTを実行し、サブスクライバーにデータが届くか確認します。# パブリッシャーサーバーで実行 sudo -u postgres psql -d mydb -c "INSERT INTO orders (id, item, qty) VALUES (1, 'widget', 10);"
# サブスクライバーサーバーで確認 sudo -u postgres psql -d mydb -c "SELECT * FROM orders;"
id | item | qty ----+--------+----- 1 | widget | 10 (1 row)
テーブルの追加・削除とSUBSCRIPTIONの更新
運用中に複製対象のテーブルを変更したい場合は、PUBLICATIONとSUBSCRIPTIONの両方を更新する必要があります。PUBLICATIONにテーブルを追加する
# パブリッシャーでPUBLICATIONにテーブルを追加 sudo -u postgres psql -d mydb -c "ALTER PUBLICATION mypub ADD TABLE customers;"
# サブスクライバーでSUBSCRIPTIONを更新 sudo -u postgres psql -d mydb -c "ALTER SUBSCRIPTION mysub REFRESH PUBLICATION;"
PUBLICATIONからテーブルを削除する
# パブリッシャーでPUBLICATIONからテーブルを削除 sudo -u postgres psql -d mydb -c "ALTER PUBLICATION mypub DROP TABLE products;"
SUBSCRIPTION・PUBLICATIONを削除する
# SUBSCRIPTIONを一時停止 sudo -u postgres psql -d mydb -c "ALTER SUBSCRIPTION mysub DISABLE;" # SUBSCRIPTIONを削除(レプリケーションスロットも自動解放される) sudo -u postgres psql -d mydb -c "DROP SUBSCRIPTION mysub;" # PUBLICATIONを削除(パブリッシャー側) sudo -u postgres psql -d mydb -c "DROP PUBLICATION mypub;"
トラブルシュートとよくあるエラー
「ERROR: publication "mypub" does not exist」
PUBLICATIONが存在しないままCREATE SUBSCRIPTIONを実行した時に発生します。パブリッシャー側でSELECT * FROM pg_publication;を実行してPUBLICATIONの存在を確認してください。
「FATAL: no pg_hba.conf entry for replication connection」
pg_hba.confのreplicationコンテキスト行が不足しているか、サブスクライバーのIPアドレスが一致していません。追加後にSELECT pg_reload_conf();で設定を再読み込みしてください。
「ERROR: logical replication slot "mysub" already exists」
過去に削除したSUBSCRIPTIONのレプリケーションスロットが残った状態で、同名のSUBSCRIPTIONを再作成しようとした時に発生します。パブリッシャー側で古いスロットを削除します。# パブリッシャーで実行 — スロット名はサブスクリプション名と同一 sudo -u postgres psql -c "SELECT pg_drop_replication_slot('mysub');"
レプリケーション遅延(lag)が大きい
パブリッシャーへの書き込み量が多い場合やネットワーク帯域が不足している場合に遅延が発生します。パブリッシャー側で遅延バイト数を確認します。sudo -u postgres psql -c " SELECT application_name, (sent_lsn - replay_lsn) AS lag_bytes, now() - pg_last_xact_replay_timestamp() AS lag_time FROM pg_stat_replication; "
lag_bytesが継続して増加している場合は、サブスクライバーのI/O性能やCPUリソースを確認してください。
「could not connect to the publisher」
接続文字列のhost・port・dbname・user・passwordの誤りのほか、サブスクライバーからパブリッシャーへのファイアウォール設定(5432/tcpポート)が原因になることが多いです。まず接続文字列を確認し、次にネットワーク経路を確認してください。本記事のまとめ
PostgreSQLの論理レプリケーション(PUBLICATION・SUBSCRIPTION)の設定手順をまとめます。| 手順 | 対象 | 設定内容 |
|---|---|---|
| wal_levelをlogicalに変更 | パブリッシャー | wal_level = logical(postgresql.conf) |
| レプリケーション用ロール作成 | パブリッシャー | CREATE ROLE replicator WITH REPLICATION LOGIN ... |
| pg_hba.confへの接続許可追加 | パブリッシャー | host replication replicator <IP> scram-sha-256 |
| PUBLICATIONの作成 | パブリッシャー | CREATE PUBLICATION mypub FOR TABLE ... |
| テーブルスキーマの作成 | サブスクライバー | pg_dump --schema-onlyでエクスポート後インポート |
| SUBSCRIPTIONの作成 | サブスクライバー | CREATE SUBSCRIPTION mysub CONNECTION '...' PUBLICATION mypub |
| 動作確認 | 両サーバー | pg_stat_replication / pg_stat_subscription |
Linuxサーバー上でのPostgreSQL運用をさらに深めたい方は、Linuxサーバー構築・運用の実践セミナーも参考にしてみてください。
>> Linux Master Pro Seminarの詳細を見る
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:LinuxサーバーのMariaDB user一覧を確認する方法|SELECT・SHOW USERSコマンド活用
- この記事の属するカテゴリ:データーベース管理へ戻る

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