メインコンテンツへスキップ
友田 陽大
PostgreSQL 運用・信頼性
PostgreSQL
アーキテクチャ設計

PostgreSQL 論理レプリケーション実践(publish/subscribe・CDC・版跨ぎのゼロダウンタイム・メジャーアップグレード・v18対応)

PostgreSQL の論理レプリケーションを本番で使う実践ガイド。物理レプリケーションとの違い、publish/subscribeの構築、CDC(変更データキャプチャ)、そして版跨ぎのゼロダウンタイム・メジャーアップグレード(数秒の停止で18へ)までを解説。DDL・シーケンスが複製されないという最重要の制約と切替時の落とし穴、pg_upgradeの--swap、PostgreSQL 18の改善も公式ドキュメントに忠実に。

公開日
読了時間
10分
著者
友田 陽大
シェア

物理レプリケーション(前の記事)は「クラスタ丸ごと・同一バージョン」のHAでした。しかし現場には、別の要求があります——「このテーブルだけ別システムへ流したい」「メジャーアップグレードを無停止でやりたい」「変更をイベントとして下流に配りたい(CDC)」。

これらに応えるのが論理レプリケーションです。この記事は、その仕組みと構築、そして最大の応用である版跨ぎのゼロダウンタイム・メジャーアップグレードを、公式ドキュメントに忠実に解説します。あわせて「何が複製されないか」という、事故に直結する制約を徹底的に潰します。本番運用ガイド §7の深掘りです。

この記事のルール:仕様・制約・アップグレード手順・PostgreSQL 18 の変更点は PostgreSQL 18 公式ドキュメント(2026年6月時点) に基づきます。論理レプリケーションは制約が多く事故りやすいため、複製されないものを特に正確に扱います。


1. 論理 vs 物理:何が違うのか

公式の定義:

論理レプリケーションは、レプリケーション識別子(通常は主キー)に基づいてデータオブジェクトとその変更を複製する手法である。これを論理的と呼ぶのは、正確なブロックアドレスとバイト単位で複製する物理レプリケーションとの対比による。

違いを表に。

物理レプリケーション論理レプリケーション
単位クラスタ全体(バイト単位)テーブル単位(行の変更)
バージョン同一メジャー版が必須版跨ぎ可(→アップグレードに使える)
プラットフォーム同一跨ぎ可(Linux→Windows等)
方向一方向双方向・カスケード可
用途HA/DR、リードレプリカ選択的複製、CDC、版跨ぎ移行、DB統合

公式が挙げる用途には、「個々の変更が到着するたびにサブスクライバでトリガを発火する」(=CDC/イベント駆動)、「複数DBを1つに統合(分析用途等)」「異なるメジャーバージョン間の複製」(=アップグレード)が含まれます。


2. publish / subscribe で構築する

論理レプリケーションは**パブリッシャ(publish)とサブスクライバ(subscribe)**のモデルです。最小構成:

パブリッシャ側

# postgresql.conf:論理デコードに必要
wal_level = logical
-- 複製したいテーブルの集合を「パブリケーション」として定義
CREATE PUBLICATION app_pub FOR TABLE users, orders;
-- スキーマ単位・全テーブルも可
-- CREATE PUBLICATION all_pub FOR ALL TABLES;
-- CREATE PUBLICATION prod_pub FOR TABLES IN SCHEMA production;

publish パラメータの既定は 'insert, update, delete, truncate'(全操作)。WITH (publish = 'insert') で挿入だけ流すこともできます。

サブスクライバ側

-- スキーマは事前に用意しておく(DDLは複製されない。§3)
-- CREATE TABLE users (...); CREATE TABLE orders (...);

CREATE SUBSCRIPTION app_sub
  CONNECTION 'host=publisher dbname=appdb user=replicator sslmode=verify-full'
  PUBLICATION app_pub;
-- 既定で初期データがコピーされ、その後ストリーミングが始まる

公式:サブスクリプションは既定で初期データをコピーし(copy_data)、その後の変更をストリーミングします。PostgreSQL 18 では CREATE SUBSCRIPTIONstreaming 既定が off から parallel に変わりました。


