■2-09■ WALとは(Write Ahead Logging)日本PostgreSQLユーザ会の仕組み分科会で発表したWALとPITRの資料とpgpool-IIのオンラインリカバリに関する資料がありますので、こちらも参照してください。 WALはトランザクションロギングを行うための一手法です。WALが実装されたことにより、ハードディスクのアクセス回数が減ったため、データベースシステムのパフォーマンスが向上しました。また、サーバやOSが突然クラッシュしても、データの一貫性を損なわずにデータベースシステムを復旧できるようになりました(補足 1)。 WALはPostgreSQLのパフォーマンスと信頼性を確保するための重要な機構ですが、その理解にはUnix系OSの基礎知識が必要です。ここでは、OSのデータ書き込みから順を追ってWALの仕組みを解説していきます。 OSのデータ書き込みUnix系OSはハードディスクにデータを書き込む際、一旦カーネルのバッファキャッシュに保存し、後に適当なタイミングでハードディスクに書き込みます。アプリケーション側の書き込みとハードディスクへの書き込みが非同期に行われるので、これを非同期書き込みといいます。なぜ二段階に分けるかといえば、ハードディスクの動作が遅いからです。複数のデータをバッファキャッシュに溜めて、後で一挙にデータ書き込みをしたほうがOS全体のパフォーマンスが向上します(【図.2-12】参照)。 図.2-12 一般的なOSのデータ書き込み(非同期) ただし、バッファキャッシュに保存した直後にトラブルが起こると、当然ながらデータはハードディスクに記録されることなく消失してしまいます。これはすべてのアプリケーション(特にデータベースシステム)にとって致命的な問題です。 このような事態を避ける方法として、同期書き込み(常にバッファキャッシュとハードディスクの内容を一致させる)があり、次の2つの方式があります(【図.2-13】参照)。
図.2-13 同期書き込み 以降、同期書き込みは実線、非同期書き込みは破線で表示し、カーネルのバッファキャッシュは図示しません。 バージョン7.0までのデータ書き込み:WAL以前バージョン7.0 まではWAL が実装されておらず、ハードディスクへのデータ書き込みは、非同期書き込みか同期書き込み(デフォルト)のいずれかを選択しなければなりませんでした。非同期書き込みの場合、テーブルのデータを更新してもすぐにはハードディスクに書き込まれません。ディクスアクセス回数が減るのでパフォーマンスは向上しますが、停電などの障害によりOSやデータベースプロセスがクラッシュした場合、データの一貫性が損なわれて甚大な被害が出る可能性があります。 一方、同期書き込みはデータの更新ごとにハードディスクに書き込みますので、データの一貫性は保たれますが、ハードディスクアクセスが頻発するためパフォーマンスが大幅に低下します。 つまり、WAL導入以前は、非同期書き込みで安全性を犠牲にするか、同期書き込みでパフォーマンスを犠牲にするかを選択しなければなりませんでした(【図.2-14】参照)。 図.2-14 非同期書き込みと同期書き込み WALの基本動作バージョン7.1からWALが実装されました。ここでデータの検索、および更新がどのように行われるのか、各バッファとハードディスクとのデータのやりとりに焦点を合わせて説明します。なお、WALの基本的動作を把握するため細部の説明を省き、概略のみ説明します。WALの詳細は【2-10】でまとめて解説します。 (a)検索(【図.2-15】参照) 共有バッファにキャッシュされたデータを検索します。目的のデータが存在すればそのデータを利用し、存在しない場合はハードディスクからデータを読み出します。 図.2-15 SELECT (b)更新(補足 3)(【図.2-16】参照)
図.2-16 UPDATE データ操作は共有バッファをキャッシュとして利用しているので、高速にデータ処理ができます。また、トランザクションログを同期書き込みで保存しているので、トラブルがあってもWALログを使ってデータベースを復旧することができます。 復旧事故後の復旧について解説します。いくつかのSQL文が実行された直後、システムがクラッシュしたとします。ここでPostgreSQLを再起動すると、復旧処理がはじまります。ハードディスクには、最後のCHECKPOINT時点でのデータが保存されており、それ以降の変更はWALログにだけ保存されています。そこで、WALログに記録されたSQL文を順に再実行(Redo)することで、クラッシュ直前の状態にまで復旧することができます(【図.2-17】参照)。 「WALの詳細」へ進む → 図.2-17 復旧処理 補足(1) ハードウエア障害など、深刻なトラブルの場合は復旧できません。 (2) 正確には、fsync()システムコールは“カーネルバッファの内容をハードディスク上の内容と一致させる処理”であり、“同期的にデータを書き込む処理”ではありません。しかし、本書では説明の複雑化を避けるため、fsync()を呼ぶことも同期書き込み方式として扱います。 (3) PostgreSQLはデフォルトでautocommit(オートコミット)が有効です。オートコミットの場合、SQL文の実行直後にコミットされるので、通常は(1)(2)が連続して行われます。 (4) WALログはデータベースクラスタ以下のサブディレクトリ“pg_xlog”に、16[Mbyte] のセグメントファイルとして複数おかれています。 [PREVIOUS][UP][NEXT] |