🐈

PostgreSQLのチェックポイント実行契機

2023/12/12に公開

はじめに

これは、 PostgreSQL Advent Calendar 2023 シリーズ1の12日目の記事です。

今回は、業務でチェックポインタプロセスのソースコードを読むことがあったので、チェックポイントがいつ実行されるかについて調べました。
半分はみんながよく知ってること、半分は知らなくても特に問題ないこと、なのでたぶんこの記事はあまり役に立たないと思います・・・

チェックポイントとは?

まずおさらいしておきましょう。ググってみるとITパスポートの勉強サイトが出てきました。このサイトによるとチェックポイントは以下のようです。

データベースにおいてトランザクションの更新情報が、ディスク上のデータベースに反映されるタイミングのこと。

https://www.itpassportsiken.com/word/チェックポイント.html
チェックポイントという用語はITパスポートにも出題されるみたいですね。知らなかった。

PostgreSQL的に言うと、共有バッファ上のダーティなページをディスクに書き出す処理のことになります。チェックポイント処理の一部といってよいかはわかりませんが、不必要になったWALの削除やリサイクルもチェックポイントのタイミングで実行されます。

詳しくは色々な記事があるので、それらを参考にするのがいいと思います。

調査方法

調査環境

  • PostgreSQL 16.1

チェックポイントのログを見たいので、log_checkpoints=onにしておきましょう。

方法

src/backend/access/transam/xlog.cCreateCheckPointという関数があり、この関数を呼び出すことでチェックポイントが実行されます。これ呼び出している部分の実装やコメントを読んだり、ドキュメントを読んだりして調査しました。

ちなみに、CreateCheckPointは以下になります。
https://github.com/postgres/postgres/blob/REL_16_1/src/backend/access/transam/xlog.c#L6423-L6870

チェックポイントの実行契機

簡単にチェックポイントの実行契機を3つに分類しました。

  • 時間とWALファイルサイズ
  • PostgreSQLの起動・停止
  • SQLコマンド

それぞれ見ていきましょう。

時間とWALファイルサイズ

これが一番初めに思い浮かぶのではないでしょうか。
PostgreSQLのチェックポインタプロセスは、以下の条件のどちらかが満たされるとチェックポイントを開始します。

  • 前回のチェックポイントからcheckpoint_timeout(デフォルト5分)時間が経過する。
  • 前回のチェックポイントからmax_wal_size(デフォルト1GB)サイズのWALが生成される。

ただし、前回のチェックポイント以降書き出すWALがない場合はチェックポイントはスキップされます。

PostgreSQLの起動・停止

起動

通常起動の場合はチェックポイントは実行されませんが、リカバリが走る場合はチェックポイントが実行されます。

  • リカバリ中:checkpoint_timeout時間が経過している、またはmax_wal_sizeサイズ以上のWALファイルをリカバリしている場合にチェックポイントが実行される(リカバリ中のチェックポイントをリスタートポイントと呼ぶらしい)。ただし、リプレイした最後のチェックポイントがリスタートポイントである場合は実行されない。
  • リカバリ完了時(スタンバイからの昇格):一貫性のために必須ではないが、最後のリスタートポイントがかなり前になってしまうのを避けるためにチェックポイントが実行される。リカバリ完了のレコードを作成した後、リカバリモードから抜けてSQLを受け付けるようになった後でチェックポイントが実行される。(これをオンラインチェックポイントらしい)
  • リカバリ完了時(スタンバイからの昇格以外):リカバリした内容をディスクへフラッシュするため、チェックポイントが実行される。

停止

PostgreSQLを停止するときにチェックポイントが実行されます。ただし、以下の停止のときのみで、即時シャットダウンのときはチェックポイントは実行されません。

  • スマートシャットダウン(pg_ctl stop -m smart
  • 高速シャットダウン(pg_ctl stop -m fast

SQLコマンド

CHECKPOINT

当たり前ですが、CHECKPOINTコマンドを実行するとチェックポイントが実行されます。

SELECT pg_backup_start(label => 'label', fast => true)

これは低レベルAPIを使用したベースバックアップを作成するときに、バックアップを開始する関数です。2番目の引数にtrueを渡すかfalseを渡すかでチェックポイントの挙動が変わります。

  • true:即時にチェックポイントが要求されます。
  • false:次にスケジュールされたチェックポイントが完了するまで待機します。

CREATE DATABASE

CREATE DATABASE name WITH STRATEGY = strategyでデータベース作成時の手法を指定できます。以下の2種類があり、FILE_COPYが指定された場合にデータベース作成前後でチェックポイントが実行されます。

strategy 説明
WAL_LOG デフォルト。ブロックごとにコピーされ、各ブロックがWALに書かれる。
FILE_COPY ファイルシステムレベルでディレクトリ全体がコピーされる。

チェックポイントを実行する必要がある理由は以下の通りです。

  • データベース作成前:コピー元のデータベース(テンプレートデータベース)への変更をディスクへフラッシュし、データベースがディスク上で最新であることを保証するため。
  • データベース作成後:ディレクトリコピーが再実行されないことを保証するため。

これにドキュメントにも記載されています。
https://www.postgresql.org/docs/16/sql-createdatabase.html#CREATE-DATABASE-STRATEGY

DROP DATABASE

以下の流れでチェックポイントが実行されます。

  1. 共有バッファ上にある削除対象のデータベースのページを削除する。
  2. 削除対象のデータベースのファイルに対するfsync要求とリンク解除要求をキャンセルするようにチェックポインタプロセスに伝える。
  3. 2によって送信されたメッセージをチェックポインタプロセスが受信したことを確認するためにチェックポイントを実行する。

このような作業を行わないと、削除されたデータベースのページをフラッシュするようなことが起こります。そして、同じOIDをもつ新しいデータベースが作成されていた場合には上書きされてしまいます。

ALTER DATABASE SET TABLESPACE

ALTER DATABASE SET TABLESPACEコマンドが実行される前後でチェックポイントが実行されます。これは、CREATE DATABSEと同様に説明することができます。

  • データベース変更前:コピー元のデータベースへの変更をディスクへフラッシュし、データベースがディスク上で最新であることを保証するため。
  • データベース変更後:ディレクトリコピーが再実行されないことを保証するため。

DROP TABLESPACE

DROP TABLESPACEを実行するとき、ディレクトリが空でないとテーブルスペースを削除できません。しかし、テーブルスペースにファイルが残存する場合があります。例えば、DROP TABLEの実行によって、次のチェックポイントで削除するようにスケジュールされた空のファイルが残っている可能性があります。そのファイルを消してよいかどうかをチェックするためにチェックポイントを強制的に実行し、空ファイルを削除します。

まとめ

PostgreSQLのチェックポイント実行契機を調べてみました。
特にSQLコマンドの部分は今まであまり意識したことがなかったですが、確かにチェックポイント必要だなとわかり、勉強になりました。
間違っていることを書いているかもしれませんので、有識者のコメントお待ちしています!

おまけ

NTTデータグループのSlideShareの発表資料を以下にまとめています。今年の資料だけで20件を超えました。ぜひご覧ください!
https://zenn.dev/shinyakato/articles/ab33eef9ae2f27

Discussion