pg_rmanによるPostgreSQLの簡単バックアップ＆リカバリ

さて、前回の続きです。

前回はPostgreSQLのバックアップ手法を紹介・比較しました。

前回述べなかったのですが、物理バックアップには大きな利点があります。それは、データベースのバックアップとWALファイルのバックアップを組み合わせることで、リカバリする時点を自由にコントロールできるという点です。

# リカバリの違い

論理バックアップは特定の時点のデータをSQLの形で抜き出してくる方法でした。そのため、論理バックアップからデータを復旧した場合、バックアップを取得した時点のデータの状態に戻ります。当たり前ですね。

一方、物理バックアップはデータベースの実体のファイル自体をバックアップするものでした。オンライン・バックアップを行った場合は、これだけだとバックアップ中の変更が把握できないので、バックアップ中に発生したWALファイルから変更情報を読みだして反映することで、バックアップが完了した時点のデータの状態にまでようやく戻すことができます。

実は、物理バックアップからデータをリカバリする際には、リカバリする時点を変更してあげることが可能です！

何故ならば、WALにはデータベースに対して行われたすべての変更情報が記録されているので、WALファイルから変更情報を読みだして反映する時に「どこまで反映させるか」を変えられるのです。

この機能を**ポイント・イン・タイム・リカバリ(PITR)**と呼びます。

PITRを使えば、究極的には、一度データベースのバックアップを取っておけば、あとはアーカイブWALをバックアップし続けるだけで、リカバリが可能になるわけです。（実際には、WALから変更を反映する処理がどんどん大変になるので、バックアップを取り直すのが現実的ですが）

# PITRの手順


1. データベースのバックアップを用意します。このバックアップのことをリカバリの基点となることから「ベース・バックアップ」と呼びます。
2. アーカイブしたWALファイルを用意します。データベースを戻したい時刻の変更まで含まれてる分だけ用意する必要があることに注意します。場合によっては、アーカイブされていない最新のWALファイルまで必要となります。
3. リカバリを行うための設定ファイルrecovery.confを作成し、ベースバックアップのディレクトリに配置します。
4. ベース・バックアップのディレクトリ上でPostgreSQLを起動します。

これで、PostgreSQLがrecovery.confを読んで、指定した時点までリカバリを行ってくれます。
素晴らしいですね。

# PITRのデメリット

PITRは必要な情報さえ与えれば、後はPostgreSQLを起動するだけです。

「何が問題なのでしょうか？」

それは、**必要な情報をきちんとそろえる**ことです。ここはPostgreSQLは面倒を見てくれないので、ユーザがなんとかして必要性を管理・チェックする必要があります。手順に慣れていないと、必要な情報を揃えるのにかなり神経をつかいます。

というか、PITR手順に慣れるほど実施しているという状況はあまり良いものではないと思います。。。

# pg_rmanを使おう

