Article

HA構成でもPostgreSQLのcheckpoint_timeoutを長くしすぎない理由

PostgreSQLのcheckpoint_timeoutを長くすると、プライマリだけでなくスタンバイの再起動時にもWAL再生量が増える可能性があります。HAを復旧時間の代替と考えず、チェックポイント、restartpoint、監視、障害訓練を一つの可用性設計として扱う理由を整理します。

Share

こはるの読みどころ

レプリカがあるから復旧時間の設定を緩めてよいのか、WALとrestartpointの仕組みから一緒に切り分けてみよう!

こはるの読みどころ

checkpoint_timeoutを45分に延ばしたプライマリが落ちても、スタンバイへ切り替えれば復旧を待たずに済む——HA構成なら、そう考えたくなる場面があります。

ただし、その判断が成立するのは切り替え先が動き続ける間です。昇格後のスタンバイまで再起動すると、長くしたチェックポイント間隔が再び復旧時間へ効いてきます。

2026年8月12日に公開された投稿をきっかけに、チェックポイントとスタンバイのrestartpointがどう結び付くのかをたどります。最後には、checkpoint_timeoutを性能だけでなく可用性の目標から決めるための見方を整理します。

チェックポイント間隔が長いほど再起動時のREDO範囲が広がる

PostgreSQLは、データファイルより先に変更内容をWALへ記録します。チェックポイントでは、その時点までのdirty pageをディスクへ書き出し、クラッシュ後にどのWAL位置からREDOを始めればよいかを確定します。仕組みの詳細はPostgreSQL 18のWAL設定ドキュメントで説明されています。

現在のPostgreSQL 18では、checkpoint_timeoutの既定値は5分、設定範囲は30秒から1日です。自動チェックポイントはこの時間に達したときだけでなく、max_wal_sizeへ近づいたときにも始まります。公式のパラメータ説明は、checkpoint_timeoutmax_wal_sizeを増やすとクラッシュリカバリに必要な時間が延びる可能性を明記しています。

ここでの値は「5分なら5分以内に復旧する」という保証ではありません。再生するWAL量、ストレージ性能、CPU、WALに含まれる処理などで実時間は変わり、今回の投稿でも実際の起動・再生時間はcheckpoint_timeoutを超え得るとされています。checkpoint_timeoutは復旧時間そのものではなく、再起動時に戻る基点を作る間隔として見るのが近いですね。

スタンバイのrestartpointはプライマリのcheckpointレコードに依存する

物理スタンバイは、プライマリが生成した同じWALストリームを受け取り、継続的に適用します。スタンバイ運用の公式説明によると、再起動後には受信済みのWALを再び適用し、アーカイブ、ローカルのpg_wal、ストリーミングの順に利用可能なWALを探します。

スタンバイ上では、通常時のチェックポイントに相当する処理をrestartpointと呼びます。restartpointは処理済みのWALをどこまで再走査しなくてよいかをpg_controlへ記録しますが、プライマリのcheckpointレコードに到達した場所でしか作れません。そのため、公式ドキュメントが示すとおり、プライマリのチェックポイントより高い頻度でrestartpointを作ることはできません。

一方、稼働中のスタンバイはpg_promote()で昇格でき、PostgreSQL 18の管理関数は昇格完了を待つ操作も提供しています。プライマリだけが停止し、スタンバイがそのまま昇格できる障害なら、HAは確かに長いプライマリ復旧を待たずにサービスを戻す手段になります。

問題は、その後に昇格先も再起動するケースです。ホスト障害、ローリング再起動の手順ミス、同じワークロードで再現する障害などで両ノードが順に再起動すれば、スタンバイ側も直近のrestartpointからWALを再生します。つまりHAは「生きている別ノードへ逃がす」仕組みであり、両ノードの再起動コストを消す仕組みではありません。

checkpoint_timeoutは書き込み負荷とRTOの両方で決める

それならcheckpoint_timeoutを短くすればよい、という単純な話でもありません。チェックポイントを頻繁にすると再実行するWALを抑えやすい一方、dirty bufferの書き出し回数が増え、full_page_writesが有効ならチェックポイント後の最初のページ変更でfull-page imageも増えます。WAL設定の解説も、速いクラッシュリカバリと追加I/Oの間にトレードオフがあると説明しています。

