TECH BLOG
技術ブログ

ARTICLE

  • 2023-08-01 PostgreSQLPostgreSQL パラメータ

    出力されたWALファイルのサイズとチェックポイントが発生するタイミング

WAL ファイルの出力を契機としたチェックポイント

今回は WAL ファイルの出力を契機として行われるチェックポイントについて、調べた結果をお伝えします。
WAL ファイルの出力を契機としたチェックポイントとは、更新処理などによって発生した WAL ファイルの合計サイズが閾値を超えたために行われる、緊急的なチェックポイントのことです。

ちなみに PostgreSQL のログ上では

2023-06-21 10:46:09.135 JST [30084] LOG: checkpoint starting: wal

という形で出力されます。

緊急的なチェックポイントなので、WAL ファイルの出力を契機としたチェックポイントは可能な限り発生させず、時間経過を契機としたチェックポイントが繰り返し行われる状況が理想です。

公式ドキュメントでの説明

公式ドキュメント( https://www.postgresql.jp/document/current/html/wal-configuration.html )の説明を引用します。

サーバのチェックポインタプロセスは、自動的にチェックポイントを時々実行します。 checkpoint_timeout秒が経過するか、またはmax_wal_sizeに達するか、どちらかの条件が最初に満たされるとチェックポイントが開始されます。

翻訳元の英文は下記となります。

A checkpoint is begun every seconds, or if is about to be exceeded, whichever comes first.

この文章だけ読むと、「WAL ファイルの出力サイズが max_wal_size 付近になったらチェックポイント処理が行われるのか」と理解してしまいそうになるのですが、実際にはそうでありません。
WAL ファイルの出力サイズを契機としたチェックポイント処理には、max_wal_size と checkpoint_completion_target が関係しています。

ソースコードの確認

ここで内部的なお話となってしまうのですが、WAL ファイルの出力サイズを契機としたチェックポイント処理を行うかどうかは xlog.c の XLogCheckpointNeeded 関数で決定されます。
ちなみに xlog.c は src/backend/access/transam にあります。

XLogCheckpointNeeded 関数

XLogCheckpointNeeded 関数は数行のコードですので、下記に引用します。
バージョンは PostgreSQL 15.3 です。

bool
XLogCheckpointNeeded(XLogSegNo new_segno)
{
    XLogSegNo   old_segno;

    XLByteToSeg(RedoRecPtr, old_segno, wal_segment_size);

    if (new_segno >= old_segno + (uint64) (CheckPointSegments - 1))
        return true;
    return false;
}

8 行目の if 文が、チェックポイント処理を行うかどうかの判定式となります。
ざっくりとした説明になりますが

  • new_segno は、書き込み先(コメントでは「いっぱいになったばかりの」と表現されています)の WAL ファイル
  • old_segno は、最後にチェックポイントされた時点の WAL ファイル
  • CheckPointSegments は、チェックポイントを発生させる WAL ファイルの数の閾値

という内容になっています。
つまりは、CheckPointSegments の値がチェックポイントを発生させるかどうかに関係するのですが、この値は xlog.c の CalculateCheckpointSegments 関数で算出されます。

CalculateCheckpointSegments 関数

CalculateCheckpointSegments 関数も(コメントを除くと)数行のコードですので、下記に引用します。

static void
CalculateCheckpointSegments(void)
{
    double      target;

    target = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /
        (1.0 + CheckPointCompletionTarget);

    /* round down */
    CheckPointSegments = (int) target;

    if (CheckPointSegments < 1)
        CheckPointSegments = 1;
}

こちらもざっくりとした説明になりますが、max_wal_size と checkpoint_complation_target からチェックポイントを発生させるかどうかの閾値を算出しています。
max_wal_size が 1024 MB、WAL ファイルのサイズが 8 MB で、checkpoint_completion_target が 0.9 の場合、

(1024  / 8 ) / (1.0 + 0.9) = 約 67 .3

となります。
この 67.3 は WAL ファイルの数を表しますので、サイズに変換する( 8 MB をかける)と 544 MB となります。

max_wal_size が 1024 MB、WAL ファイルのサイズが 8 MB で、checkpoint_completion_target が 0.5 の場合、

(1024  / 8 ) / (1.0 + 0.5) = 約 85.3

となり、こちらもサイズに変換すると 688 MB となります。

結局のところ、どれぐらいの WAL ファイルが作成されたらチェックポイントが行われるのか

ということですが、checkpoint_completion_target が 1 に近づくにつれ、チェックポイントが発生しやすくなるということになります。
具体的には checkpoint_completion_target が 0.9 の場合、max_wal_size の 53 % 前後の WAL ファイルが作成された場合にチェックポイントが行われます。
checkpoint_completion_target が 0.5 の場合、max_wal_size の 67 % 前後の WAL ファイルが作成された場合にチェックポイントが行われます。

まとめ

今回の記事では、WAL ファイルの出力サイズを契機としたチェックポイント処理の実行タイミングが、max_wal_size と checkpoint_completion_target の値によって変動することを説明いたしました。
公式ドキュメントの情報は非常に有益ですが、それと合わせてソースコードを確認すると、より PostgreSQL を理解できるようになります。
とは言ってもソースコードは量が膨大な上、複雑ですので、ソースコードのコメントや各ディレクトリに配置されている README ファイルを読むことから始めるのがお勧めです。

CATEGORY

ARCHIVE

PostgreSQLの
ハイパフォーマンスチューニングのご相談は
株式会社インサイトまで
お気軽にお問い合わせください。

CONTACT