著者: Vadim MikheevとOliver Elphick
Write Ahead Logging (WAL) はトランザクションロギングを行うための一般的な手法です。詳しい説明 はすべてでなくても、たいていのトランザクション処理について書かれた 本に書かれています。WALの基本的な考え方は、テー ブルやインデックスがあるデータファイルに書く前に変更分が先立ってロ ギングされていなければいけないという点にあります。すなわち、ログレ コードが永続的な記憶装置に吐き出されてからということになります。こ のような手順に従って処理を行えば、たとえクラッシュがおきてもログを 使ってデータベースをリカバリできるため、トランザクションのコミット の度にデータページをディスクに吐き出す必要がなくなります。リカバリ の時点では、データページに対してまだ行われていない変更分はログレコー ドを使って再実行されます。(これがロールフォワードリカバリです。すな わち REDOとして知られています。)また、コミットされていないトランザ クションはデータページから削除されます。(これはロールバックワードリ カバリ、すなわちUNDOとして知られています。)
WALを採用する一番目の明白な利点はディスクへの書 き込み回数が大幅に減ることです。というのは、トランザクションコミッ トの時にログファイルだけをディスクに吐き出せば良いからです。マルチ ユーザ環境では多くのトランザクションのコミットがログファイルへの一 回の fsync()ですますことができます。それだけ ではなく、ログファイルへの書き込みはシーケンシャルに書き込まれるた め、データページを吐き出すコストに比べログファイルへの書き込みはずっ と低コストになります。
2番目のメリットは、データページの一貫性です。本当のこというと WALが導入される前は、 PostgreSQLはクラッシュしたときに一貫性 を保てるという保証はありませんでした。WAL導入以 前では、書き込み中にクラッシュした場合に次のようなことが起こる可能 性があります。
存在しないテーブルの行をインデックスタプルが指す
(btreeの)分割中にインデックスタプルが失われる
部分的にしかデータが書かれていないために、完全にテーブ ルやインデックスのページの内容が壊れてしまう
今回のこのWALの最初の実装では、時間が足りなかっ たのでUNDO操作は実装されていません。このためアボートしたトランザク ションは依然としてディスクスペースを使っており、トランザクションの 状態を記録するために永続的なpg_logファイルを 必要としています。何故なら、トランザクション識別子を再利用すること ができないからです。ひとたびUNDOが実装されれば、 pg_logを永続的に保持する必要はありません。 pg_logをセグメントに分割し、古いセグメントを 削除することによってシャットダウンの時に pg_logを削除することができます。
またUNDOによって、savepoints を実装すること ができます。そうすれば、不正なトランザクション処理(タイプミスによ るパースエラー、重複したプライマリ/ユニークキーへの挿入、など)を 部分的にロールバックすることができます。savepoints はトランザクショ ンのエラーになる前に実行された有効な操作を継続ないしコミットするこ とができます。今のところ、どんなエラーもトランザクション全体を無効 にするのでトランザクションのアボートが必要になります。
WALによって、データベースのオンラインバックアッ プそしてリストア(BAR)を行うための新しい方法を実 装できる可能性があります。この方法では、定期的にデータファイルを他 のディスク、テープ、あるいは他のホストに保存し、また WALのログファイルをアーカイブする必要があります。 データファイルのコピーとアーカイブされたログを使って、クラッシュの 後にリカバリを行ったのと同じ状態にリストアすることができます。デー タベースファイルコピーを作る度に古いログファイルを削除してもかまい ません。この機能を実装するためには、データファイルとインデックスの 生成と削除をロギングすることが必要です。また、データファイルをコピー する手法を開発する必要があります。(OSの提供するコピーコマン ドは使えません。)