変更要約: 初版(主題G4・G4.1〜G4.3)
4.3レプリケーションの障害と復旧
レプリケーション運用中の障害対応を学びます。スタンバイをマスタへ昇格させるpg_ctl promote、旧マスタを新マスタの子として再構成するpg_rewind、WALを直接受信し続けるpg_receivewal、ロジカルレプリケーション特有の競合(conflict)、そしてストリーミングレプリケーションのエラーハンドリングを押さえます。
レプリケーション構成の障害対応は、単体サーバの障害対応と異なり、「マスタとスタンバイの関係をどう組み替えるか」という視点が加わります。マスタが完全に失われた場合の昇格(フェイルオーバー)、旧マスタを新体制に組み込み直す再同期、WAL供給の途絶への備え、そしてロジカルレプリケーション特有の適用時競合——これらはGoldの障害対応領域の中でも実運用の勘所が凝縮された部分です。
4.3.1昇格と再同期:pg_ctl promote・pg_rewind
- pg_ctl promote=ストリーミングレプリケーションのスタンバイを新しいマスタへ昇格させるコマンド。マスタ障害時のフェイルオーバーの中核操作で、実行後スタンバイは読み取り専用状態を抜け、通常の読み書き可能なマスタとして稼働を始める。
- pg_rewind=旧マスタ(障害から復旧した元マスタ)を、新マスタのタイムラインに追従するスタンバイとして再構成するツール。旧マスタと新マスタで分岐したWAL履歴の差分だけを巻き戻して同期し直すため、旧マスタ全体をベースバックアップから作り直すより高速に復帰させられるのが利点。ただし旧マスタ側のWALが必要なため分岐後すぐに使う必要がある。
- pg_receivewal=マスタからWALストリームを継続的に受信してファイルとして保存し続けるスタンドアロンのクライアントツール(旧称pg_receivexlog)。専用のWALアーカイブ先として使うほか、通常のアーカイブ(archive_command)が何らかの理由で機能していない間の補完的なWAL保全としても使われる。
4.3.2ロジカルレプリケーションの競合とエラーハンドリング
- ロジカルレプリケーションの競合(conflict)=サブスクライバ側で変更の適用に失敗する状態。例えば、サブスクライバ側テーブルにパブリッシャ側には無いUNIQUE制約があり、レプリケートされたINSERTがその制約に違反する場合などに発生。競合が起きるとその時点で適用ワーカーが停止し、後続の変更も止まるため、放置するとレプリケーションが完全に滞留する。
- 競合の解決=サブスクライバ側で手動介入(矛盾するデータを削除・修正する、あるいは該当トランザクションをスキップする)した後、レプリケーションの再開を促す。ストリーミングレプリケーションのような物理コピーには存在しない、ロジカルレプリケーション特有の障害モードである点が重要。
- ストリーミングレプリケーションのエラーハンドリング=スタンバイ側のwalreceiverとマスタ側のwalsenderの接続が切れた場合、設定次第で自動的に再接続を試みるのが基本挙動。ネットワーク断や一時的なマスタの高負荷など一過性の要因であれば再接続で復旧するが、WALが必要な範囲を超えて欠落している(スタンバイの遅延が
wal_keep_size等の保持範囲を超えた)場合は再接続だけでは復旧できず、ベースバックアップの取り直しが必要になる。
「pg_ctl promote=スタンバイをマスタへ昇格」「pg_rewind=旧マスタを新マスタのスタンバイとして高速再同期(ベースバックアップ再取得より速い)」「pg_receivewal=WALの継続受信・アーカイブ補完」「ロジカルレプリケーションの競合は適用ワーカー停止→手動介入が必要」「ストリーミングレプリケーションは自動再接続が基本だが、WAL欠落時はベースバックアップ再取得が必要」が最頻出です。pg_rewindとPITR/ベースバックアップ再取得の使い分け(差分同期か全体再構築か)が定番の比較ポイントです。
マスタ障害時のフェイルオーバー対応を一連の流れで追ってみましょう。マスタサーバがハードウェア障害で応答不能になったとします。まず監視から異常を検知し、最新のWALを最も多く受信しているスタンバイを昇格対象として選定します(複数スタンバイがある場合、pg_stat_replicationで確認していたレプリケーション遅延の少なさが判断材料)。選定したスタンバイでpg_ctl promoteを実行すると、そのスタンバイは新マスタとして書き込みを受け付け始めます。ここで問題になるのが、元のマスタが実は完全に壊れておらず、後で復旧できる場合です。単純に元マスタを再起動して新マスタと同時に稼働させると、両方が書き込みを受け付けるスプリットブレインとなり整合性が崩壊するため絶対に避けなければなりません。正しい手順は、元マスタを新マスタに従属するスタンバイとして組み込み直すことです。ここでpg_rewindの出番です。元マスタと新マスタは昇格の瞬間から別々のタイムラインに分岐していますが、pg_rewindは分岐後に異なった部分のデータブロックだけを新マスタから取得して上書きすることで、元マスタ全体をベースバックアップから再構築するよりも短時間で「新マスタに追従する健全なスタンバイ」に仕立て直せます。ただし分岐後のWALが元マスタ側に残っていることが前提のため、障害検知からあまり時間を置かず対応する必要があります。分岐後のWALが既に失われている、あるいはpg_rewindでは対応できないほど乖離が大きい場合は、素直にpg_basebackupでベースバックアップを取り直すほうが確実です。もう一つ、レプリケーション運用で見落とされがちなのがpg_receivewalの位置づけです。通常のarchive_commandによるWALアーカイブが何らかの設定ミスで機能していない期間があっても、pg_receivewalを並行して稼働させていればその間のWALをファイルとして保全でき、後からPITRが必要になった際の欠落を防げます。
| 手段 | 用途 | 性質 |
|---|---|---|
| pg_ctl promote | スタンバイをマスタへ昇格 | フェイルオーバーの中核操作 |
| pg_rewind | 旧マスタを新マスタのスタンバイへ再構成 | 差分同期・ベースバックアップ再取得より高速だが旧マスタのWALが必要 |
| pg_receivewal | WALの継続受信・保存 | archive_command不調時の補完手段にもなる |
ひっかけ: 「元マスタが復旧したら、そのまま起動してマスタとして稼働を続けさせればよい」は誤りです。昇格済みの新マスタと同時に旧マスタが書き込みを受け付けるとスプリットブレインとなり整合性が崩壊するため、旧マスタはpg_rewind等で新マスタのスタンバイへ再構成しなければなりません。また「ロジカルレプリケーションの競合は自動的に解決されて処理が続行する」も誤り=競合は適用ワーカーを停止させ、手動介入なしには解消しません。「pg_receivewalはストリーミングレプリケーション専用で、アーカイブの代替にはならない」も誤り=archive_commandが機能していない期間の補完的なWAL保全として実務で使われます。
4.3.3この節のまとめ
- pg_ctl promote=スタンバイをマスタへ昇格(フェイルオーバーの中核)。pg_rewind=旧マスタを新マスタのスタンバイへ差分再同期(ベースバックアップ再取得より高速だが旧マスタのWALが前提)
- pg_receivewal=WAL継続受信でarchive_command不調時の保全にも使える。ロジカルレプリケーションの競合は適用ワーカー停止→手動介入必須。ストリーミングレプリケーションは自動再接続が基本だが、WAL欠落時はベースバックアップ再取得が必要
進捗の記録にはログインが必要です。
理解度チェック
(軽い確認用)Q1. マスタサーバがハードウェア障害で完全に応答不能になった。運用中のスタンバイを新しいマスタとして書き込み可能な状態にするために実行すべきコマンドは?
Q2. マスタ昇格後、まだ稼働可能だった旧マスタを新マスタに従属するスタンバイとして復帰させたい。ベースバックアップを一から取り直すよりも高速に再同期する手段は?
Q3. ロジカルレプリケーションのサブスクライバ側で、パブリッシャ側には無いUNIQUE制約に反する変更が届き、適用ワーカーが停止してしまった。この状況に対する正しい説明・対応は?

