PostgreSQLの概要とアーキテクチャ
WAL(Write Ahead Logging)とは
さて、何度かWALファイルという言葉が出てきました。WALは、Write Ahead Loggingの略で、トランザクションログと呼ばれることもあります。
PostgreSQLではデータ書き込みに先立ってWALファイルに変更内容を書き出し、共有バッファ上のデータを書き換え、ディスク上のテーブルやインデックスのファイルにはすぐには書き込みません。これにより、ディスク書き込みを節約する一方で、万が一マシンがダウンした場合にはWALファイルに基づいて復旧をすることができます。
また、このWALファイルを継続的に保管しておくことにより継続的なデータのバックアップ(アーカイブロギングによるバックアップと呼ばれます。WALは変更内容の記録なので、別途、初期状態のバックアップを取る必要があります)を実現することができます。これは多くのデータベース製品で採用されている方法で、PostgreSQLでも実現されています。
WALファイルは16MB単位で標準設定では3個のファイルです。1つのファイルを書き尽くすと次のファイルに進み、すべて使うと元のファイルを名前を変えて上書きして書き込みしていきます。アーカイブモードを指定してある場合、古いWALファイルは別の場所にコピーされ保管されます。
VACUUMと追記型アーキテクチャ
PostgreSQLのアーキテクチャで特徴的な点は、テーブルのデータ書き込みにあたり、追記型アーキテクチャを採用していることです。
ある行にUPDATE文を実行すると、既存の行の領域には「このデータはこの時点で書き換えられた」ということだけを書き換え、更新後内容の行を新たに追記して書き込みます(図3参照)。
このやり方をしていると、UPDATEを繰り返したり、INSERTとDELETEを繰り返したりすることで、物理的なデータ量がどんどん増えていってしまいます。そのため、VACUUMというコマンドが用意されています。テーブルにVACUUMを実行すると、既に上書きされて使われなくなった行の領域が整理されて、次の書き込みに利用できるようになります。
先に登場したautovacuumとは、この定期的なVACUUMをテーブルの更新度合いを見ながら自動的に行うものです(更新度合いを測るのにstats collectorが使われます)。
さて、では追記型アーキテクチャで何かいいことはあるのでしょうか。
それは、行ロックとトランザクション処理に大いに役立つという点です。追記型の場合、ある行といったときでも、UPDATEをする前、した後、というように複数バージョンが存在します。これにより、行の読み込みのロック獲得と行の書き込みのロックが競合しなくなります(相手をブロックしません)。
トランザクション処理で高い隔離レベルを取る場合、各トランザクションからは、開始時点の行の情報が見えていなくてはいけません。それでも複数バージョンの行があれば、複数トランザクションを同時に実行することができます。データベースをサービス中に何ら停止せずホットバックを取るときにこの技術が使われています。バックアップは取り始めた時点のスナップショットを保存できなければいけないからです。
また、トランザクションをロールバックするときには旧来のデータを再び有効にすればよいわけです。追記型ではないアーキテクチャの場合、行の書き換えを行うときには(Oracleデータベースの話ですが)、UNDOセグメントに変更前のデータを退避して、ロールバックが発生した場合はこれを元に戻すということを行います。
■まとめ
以上、PostgreSQLの概要とアーキテクチャについて解説してきましたが、いかがでしたか。アーキテクチャについては、当然のことながらここですべてを語ることはできませんので、基幹となる部分と特徴的な部分のみを取り上げました。
次回は「PostgreSQLの進化に迫る」と題して、ここ数年の機能追加や性能向上の軌跡を追っていきます。