Article

PostgreSQLのmax_slot_wal_keep_size:WAL保持量と復旧コストをどう決めるか

max_slot_wal_keep_sizeは、遅れたレプリケーションスロットのWAL保持を制限する設定です。チェックポイント時の挙動、停止時間からの容量見積もり、スロットの監視をつなげ、プライマリの容量と復旧負担の釣り合いを考えます。

Share

こはるの読みどころ

上限値だけを決める前に、止まった配信先をどこまで待てるか考えてみよう。WALの増える速さと復旧方法を並べると、必要な余裕が見えてくるよ。

こはるの読みどころ

レプリカが止まったとき、プライマリはいつまで追いつくためのログを残しておくべきでしょうか。復旧を待つための仕組みが、書き込みを続ける側のディスクを圧迫することがあります。

Christophe Pettus氏のmax_slot_wal_keep_sizeの解説は、この判断を考えるきっかけになります。有限の上限を設けるとWALの保持を制限できますが、その先では配信先の復旧が必要になる可能性があります。

レプリケーションスロットを使う運用では、設定値と復旧方法を一緒に決めたいところです。保持の仕組みから容量の見積もり、監視までをつなげると、どこに余裕を持たせるべきかが見えてきます。

スロットは配信先が止まってもWALを保持する

WALはデータベースの変更を記録するログです。レプリケーションスロットは、配信先が必要とするWALを送信側が早く捨てすぎないようにします。接続が切れても必要な資源の保持が続くことは、論理デコードの公式説明にも明記されています。

ここで効いてくるのが、スロットの保持開始位置である restart_lsn です。配信先の処理が止まってこの位置が進まず、送信側では書き込みが続けば、必要なWALの範囲が広がります。再接続に備える仕組みが、そのまま容量を使い続ける理由になるわけですね。

max_slot_wal_keep_size は、この保持に制限を設けるため、2020年9月24日公開のPostgreSQL 13で導入されました。今回の話題は既存設定の運用判断であり、説明とSQLはPostgreSQL 18の仕様を基準にしています。

既定値の -1 ではスロットによるWAL保持に上限がありません。有限値を設定すると、チェックポイント時に保持範囲が制限され、必要なWALを失ったスロットではレプリケーションを継続できなくなります。設定の公式仕様で、この条件を押さえておきましょう。

WAL保持上限はディスク使用量の上限とは異なる

上限を指定しても、pg_wal がその容量を超えないとは限りません。制限の適用はチェックポイント時なので、その間のWAL生成を収容する余裕も必要です。

また、似た名前の設定でも役割が異なります。

設定 容量設計での役割
max_slot_wal_keep_size スロットのために保持するWALの制限
wal_keep_size スタンバイ向けに残すWALの最低量
max_wal_size 自動チェックポイントに関わる目安。厳密な容量上限ではない

wal_keep_size による保持はスロットも利用できます。大きな値が設定されていれば、スロット用の上限だけを小さくしても、期待した容量までWALが減るとは限りません。さらにアーカイブに失敗すると、未アーカイブの古いWALが蓄積します。こうした保持条件はWAL構成の公式説明で確認できます。

したがって、スロットの上限とディスク空き容量は別々に監視します。スロット起因の蓄積を抑える設定だけでは、アーカイブ障害などによる容量不足まで解消できません。

許容する停止時間をWALの容量へ換算する

値を決める出発点は「何GBが一般的か」よりも、「配信先を何分待ちたいか」です。容量計画の考え方として、配信先が完全に止まる場合の追加保持量を、ピーク時のWAL生成速度と許容停止時間から見積もれます。

たとえば、毎秒8 MiBのWAL生成が30分続くと仮定します。計算は 8 × 30 × 60 = 14,400 MiB、約14.1 GiBです。これは説明用の仮定であり、実測値でも推奨設定値でもありません。

この量に停止前からの遅れを加え、再開後に追いつくまでの余裕も考えます。一方で、WAL用ボリュームには通常運用分やチェックポイント間の増加分も必要です。待ちたい時間を支える容量が収まらないなら、許容停止時間、ストレージ容量、復旧方法のどれかを見直す必要があります。

実測には、プライマリで一定間隔を空けて pg_current_wal_lsn() を取得し、2点の差を経過秒数で割る方法があります。pg_wal_lsn_diff() はLSN間の差をバイトで返します。LSNはWAL内の位置であり、データベース本体の増加量とは区別します。管理関数の仕様に沿って、通常時だけでなくバッチ処理中なども測ると判断材料になります。

スロットの残り余裕を状態と一緒に読む

容量を決めたら、その予算がどれだけ残っているかを追います。次はPostgreSQL 18のプライマリで、設定とスロットの状態を読むSQLです。設定やスロットを変更する操作は含みません。

SQL
-- 有効なWAL保持設定を読む。
SHOW max_slot_wal_keep_size;
SHOW wal_keep_size;
SHOW max_wal_size;

-- スロットごとの状態と保持開始位置を読む。
SELECT slot_name,
       slot_type,
       active,
       restart_lsn,
       wal_status,
       safe_wal_size
FROM pg_replication_slots
ORDER BY slot_name;

safe_wal_size は、スロットが lost になる危険に入るまでに追加で書けるWALのバイト数です。ディスクの空き容量ではありません。NULL は無制限設定や、すでに lost の場合にも現れるため、数値だけでは判断できません。pg_replication_slotsの公式仕様を基に、状態も合わせて読みます。

wal_status 読み取れること
reserved 必要なWALが max_wal_size の範囲内にある
extended その範囲を超えているが、WALは保持されている
unreserved 必要なWALの保持が外れ、次のチェックポイントで一部が削除され得る
lost スロットは利用できない

extended だけで故障とは断定できず、unreserved から保持された状態へ戻る場合もあります。監視の設計としては、状態の変化に加え、余裕の減り方とディスク空き容量を追い、担当者が対応する時間を残して通知するのが実用的です。

上限を決める前に配信先の戻し方を決める

同じ量のWALを失っても、配信先の構成によって復旧負担は変わります。物理スタンバイは、必要なWALがアーカイブに残り、restore_command で取得できれば、アーカイブから追いつけます。必要なWALがどこにもなければ、新しいベースバックアップからの再構築が必要です。スタンバイの動作と復旧経路を踏まえて、スロットの再作成も含む手順を用意します。

論理レプリケーションでは、新しいスロットを作るだけで、失った変更履歴が戻るわけではありません。新規スロットと対応するスナップショットから整合したデータを用意する仕組みは、論理デコードのスナップショット仕様にあります。購読先の再同期や初期コピーを含め、整合性を回復する方法を決めておきたいところです。

冒頭の問いへの答えは、「配信先を戻すために必要な時間を、プライマリが負担できる容量の範囲で待つ」です。WAL生成量を測り、有限の保持予算と監視、復旧手順をそろえることで、上限に達した後の対応まで含めて運用を設計できます。

出典

Share

Related Articles

カテゴリやタグが近い記事を続けて読めるように並べています。