3. 最重要:何が複製されないか

論理レプリケーションの事故は、ほぼ全て**「複製されないもの」を知らない**ことから起きます。公式の制約を正確に押さえます。

⚠ DDL(スキーマ変更)は複製されない

データベーススキーマと DDL コマンドは複製されない。初期スキーマは pg_dump --schema-only で手動コピーできる。後続のスキーマ変更は手動で同期し続ける必要がある

つまりパブリッシャで ALTER TABLE しても、サブスクライバには反映されません。しかも公式は重要な順序を示します:

パブリッシャでスキーマが変わり、サブスクライバのテーブル定義に合わないデータが届くと、スキーマを更新するまで複製はエラーで止まる。多くの場合、サブスクライバに先に追加的なスキーマ変更を適用することで、断続的エラーを避けられる。

→ **列追加は「サブスクライバ先 → パブリッシャ後」**の順で。

⚠ シーケンスは複製されない(切替時の地雷)

シーケンスデータは複製されない。serial / identity 列の値はテーブルの一部として複製されるが、シーケンス自体はサブスクライバで開始値のままである。…切替やフェイルオーバーを意図する場合、シーケンスを最新値に更新する必要がある

これはアップグレードの切替時に最も人を刺す落とし穴です(§4 で対処)。

⚠ UPDATE/DELETE には主キー(レプリカ識別子)が必要

論理レプリケーションは「レプリケーション識別子(通常は主キー)」に基づきます。主キーや明示的な REPLICA IDENTITY を持たないテーブルは、UPDATE/DELETE を複製できません(INSERT は可)。全テーブルに適切な主キーを——これは設計の前提になります。

その他の制約

  • ラージオブジェクトは複製されない(回避策なし。通常テーブルに格納すること)。
  • テーブルのみが対象(ビュー・マテビュー・外部テーブルはエラー)。
  • パーティションテーブルは既定でリーフパーティションから複製される(publish_via_partition_root で変更可)。

4. 版跨ぎのゼロダウンタイム・メジャーアップグレード

論理レプリケーションの最大の実用価値が、メジャーアップグレードの無停止化です。メジャーアップグレードには2つの道があります(公式 §18.6)。

道A:pg_upgrade(インプレース・短時間停止)

# 旧クラスタを停止し、新バージョンへインプレース変換
pg_upgrade \
  --old-datadir=/var/lib/postgresql/17/main \
  --new-datadir=/var/lib/postgresql/18/main \
  --old-bindir=/usr/lib/postgresql/17/bin \
  --new-bindir=/usr/lib/postgresql/18/bin \
  --jobs=4 \        # PG18:チェックを並列化
  --swap            # PG18:ディレクトリ入替で最速(コピー/リンクより速い)

公式:「pg_upgrade はインストールをインプレースであるメジャー版から別の版へ移行できる。特に --link モードなら数分で完了する」。PostgreSQL 18 の改善:

  • 統計の引き継ぎ--no-statistics で無効化可)——アップグレード後の「統計が空でプランナーが誤動作」を防ぐ。
  • --jobs による並列チェック——オブジェクトが多いDBで高速。
  • --swap——ディレクトリを入れ替える最速モード(ただし旧クラスタは破壊的に変更され、以後起動不可)。

--swap の注意(公式):「ファイル転送が始まると旧クラスタは破壊的に変更され、もはや安全に起動できない」。事前のバックアップ必須です。

道B:論理レプリケーションで切替(数秒の停止)

「ほぼ無停止」を極めるなら、新バージョンのインスタンスへ論理複製し、追いついたら切り替える。公式:

論理レプリケーションは異なるメジャー版間の複製をサポートするため、更新済みバージョンのスタンバイを作れる。…プライマリ(旧版)に追いついたら、プライマリを切り替えてスタンバイを新プライマリにし、旧インスタンスを停止する。この切替は数秒のダウンタイムで済む

手順の骨子(公式 §29.13 を実務向けに):

