Chapter 12. ログ先行書き込みプロトコルに基づくロギング――Write-Ahead Logging (WAL)

Table of Contents
12.1. 概説
12.1.1. 現時点の WAL のメリット
12.1.2. 将来のメリット
12.2. 実装
12.3. WALの設定

著者: Vadim Mikheev、 Oliver Elphick

12.1. 概説

Write Ahead LoggingWAL)はトランザクションロギングを行うための一般的な手法です。詳しい説明はすべてでなくても、たいていのトランザクション処理について書かれた本に書かれています。簡単にいうと、WALの基本的な考え方は、(テーブルやインデックスがある)データファイルに書く前に変更分が先立ってロギングされていなければいけないという点にあります。 すなわち、ログレコードが永続的な記憶装置に吐き出されてからということになります。このような手順に従って処理を行えば、たとえクラッシュがおきてもログを使ってデータベースをリカバリできるため、トランザクションのコミットのたびにデータページをディスクに吐き出す必要がなくなります。リカバリの時点では、まず、データページに対してまだ行われていない変更分はログレコードを使って再実行(これがロールフォワードリカバリです。 すなわちREDOとして知られています)され、コミットされていないトランザクションによる変更はデータページから削除されます(これはロールバックワードリカバリ、すなわちUNDOとして知られています)。

12.1.1. 現時点の WAL のメリット

WALを採用する1つ目の明白な利点はディスクへの書き込み回数が大幅に減ることです。 というのは、トランザクションコミットのときにログファイルだけをディスクに吐き出せばよいからです。 マルチユーザ環境では多くのトランザクションのコミットをログファイルの1回のfsync()で済ますことができます。それだけではなく、ログファイルへの書き込みはシーケンシャルに書き込まれるため、データページを吐き出すコストに比べログファイルの同期はずっと低コストになります。

2つ目のメリットは、データページの一貫性です。実際、WALが導入される前は、PostgreSQLはクラッシュしたときに一貫性を保てるという保証はありませんでした。WAL導入以前では、書き込み中にクラッシュした場合に次のようなことが起こる可能性がありました。

  1. 存在しないテーブルの行をインデックスタプルが指す

  2. (B-treeの)分割中にインデックスタプルが失われる

  3. 部分的にしかデータが書かれていないために、完全にテーブルやインデックスのページの内容が壊れてしまう

このインデックスに関わる問題(上記の1と2)は、fsync()の呼び出しを追加すれば解決できる可能性があります。 しかしWALがない場合、最後の問題を解決するかというのはわかりません。WALは、クラッシュ後の修復時にページの一貫性を保証するために必要とされるページであれば、そのデータページ内容全体をログに保存します。

12.1.2. 将来のメリット

UNDO 操作は実装されていません。このためアボートしたトランザクションは依然としてディスクスペースを使っており、トランザクションの状態を記録するために永続的なpg_clogファイルを必要としています。 何故なら、トランザクション識別子を再利用することができないからです。ひとたびUNDOが実装されれば、pg_clogを永続的に保持する必要はありません。 pg_clog をシャットダウン時に削除することができるようになります。(しかし、この問題の緊急性は pg_clog にセグメント分割格納方式を適用する、つまり、古いpg_clogエントリを永遠に保持する必要をなくすことで大きく減少します。

またUNDOによって、savepointsを実装することができます。 そうすれば、不正なトランザクション処理(コマンド入力ミスによるパースエラー、重複したプライマリ/一意キーへの挿入、など)を部分的にロールバックすることができます。 savepointsはトランザクションのエラーになる前に実行された有効な操作を継続またはコミットすることができます。今のところ、どんなエラーもトランザクション全体を無効にするので、トランザクションのアボートが必要になります。

WALによって、データベースのオンラインバックアップとリストア(BAR)を行うための新しい方法を実装できる可能性があります。この方法では、定期的にデータファイルを他のディスク、テープ、あるいは他のホストに保存し、またWALのログファイルをアーカイブする必要があります。データファイルのコピーとアーカイブされたログを使って、クラッシュの後にリカバリを行ったのと同じ状態にリストアすることができます。データベースファイルコピーを作るたびに古いログファイルを削除してもかまいません。この機能を実装するためには、データファイルとインデックスの生成と削除をロギングすることが必要です。 また、データファイルをコピーする手法を開発する必要があります(OSの提供するコピーコマンドは使えません)。

これらの利点を実現する上での問題は、WAL エントリの保存を(例えば、トランザクションのUNDO を行う場合は起こり得るトランザクションの最長実行期間など)起こり得る期間行う必要があるということです。現在の WAL の書式は、ディスクページのスナップショットを多く持つため、かなり大きなものです。現時点では、保持する必要があるのは高々1,2回のチェックポイント期間分だけですので、これはあまり深刻な問題ではありませんが、この将来のメリットを達成するためには、何らかの圧縮された WAL 書式というものが必要になるものと考えています。