HIRO Tracks

ソフトウェアエンジニアが日々学んだ知識を発信します。

PostgreSQLにおけるWAL(Write Ahead Logging)って何?

始めに

この記事では、

  • データベースの内部構造や仕組みに詳しくなりたいけど、そもそも「WALってなんやねん」という人
  • 「SQL書けるよ」だけじゃなくて、運用目線でDBに詳しくなりたい人

向けに、WALとはなんぞや?という内容について整理してみます。

参考図書は主に以下の三つ。

公式ドキュメント www.postgresql.jp

「内部構造から学ぶPostgreSQL―設計・運用計画の鉄則」

https://www.amazon.co.jp/%EF%BC%BB%E6%94%B9%E8%A8%823%E7%89%88%EF%BC%BD%E5%86%85%E9%83%A8%E6%A7%8B%E9%80%A0%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6PostgreSQL%E2%80%95%E8%A8%AD%E8%A8%88%E3%83%BB%E9%81%8B%E7%94%A8%E8%A8%88%E7%94%BB%E3%81%AE%E9%89%84%E5%89%87-Software-Design-plus-%E4%B8%8A%E5%8E%9F/dp/4297132060/ref=sr_1_1_sspa?keywords=%E5%86%85%E9%83%A8%E6%A7%8B%E9%80%A0%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6+postgresql+%E8%A8%AD%E8%A8%88+%E9%81%8B%E7%94%A8%E8%A8%88%E7%94%BB%E3%81%AE%E9%89%84%E5%89%87&qid=1687697273&sprefix=%E5%86%85%E9%83%A8%E6%A7%8B%E9%80%A0%E3%81%8B%E3%82%89%2Caps%2C228&sr=8-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1

釣りキチ翔平の備忘録 poppingcarp.com

WAL(Write Ahead Logging)って何?

その名の通り、「書く前にログ吐きましょう」という取り決めのことです。

「書き込んだその履歴をログとして吐くなら、"書き込み"=>"ログ吐く"の順番じゃないの?」という思いに反して、どうしてログを先に出力するのかというと、やりたいことは一つ。

「トランザクションの原子性を保証するため」です。

トランザクションの途中でエラーが発生した時、ロールバックまたはロールフォワードによりDB状態の復旧が可能かと思います。

この時テーブルの実体であるデータファイルは中途半端な状態で止まっていることが想定されるため、別途復旧の手掛かりが必要です。

この役割を、WALによって書き出されたログファイルが担います。

DBスペシャリスト試験にもイイ感じにこの辺を聞く質問が出ていますね。

www.db-siken.com

www.db-siken.com

PostgreSQLにおけるWAL

PostgreSQLのWAL挙動例

PostgreSQLにおいてWALが保存される領域は「WALバッファ」「WALファイル」と分かれています。前者がメモリ領域、後者がディスク領域です。

メモリだと揮発してしまうので最終的にはディスク領域に保存する必要があるものの、1トランザクション内のすべての更新処理(UPDATE/SELECT/DELETE)それぞれについてディスク書き込みしていると性能が遅くなってしまいます。

これを避けるためのキャッシュとして、WALバッファを置いています。

WALバッファがディスクに書き込まれるトリガーとしては、以下の二つがあります。

  • ユーザが(BEGIN TRANSACTIONの後)COMMITコマンドを実行する
  • WALバッファサイズが規定量を超える(設定値:wal_buffers)を超える
    • 似た設定値「max_wal_size」がありますが、こちらはWALファイル(ディスク領域)の最大値。こちらはチェックポイントの頻度に関連

このことから、wal_buffersが小さすぎるとディスク書き込みが増えて性能劣化が起きてしまいそうですね。

※チェックポイント機構や、実際のデータファイルの更新機構については別記事で語ろうと思います

内部構成の詳しいところは以下のブログを参考にさせてもらいました!

poppingcarp.com

実際にinstallしてwal_buffersの設定値見てみた

wal_buffers

LocalPCにinstallして設定値を確認してみました。(2023/06/25時点で最新のPostgreSQL@15.3)

ファイル名は「postgresql.conf」、ファイルパス(MacOS,Intell)は「/usr/local/var/postgresql@15」でした。

書籍通り、wal_buffersの設定は

  • デフォルトは-1(別設定値"shared_buffers"の1/32(約3%)の容量に等しい大きさをPostgreSQLが選択してくれる)
    • shared_buffersのデフォルトは128MBなので、wal_buffersは4MB となっている

ことが確認できました。

PITR各種パラメータ

WALはPITRリストア方式(Point In Time Recovery)でも利用されます。 利用のために意識すべき設定値を記載しておきます。

20.5. ログ先行書き込み(WAL)

wal_level

WALにどの程度の情報を書き込むかを指定する。以下、下に行くにつれて詳しい設定値となる。

minimal

replica(デフォルト)(PITRするには最低限これにしておく必要がある)

logical

archive_mode

WALファイルをWALアーカイブとして保存するかどうか

PITRをするにはONにしておく必要がある。

デフォルトだとOFF

archive_command

WALファイルをWALアーカイブとして保存しておくためのCOPYコマンドを記載する。

PITRのためには設定必須。

最後に

今回はPostgreSQLにおける「WAL(Write Ahead Logging)」という内容だけで切り取って、簡単にまとめてみました。

以下について整理中なので、出来次第、記事にしていこうかなと思います!

  • PostgreSQLの
    • トランザクション分離レベルについて
    • リカバリについて(今回紹介したWALをする利用する
    • チェックポイント機構
    • VACUUM・不要領域回収について
    • バックアップについて(物理バックアップ・論理バックアップ)
    • バージョンアップについて
    • AWS(RDS)だとどこまでチューニングできるのか