ぱと隊長日誌

ブログ運用もエンジニアとしての生き方も模索中

pg_rman の「最新の状態までリカバリ」の処理内容

目的

pg_rman で復元ポイントを指定せずにリストアを実行し、PostgreSQLを起動すると、可能な限り障害直前の状態までリカバリされます。pg_rman のマニュアルで「リストア・オプション」の節に以下の説明があります。

  • --recovery-target-timeline TIMELINE
    • どの時系列でリカバリを行うかを指定します。省略時は現在のタイムライン($PGDATA/global/pg_control から取得)でリカバリを行います。
  • --recovery-target-time TIMESTAMP
    • リカバリ処理をどこまで行うかを示す時刻を指定します。省略時は可能な限り最新の状態までリカバリを行います。
pg_rman

pg_rman がどのようにして障害直前の状態にまでリカバリしているのか、リストア処理の概説と共に説明します。

環境

今回、参考にした pg_rman のソースコードは以下のリンクからダウンロードしました。
https://github.com/ossc-db/pg_rman/archive/v1.3.4.zip

挙動確認は以下の構成で行いました。
CentOS 7
PostgreSQL 9.6
pg_rman-1.3.4-pg96

説明

ベースバックアップからのリストアは以下の流れで行われます。

  1. オンラインWALとサーバログのバックアップ
  2. $PGDATA 配下の削除
  3. バックアップから $PGDATA 配下のリストア
  4. バックアップからアーカイブWALのリストア
  5. オンラインWALのリストア(先ほどバックアップしたオンラインWAL)
  6. recovery.conf の作成

このリストア処理が完了すると、ベースバックアップ+アーカイブWAL+オンラインWALによる完全リカバリを行える状況になります。見方を変えると、 --recovery-target-time を指定しなければ完全リカバリになります。任意の時点(例えばバックアップ時点)に戻したい場合は --recovery-target-time を指定して、不完全リカバリを実行する必要があります。

補足

バックアップされていないアーカイブWALのリストア時の扱い

バックアップされていないアーカイブWALに対し、リストア処理では何もしません。つまり、そのまま残ります。これは完全リカバリを行うために必要です。

リストア処理でのオンラインWALとサーバログのバックアップ

pg_rman のマニュアルには以下の記載があります。

pg_rmanがリストア中に未アーカイブの WAL をバックアップしつつ、その他のデータを削除します。 未アーカイブの WAL のバックアップは次に全体バックアップを取得するまで保持されるので、リカバリ結果が望んだものでなかった場合は再度リストアからやり直すことが可能です。

pg_rman

実際には未アーカイブのWAL(オンラインWAL)だけでなく、サーバログもバックアップされています。

コピーは以下のように行われます。

対象 コピー元 コピー先
オンラインWAL $PGDATA/pg_wal $BACKUP_PATH/backup/pg_xlog
サーバログ $SRVLOG_PATH $BACKUP_PATH/backup/srvlog

※各環境変数については pg_rman マニュアルの「パラメータの指定方法」(http://ossc-db.github.io/pg_rman/index-ja.html#waytopassoptions)を参照ください。

該当処理のソースコードを抜粋します。
restore.c (778)

/* backup online WAL */
snprintf(pg_wal_path, lengthof(pg_wal_path), "%s/pg_wal", pgdata);
snprintf(work_path, lengthof(work_path), "%s/%s/%s", backup_path,
	RESTORE_WORK_DIR, PG_XLOG_DIR);
dir_create_dir(work_path, DIR_PERMISSION);
dir_copy_files(pg_wal_path, work_path);

/* backup serverlog */
snprintf(work_path, lengthof(work_path), "%s/%s/%s", backup_path,
	RESTORE_WORK_DIR, SRVLOG_DIR);
dir_create_dir(work_path, DIR_PERMISSION);
dir_copy_files(srvlog_path, work_path);

pg_xlog と pg_wal

pg_rman は対応する PostgreSQL のバージョン毎にパッケージを用意しています。
pg_rman-1.3.4 のパッケージ間で PG_XLOG_DIR の定義に差異がありました。

ダウンロード元
Release 1.3.4 · ossc-db/pg_rman · GitHub

Source code (zip) - pg_rman.h

#define PG_XLOG_DIR "pg_wal"

pg_rman-1.3.4-pg96.tar.gz - pg_rman.h

#define PG_XLOG_DIR "pg_xlog"

この差異について、リリースノートの「変更点」に説明がありました。

PostgreSQL 10では'pg_xlog'が'pg_wal'に変更されることや、SQL関数名の中の'xlog'も'wal'に変更されることに対応しました。

Release 1.3.4 · ossc-db/pg_rman · GitHub

ベースとなる "Source code" は最新のバージョン(現時点で開発中の PostgreSQL 10)をターゲットとしているようです。

リストアとリカバリの違い

「リストア」と「リカバリ」という用語は pg_rman のマニュアルで共につかわれています。
一例を挙げます。

リストア完了後にpg_rmanが生成したrecovery.confの内容を確認し、必要に応じて修正を行います。 今回の場合は、最新の状態までリカバリするため特に修正せず、そのままPostgreSQLを起動してPITRを実施させます。

pg_rman

「リストア」と「リカバリ」の定義(使い分け)を調べたところ、Oracle Database を例に解説したエントリがありました。

Oracleデータベースのリストアとは、バックアップ媒体から元の場所もしくは新しい場所へデータベースを構成する物理ファイルをコピーして復元することを指します。
Oracleデータベースのリカバリとは、REDOログファイル(バックアップ取得~現在までのトランザクションの変更情報が保存されています)を使用してバックアップ後に作成されたデータベースへ変更情報を反映してデータを復旧することを指します。
参照元より抜粋)

Oracle:リカバリとリストアの違い | 覚え書き.com

この解説を踏まえて pg_rman のマニュアルを読み直したところ、この解説に沿った使い分けがなされているようでした。そこで、本エントリでもこの解説にそった使い分けを行いました。