MENU

本番PostgreSQLを論理レプリケーションでゼロ停止移行する|切り替えタイミング設計と整合性確認・切り戻し手順

目次

論理レプリケーションが移行手段の主流になった背景

データベースの移行というと、かつては「深夜メンテナンスウィンドウを設けてダンプ&リストア」が定番でした。しかし、24時間稼働するWebサービスや決済系システムでは、たとえ30分の停止でも許容されないケースが増えています。こうした現場で注目を集めているのが、PostgreSQLの論理レプリケーション(Logical Replication)を使ったゼロ停止移行です。

論理レプリケーションはPostgreSQL 10で正式導入されて以来、バージョンを重ねるごとに機能が充実しています。物理レプリケーションと違い、メジャーバージョン間・OS間・アーキテクチャ間を跨いだデータ転送が可能で、テーブル単位での選択的レプリケーションや、ソース側を書き込み可能なまま運用できる点が実務上の大きな強みです。2026年現在、PostgreSQL 16・17環境では組み込みの論理レプリケーション機能だけでほぼすべての移行シナリオをカバーできるようになっており、pglogical等の外部拡張に依存する必然性は薄れています。

ただし、移行を成功させるには「コマンドを覚える」だけでは不十分です。切り替えタイミングの設計・整合性確認の方法・切り戻しシナリオの整備という3つの柱を事前に設計しておかなければ、本番当日に致命的な判断ミスを招きます。本記事ではこの3点を軸に、実務で通用する手順を解説します。

移行前の前提確認と環境準備

wal_levelとパラメータ設定

論理レプリケーションを使うには、ソース側のPostgreSQLで wal_level = logical が設定されている必要があります。デフォルト値は replica なので、移行作業を始める前に確認・変更が必要です。変更にはデータベースの再起動を伴うため、この作業だけは計画的な短時間停止が必要になります。移行当日ではなく数日前に済ませておくのが現場での定石です。

あわせて max_replication_slotsmax_wal_senders も確認します。移行用のスロットが少なくとも1つ追加で確保できる余裕が必要です。既存のレプリカ(読み取り用スタンバイ等)がある環境では、既存スロット数にαを加えた値を設定してください。pg_hba.confにはターゲットサーバーのIPアドレスからのレプリケーション接続を許可するエントリも忘れずに追加します。

スキーマの事前移行とDDL非レプリケーションの制約

論理レプリケーションはDMLのみを転送します。DDL(テーブル定義の変更)・シーケンス値・ラージオブジェクトはレプリケーションの対象外です。このため、ターゲット側のデータベースにはあらかじめスキーマを適用しておく必要があります。pg_dump --schema-only でスキーマのみを取得してターゲットに適用するのが標準的な手順です。また、テーブルにプライマリキーまたは REPLICA IDENTITY が設定されていない場合、UPDATEとDELETEのレプリケーションが機能しません。移行前に全テーブルを棚卸しして確認することを強くお勧めします。

パブリケーション・サブスクリプションの構築と同期監視

準備が整ったら、ソース側でパブリケーションを作成します。全テーブルを対象にする場合は CREATE PUBLICATION pub_migration FOR ALL TABLES; が最もシンプルです。一部テーブルのみを対象にしたい場合はテーブル名を列挙します。PostgreSQL 16以降ではテーブルごとの行フィルタリングもサポートされており、マルチテナント構成でテナント単位の段階移行なども実現可能です。

ターゲット側では CREATE SUBSCRIPTION sub_migration CONNECTION '接続文字列' PUBLICATION pub_migration; でサブスクリプションを作成します。この時点から初期データコピー(スナップショット取得)が始まり、完了後にストリーミングレプリケーションへ移行します。初期コピーの完了状況は pg_stat_subscription ビューの relidreceived_lsn で確認できます。

同期の進捗とレプリケーションラグはソース側の pg_stat_replication ビューをクエリして把握します。write_lagflush_lagreplay_lag の3カラムが主要な監視指標です。本番切り替えの判断材料としては、この3つがいずれもゼロに近づき、かつ安定して推移していることを少なくとも10〜15分は観測して確認することが推奨されます。

切り替えタイミング設計――ラグ収束の見極め方

LSNを使ったラグの定量化

切り替えのタイミングを感覚で判断するのは危険です。定量的な指標として、ソース側の現在のLSN(Log Sequence Number)とターゲット側の受信済みLSNの差分をバイト数で表示するクエリを事前に用意しておきます。pg_current_wal_lsn() から pg_replication_slots ビューの confirmed_flush_lsn を引いた値がゼロに近づき、かつ書き込みの少ない時間帯(夜間バッチ処理後等)に切り替えを実施することで、切り替え後のデータ損失リスクを最小化できます。

高トラフィック環境では「ラグが完全にゼロになる瞬間」を待つのは現実的ではありません。多くの現場では「ラグが1MB以下かつ安定している」状態を切り替えの目安にしています。切り替え直前にアプリケーション側を一時的に読み取り専用モードにするか、接続をドレインしてラグを完全消化してから接続先を切り替える「短時間グレースフル切り替え」のアプローチが現実的です。

アプリケーション側の接続切り替え戦略

接続先の切り替え方法は環境によって異なります。pgBouncer等のコネクションプーラーを中間に挟んでいる環境では、接続先変更+reloadで完結する場合があります。アプリケーションが直接接続している場合は、DNS切り替え(低TTLを事前設定)か、接続文字列を環境変数化して再起動なしで反映できる構造にしておくことが望ましいです。いずれの方法でも、切り替え後の最初のトランザクションが新DBに到達したことを確認するモニタリングフローを事前に用意しておきます。