1. 新バージョン(18)で空のインスタンスを構築(wal_level=logical)
2. パブリッシャ(旧17)の現スキーマを pg_dump --schema-only で新18へ適用(DDLは複製されないため)
3. 旧17に CREATE PUBLICATION、新18に CREATE SUBSCRIPTION → 初期コピー+ストリーミング開始
4. レプリケーション遅延が0に追いつくのを待つ(pg_stat_subscription / lag を監視)
5. 【切替】アプリを一時停止 → 残りの変更が新18へ届くのを確認
6. 【最重要】シーケンスを手で進める(複製されないため)
7. アプリの接続先を新18へ向けて再開 → 旧17を停止

ステップ6のシーケンス更新を忘れると、切替直後に主キー衝突(重複ID)で本番が壊れます。公式の指示どおり、pg_dump でシーケンス現在値を写すか、テーブルの最大値から十分大きい値を setval で設定します。

-- 切替時:各シーケンスをテーブルの最大値より先へ進める(ID衝突を防ぐ)
SELECT setval('users_id_seq', (SELECT max(id) FROM users));
SELECT setval('orders_id_seq', (SELECT max(id) FROM orders));
-- 多数あるなら information_schema から生成して一括実行する

どちらを選ぶか:停止許容が「分」なら pg_upgrade(シンプル)。停止許容が「数秒」、かつダウンタイムが事業に直結するなら論理レプリケーション(手間は増えるが無停止に近い)。まず pg_upgrade を検討し、それでは停止時間が長すぎる場合に論理レプリケーションへ——これが現実的な判断順です。


5. CDC:変更をイベントとして配る

論理レプリケーションの基盤(論理デコード)は、変更データキャプチャ(CDC)にも使えます。公式が用途に挙げる「個々の変更が届くたびにサブスクライバでトリガを発火」がそれ。さらに Debezium などは論理デコードのスロットを購読し、行変更を Kafka 等へイベントとして流します。

これにより、「DBの変更 → 検索インデックス更新/キャッシュ無効化/監査ログ/マイクロサービス連携」を、アプリのコードに二重書き込みを仕込まずに実現できます。アプリは DB に書くだけ。下流はWALから変更を受け取る——Transactional Outbox の代替にもなる強力なパターンです(信頼性設計はトランザクショナル・アウトボックスの記事も参照)。


6. 監視

-- サブスクライバ側:適用の遅延と状態
SELECT subname, received_lsn, latest_end_lsn,
       last_msg_receipt_time, latest_end_time
FROM pg_stat_subscription;

-- PG18:競合がログと統計に記録される
SELECT * FROM pg_stat_subscription_stats;   -- 競合カウント(apply_error_count 等)

PostgreSQL 18 は論理複製の競合をログに記録し、pg_stat_subscription_stats の新カラムで可視化します。生成列の論理複製publish_generated_columns)、ALTER SUBSCRIPTION での二相コミット切替も追加されました。


7. まとめ

  • 論理レプリケーション=行単位・テーブル単位・版跨ぎ・双方向。物理(クラスタ全体・同一版)とは別物。
  • publish/subscribe で構築(wal_level=logical)。初期コピー後にストリーミング。
  • 複製されないものを必ず把握:DDL・シーケンス・ラージオブジェクト・ビュー。UPDATE/DELETE には主キーが要る。
  • 版跨ぎの無停止アップグレードpg_upgrade(分単位・PG18の--swapで最速)か、論理複製+切替(数秒)。切替時のシーケンス更新を絶対に忘れない。
  • CDC にも使える(Debezium 等)。アプリの二重書き込みなしに変更をイベント配信。

「進化させる」が固まったら、日々のスキーマ変更を止めずに行う技術——ゼロダウンタイムのスキーマ変更(ロックセーフDDL) へ。


参考(PostgreSQL 18 公式ドキュメント)

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事で解説した技術の適用事例

木材流通DXのB2B SaaS — PostgreSQL を中核にマルチテナント・多段商流を支えたデータ基盤

ケーススタディを見る