PostgreSQL 18のcheckpoint_completion_targetは既定値0.9で、チェックポイントの書き込みを利用可能な時間の大部分へ分散します。短い間隔でI/Oを集中させるのではなく、まずこの平準化が機能しているか、max_wal_size到達による要求チェックポイントが多すぎないかを見たいところです。

今回の投稿は、安全側の出発点としてcheckpoint_timeoutを既定の5分から変更しないことを勧めています。公式ドキュメントはチューニング自体を禁止していませんが、長くするほど復旧時間が増える可能性を明示しています。したがって変更理由を「チェックポイントが重そうだから」だけにせず、許容できるRTOと実測したI/Oの両方で説明できる状態にしておく必要があります。

PostgreSQL 17以降はpg_stat_checkpointerで両ノードを観測する

設定変更の前に、現在値と累積統計を採ります。PostgreSQL 17以降なら、次のSQLでチェックポイントとrestartpointの回数、書き込み時間、同期時間を同じビューから確認できます。

SQL
SHOW checkpoint_timeout;
SHOW checkpoint_completion_target;
SHOW max_wal_size;
SHOW log_checkpoints;

SELECT
  num_timed,
  num_requested,
  num_done,
  restartpoints_timed,
  restartpoints_req,
  restartpoints_done,
  write_time,
  sync_time,
  buffers_written,
  stats_reset
FROM pg_stat_checkpointer;

pg_stat_checkpointerPostgreSQL 17で追加され、チェックポイント関連の列がpg_stat_bgwriterから移されました。PostgreSQL 18の統計ビュー仕様では、要求回数には実行できずにスキップされたrestartpointも含まれ、実際に完了した回数はrestartpoints_doneで分かるとされています。単発の値だけでなく、一定時間の差分をWAL生成量や負荷と並べて見るのがよいでしょう。

PostgreSQL 16以前ではビュー構成が異なります。チェックポイントの回数と所要時間は当時のpg_stat_bgwriterで確認し、restartpointはサーバログと組み合わせます。現行版ではlog_checkpointsが既定で有効で、チェックポイントとrestartpointの書き込み量や時間をログへ記録します。

SQL
SELECT
  checkpoints_timed,
  checkpoints_req,
  checkpoint_write_time,
  checkpoint_sync_time,
  buffers_checkpoint,
  stats_reset
FROM pg_stat_bgwriter;

さらに、レプリケーション遅延は別の軸です。スタンバイがWALを受信・再生し切れていなければ、チェックポイント間隔だけを論じても復旧像は見えません。ストリーミングレプリケーションの監視説明に沿って、プライマリのpg_stat_replicationとスタンバイのpg_last_wal_receive_lsn()pg_last_wal_replay_lsn()も一緒に追います。

フェイルオーバー後の再起動まで測って設定変更を判断する

checkpoint_timeoutを長くする前に、平常時のI/Oだけでなく障害時の経路をテストへ入れます。検証環境で代表的なWAL生成負荷を流し、プライマリ停止からスタンバイ昇格までの時間、昇格後ノードを再起動して接続可能になるまでの時間を別々に測ると、HAが吸収できる時間と吸収できない時間を切り分けられます。

ローリング再起動の自動化も同じ観点で見直せます。最初のノードが規定時間内に戻らないときは後続ノードを再起動しないこと、昇格先の役割を認識すること、手動介入時の停止条件が決まっていることを、設定変更と同じレビュー対象にします。これはPostgreSQLのパラメータだけでは保証されない運用側の仕事です。

マネージドPostgreSQLでは、設定可能な範囲、フェイルオーバー方式、ログや統計の公開方法がサービスごとに異なります。上のSQLをそのまま適用できない場合も、判断軸は変わりません。プライマリとスタンバイの両方について、再起動時のWAL再生をどこまで許容できるかをサービス固有の手段で測ります。

結論として、HAレプリカは長いcheckpoint_timeoutの安全装置にはなりません。稼働中のスタンバイへ切り替える一度目の障害には有効でも、そのノードまで再起動する二度目の障害では同じWAL履歴とrestartpointの制約へ戻るからです。既定値から動かすなら、性能改善の測定だけでなく、RTOを満たす二段階の障害訓練までそろって初めて判断できる、と考えるのが実務的です。

出典

  • Title: Jeremy Schneider: Postgres Checkpoint Followup and Collation Visualization and Codex Luna
  • URL: https://postgr.es/p/9s8

Share

Related Articles

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