そこで、[pg_rman](https://github.com/ossc-db/pg_rman)の出番です。

* バックアップとリカバリがそれぞれ1コマンドで
* バックアップを取る際に、前回から変更があったファイルだけをバックアップすることが可能
* さらに、バックアップデータの圧縮機能を併用することでバックアップデータをコンパクトに
* 取得したバックアップの確認や、世代管理も実施

動作環境はLinuxのみです。一部ユーザがMac OSでも動かしているようです。残念ながらWindowsは動作保証していません。

動作確認をしているPostgreSQLのバージョンは8.4から9.4です。一応、9.5alpha2でも動作すること確認しています。

## pg_rmanのインストール

RHEL or CentOSならRPMを公開しているので、それを使ってください。

https://github.com/ossc-db/pg_rman/releases/tag/v1.3.0

対象とするPostgreSQLのバージョンとOSに合わせたRPMをインストールする必要があります。

```
# rpm -ivh pg_rman-1.3.0-1.pg94.rhel7.x86_64.rpm
```

それ以外の環境の方はソースコードからインストールしてください。
ソースコードからビルドする際に、以下のパッケージが必要です。

* postgresql-libs, postgresql-devel
* pam-devel(libpam-dev)
* readline-devel(libedit-dev)
* zlib-devel

ソースコードの方もPostgreSQLのバージョンによってtar ballが分かれているので注意してください。

```
$ tar zxf pg_rman-1.3.0-pg94.tar.gz
$ cd pg_rman-1.3.0-pg94
$ make
# make install
```

## pg_rmanの初期化

バックアップを取得するPostgreSQLのディレクトリや、バックアップの格納先（バックアップカタログパスと呼びます）、アーカイブWALの格納パスを指定して`pg_rman init`コマンドを実行します。

```
$ pg_rman init -B <バックアップカタログパス> -D <PostgreSQLのデータベースクラスタパス> -A <アーカイブWALファイルの格納パス>
```

バックアップカタログパスとPostgreSQLのパスは環境変数で指定しておくこともできます。

アーカイブWALファイルの格納先は明示的に指定しなくても大丈夫です。pg_rmanがinit時にPostgreSQLの設定ファイルを読んで、`archive_command`に書かれたパスを抽出します。

```
$ echo $PGDATA
/home/postgres/pg_data/9.4
$ echo $BACKUP_PATH
/home/postgres/pg_data/backup
$ pg_rman init
INFO: ARCLOG_PATH is set to '/home/postgres/pg_data/archivelog'
INFO: SRVLOG_PATH is set to '/home/postgres/pg_data/9.4/pg_log'
```

## pg_rmanによるバックアップ取得

1コマンドです。

```
$ pg_rman backup --backup-mode=full --compress-data --progress
INFO: copying database files
Processed 1036 of 1036 files, skipped 0
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived
INFO: copying archived WAL files
Processed 3 of 3 files, skipped 0
INFO: backup complete
HINT: Please execute 'pg_rman validate' to verify the files are correctly copied.
```

バックアップのモードなどがオプションで指定できます。
個人的におすすめなのは、バックアップ取得中の進捗を出すようにする`progress`オプションです。

## バックアップデータの検証

バックアップ時のメッセージにも出ていますが、取得したバックアップをリカバリに使うためには`pg_rman validate`コマンドで問題なくデータが取得できているかチェックしておく必要があります。

```
$ pg_rman validate
INFO: validate: "2015-08-28 22:46:00" backup and archive log files by CRC
INFO: backup "2015-08-28 22:46:00" is valid
```

## 取得したバックアップの確認

`pg_rman show`コマンドで確認できます。

```
$ pg_rman show
==========================================================
 StartTime           Mode  Duration    Size   TLI  Status
==========================================================
2015-08-28 22:46:00  FULL        0m  3302kB     1  OK
2015-08-28 22:45:43  ARCH        0m    26kB     1  OK
2015-08-28 22:45:30  INCR        0m    96kB     1  OK
2015-08-28 22:39:44  FULL        0m  5176kB     1  OK
```

## pg_rmanによるリストア

動作しているPostgreSQLがあれば停止したうえで、`pg_rman restore`コマンドを実施します
このとき、どこまでリカバリで戻したいかを`recovery-target-time`オプションなどで指定することができます。何も指定しないと、できるだけ最新の状態にまで戻す設定になります。

```
$ pg_ctl stop -m immediate
$ pg_rman restore --recovery-target-time "2015-08-28 22:44:00"
INFO: the recovery target timeline ID is not given
INFO: use timeline ID of current database culster as recovery target: 1
INFO: calculating timeline branches to be used to recovery target point
INFO: searching latest full backup which can be used as restore start point
INFO: found the full backup can be used as base in recovery: "2015-08-28 22:39:44"
INFO: copying online WAL files and server log files
INFO: clearing restore destination
INFO: validate: "2015-08-28 22:39:44" backup and archive log files by SIZE
INFO: backup "2015-08-28 22:39:44" is valid
INFO: restoring database files from the full mode backup "2015-08-28 22:39:44"
INFO: searching incremental backup to be restored
INFO: searching backup which contained archived WAL files to be restored
INFO: backup "2015-08-28 22:39:44" is valid
INFO: restoring WAL files from backup "2015-08-28 22:39:44"
INFO: backup "2015-08-28 22:45:30" is valid
INFO: restoring WAL files from backup "2015-08-28 22:45:30"
INFO: validate: "2015-08-28 22:45:43" archive log files by SIZE
INFO: backup "2015-08-28 22:45:43" is valid
INFO: restoring WAL files from backup "2015-08-28 22:45:43"
INFO: backup "2015-08-28 22:46:00" is valid
INFO: restoring WAL files from backup "2015-08-28 22:46:00"
INFO: restoring online WAL files and server log files
INFO: generating recovery.conf
```

PIRTのための設定ファイルであるrecovery.confはpg_rmanが自動生成してくれています。

```
$ cat pg_data/9.4/recovery.conf
# recovery.conf generated by pg_rman 1.3.0
restore_command = 'cp /home/postgres/pg_data/archivelog/%f %p'
recovery_target_time = '2015-08-28 22:44:00'
recovery_target_timeline = '1'
```

後は、PostgreSQLを起動してPITRをさせるだけです。

```
$ pg_ctl start
```

どうでしょう。
自分でバックアップデータやアーカイブWALを管理して、データを戻してrecovery.confを書いて・・・としなくても、pg_rman でサクッとPITRの準備ができます。

より詳細なオプションや機能については、ドキュメントを参照してください。
http://ossc-db.github.io/pg_rman/index-ja.html