PostgreSQLのポイントインタイムリカバリ(PITR)めも

PostgreSQLのポイントインタイムリカバリ(PITR)のしくみとオンラインバックアップ手順、リカバリ手順のめも。

バックアップ概要

バックアップの種類

サーバを起動したまま、pg_dumpコマンドでバックアップを取得します。DBをバックアップを取った時点のデータに戻すことができます。PostgreSQLのメジャーバージョンが異なるとき、この方法でデータの移行を行う必要があります。

  • オフラインバックアップ

サーバを停止後、dataディレクトリ以下をまるまるコピーします。DBをバックアップを取った時点のデータに戻すことができます。

  • オンラインバックアップ

バックアップツールを使用して、サーバを起動したままファイルをコピーします。また、アーカイブログも取得します。アーカイブログを適用することで、DBの状態を任意の時刻の時点に戻すことができます。
ここでは、このオンラインバックアップをおこなったあとに、バックアップからデータをレストアする方法についてメモっておきます。

PostgreSQLのしくみとPITRについて

PostgreSQL概要

かなり簡略化してありますが・・・。

  • 図の説明
postmaster DBMS本体。postgresリスナ
postgres postgresサーバプロセス。共有バッファ領域を使用して、sqlクエリの解析や実行を行います。
共有バッファ Postgresqlのデータをキャッシュし作業するメモリ領域。サーバプロセスは基本的に共有バッファを使用します。
データベースクラスタ Postgresqlデータファイル。postgresqlのdata配下のファイル群。共有バッファの内容を永続化します。
background writer バッファの内容をデータベースクラスタに反映する
wal writer WALログバッファの内容をWALログ(REDOファイルの役割にもなる)として書き出す。
archiver archive_commandの設定に応じて、使い終わったWALログの処理を行う(一般的にはアーカイブログディレクトリに移動する)
WALログ Write Ahead Log。耐障害性を高めるため、共有バッファ更新時に書き込むログ。ベースバックアップに適用することで、REDOログとして使用できる
アーカイブログ 使い終わったWALファイルそのもの。REDOログ
  • データ更新時の動作

postgresプロセスによって共有バッファのデータの更新処理を行う。
また平行して、Wal Writerによって、更新情報ログがWALログとして書き込まれる。
共有バッファのデータはbackground writerによってデータベースクラスタに反映され、checkpoint情報が更新される。
不要になったWALログはarchiverによってアーカイブログディレクトリに移動される。

オンラインバックアップ

オンラインバックアップはデータベースを起動したまま実行可能です。さらに、アーカイブログを保存することで、バックアップ後の更新結果も復元可能です。

  • オンラインバックアップ取得イメージ図


  • 前提条件

アーカイブログを取得する設定になっていること。
アーカイブコマンドが設定されていること。

archive_mode = on
archive_command = 'cp %p /tmp/archive/%f

可能なら、WALを記録するディレクトリ(data/pg_xlog)は、共有ディスクを用いるなどデータベースとは異なるデバイスに保存するようにしてください。
また、アーカイブログやベースバックアップも物理的に異なるディスクに保存するようにしてください。

  • バックアップ取得手順

(1)pg_start_backup()を実行

psql -c "SELECT pg_start_backup(now()::text)"

この時点で、バックアップラベル(data/backup_label)が作成されます。
また、pg_stop_backup()が実行されるまで、共有バッファの内容がデータベースクラスタに反映されなくなります。

(2)ベースバックアップの取得
tarやrsyncでデータベースクラスタ(dataディレクトリ配下のデータ)を丸ごとコピーします。このデータをベースバックアップと呼びます。
postgresqlの起動プロセスファイル(postmaster.pid)やWALログ(pg_xlog)は除外します。

rsync -av --delete --exclude=pg_xlog --exclude=postmaster.pid /usr/local/pgsql/data/* ~/tmp/backup/data

(3)pg_stop_backup()を実行

psql -c "SELECT pg_stop_backup()"

バックアップラベルにバックアップの終了情報を書き込んで、data/pg_xlog/????.backupにリネームします。(data/backup_labelが残っていると、DBが起動しなくなります。その場合backup_labelを削除すれば起動します。)
また、バックアップラベルには以下のような情報が書き込まれます。

# バックアップを開始した時のWALファイル
START WAL LOCATION 0/22ABD12 (file 000000010000000000000001)
# バックアップを終了した時のWALファイル
STOP WAL LOCATION: 0/22ABD12 (file 000000010000000000000001)
# チェックポイント
CHECKPOINT LOCATION: 0/22ABD12 
# バックアップ開始時刻
START TIME: 2011-04-01 00:00:00 JST
# バックアップラベル名
LABEL: 22ABD12 
# バックアップ終了時刻
STOP TIME: 2011-04-01 00:10:00 JST


以上で、オンラインバックアップは終了です。

ポイントインタイムリカバリ(PITR)

ポイントインタイムリカバリ(PITR)では、ベースバックアップにアーカイブログ(WALログ)を適用することで、任意の時点まで復元することが可能です。復元ポイントやリカバリの設定は、recovery.confに記述します。

(1)ベースバックアップの展開
dataディレクトリにバックアップを行ったベースバックアップを展開します。
設定ファイル(postgresql.conf)なども保存しているため、そのままコピーするだけで済みます。
また、移動前のdata/backup_labelが残っていると思いますので、削除してください。

(2)WALログの展開
アーカイブログになる前の最新のWALログをdata/pg_xlogにコピーします。指定する復元ポイントによっては、必要ないことも多いです。

(3)recovery.confの設定
recovery.confを作成します。ひな形が/usr/local/postgresql/share/recovery.conf.sampleにあるので、コピーして編集します。
設定する項目は、restore_commandとrecovery_target_timeです。
recovery_target_timeはバックアップラベルなどを参考に設定してください。
recovery_target_timeを指定しなかった場合、WALログを可能な限り適用する(可能な限りロールフォワードする)動作になります。

restore_command = 'cp /tmp/archive/%f "%p"'
recovery_target_time = '2011-04-01 00:00:00'

  startup processによってWALが適用されるイメージです。
  共有バッファの動作などはあっているかどうかちょっと自信がありません。

(4)postgresqlの起動
PosgreSQLを起動すると、リストアが実行されます。リストアに必要なWALログがdata/pg_xlogに見つからない場合、recovery.confのrestore_commandを実行してアーカイブログディレクトリからコピーされます。
リストアが終了すると、recovery.conはrecovery.doneにリネームされます。


以上で、PITRによる復元処理は終了ですが、手順が結構めんどくさいです。
Postgresql9.0のストリーミングレプリケーションは、PITRのリカバリ処理の仕組みによく似た実装になっています。ですので、このあたりの動作が参考になると思います。

最後に

pg_rmanというツールは、上記の処理を簡単に実行でき、バックアップファイルの管理も行えますので、結構おすすめです。