整合性確認――切り替え直後に実施すべき検証

切り替え後の整合性確認は、できる限り自動化されたスクリプトで実施します。手動での目視確認だけでは、件数ズレやシーケンス値のズレを見逃すリスクがあります。

まず実施すべきは主要テーブルの行数確認です。ソース側とターゲット側で同一のSQLを実行して件数を比較します。論理レプリケーション中に発生した差異(切り替え直後の未コミットトランザクションによるわずかなズレ)がある場合は、トランザクションの完了を待って再確認します。次にシーケンス値の確認と修正が必要です。前述のとおりシーケンスはレプリケーションされないため、SELECT last_value FROM sequence_name; でソース側の最終値を取得し、ターゲット側で SELECT setval('sequence_name', N); で揃えます。この作業を漏らすと、切り替え後の新規INSERTで一意制約違反が発生します。

さらに、アプリケーションの動作観点での確認として、ログイン・決済・検索など主要なビジネストランザクションを実際に実行して正常完了することを確認します。監視ツールのエラーレートとレスポンスタイムをリアルタイムで追い、切り替え前後で異常な変化がないことを少なくとも15分は観測します。

切り戻し手順と本番での注意点

論理レプリケーションを使った移行の大きな利点の一つは、切り戻し経路を設計しやすい点です。切り替え後も旧ソースサーバーを即座にシャットダウンせず、一定期間(最低でも1〜2時間、可能なら24時間)稼働させておきます。

切り戻しが必要になった場合の手順には、大きく2つのパターンがあります。第1のパターンは、切り替え直後で新DB側への書き込みが少量の段階での切り戻しです。この場合は、新DBへの書き込みを停止してから旧DBへの接続を再開し、新DBに書き込まれた差分を手動で旧DBに適用します。このシナリオを想定して、切り替え後に新DBで実行されたトランザクションのログを記録する仕組みを設けておくと切り戻しコストが下がります。

第2のパターンは、逆方向のレプリケーションを事前に設定しておく方法です。切り替え前に新DBをソースとして旧DBへの論理レプリケーションも設定しておけば、切り替え後の差分が旧DBにも反映されるため、切り戻し時の整合性問題を大幅に軽減できます。ただし、双方向の書き込みによる競合が発生しうるため、切り替え前の旧DBは default_transaction_read_only = on で読み取り専用に設定しておくことが前提です。

運用上の注意点として、切り替え後に旧DB側のレプリケーションスロットを削除しないまま放置すると、WALが蓄積してソースのディスクを圧迫します。切り戻し期間が終了したら速やかに SELECT pg_drop_replication_slot('スロット名'); を実行してスロットを解放することを作業手順書に明記しておいてください。

2026年現行環境での差分と最新機能の活用

2026年現在、主要なLinuxディストリビューションでの標準PostgreSQLバージョンはPostgreSQL 16(Ubuntu 24.04 LTS)またはPostgreSQL 17(Fedora 40以降)です。これらのバージョンでは、従来の論理レプリケーションに比べていくつかの重要な改善が加わっています。

PostgreSQL 16では、論理レプリケーション中の2フェーズコミット(prepare/commit)のサポートが安定し、大規模トランザクションのレプリケーション信頼性が向上しました。また、パブリケーションにWHERE句による行フィルタリングと列リストによる列フィルタリングが追加され、移行対象の精細なコントロールが可能になっています。これにより、特定のカラムを移行対象から除外したい場合(PII保護の観点等)でも、アプリケーション側の改修なしに対応できます。

PostgreSQL 17では、サブスクリプション側でのフェイルオーバー対応(failoverパラメータ)が追加され、HA構成(PatroniやRepmgr等)との組み合わせでの移行シナリオが整理されました。論理レプリケーションスロットのスタンバイへの同期もサポートされたため、プライマリ障害時にサブスクリプションが中断するリスクが低減しています。

systemd環境での運用では、postgresql@16-main.service のような名前付きサービスユニットを意識した設定管理が求められます。移行作業時には必ずsystemdのサービス定義も確認し、新環境での自動起動・ログ出力先・起動タイムアウト設定を旧環境と整合させておくことが重要です。とくに移行先がコンテナ環境やクラウドマネージドPostgreSQLの場合は、論理レプリケーションの対応可否やパラメータ変更の制約をサービス仕様で先に確認しておく必要があります。

外部拡張のpglogicalは長らく論理レプリケーションの実質標準でしたが、PostgreSQL 16以降の組み込み機能が大半の要件を満たすようになったため、新規の移行プロジェクトでは組み込み機能のみで設計することが推奨されています。pglogicalは一部のマルチマスター構成や特殊なルーティング要件では依然として有効ですが、単純な移行シナリオでは追加の依存関係を避けることでトラブルシューティングの複雑さを抑えられます。論理レプリケーションを軸としたゼロ停止移行は、適切な事前設計と検証フローさえ整えれば、今日の標準的なLinux・PostgreSQL環境で十分に実現可能な選択肢です。

「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。

ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。

>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)

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

PR・広告

新しいLinuxの教科書 第2版(Amazon)

コマンド操作から基本運用までを手を動かして学べる定番書。記事で触れた技術の土台固めに。

Amazonで見る

※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次