サイト内の現在位置

PostgreSQL

pg_rmanを用いたバックアップ・リカバリの実現方法

本ページでは、pg_rmanを用いたバックアップ・リカバリの実現方法について解説します。サンプルシナリオでは具体的な運用例についてもご紹介していますので、ぜひ最後までご覧ください。

pg_rmanのメリット

pg_rmanを使用すると、バックアップ取得と管理、およびリカバリに関する以下の各機能が使用できます。
・コマンド1つで、テーブルスペースまで含めてデータベース全体のバックアップを取得できます。
・コマンド1つで、バックアップからの完全リカバリを行うことができます。
・増分バックアップやバックアップの圧縮を行えるため、バックアップファイルをコンパクトにできます。
・バックアップは世代ごとに管理され、一覧表示することができます。
また、各作業において実施手順が容易になるため、作業時間の短縮と作業ミスの防止に役立ちます。
ストレージ・スナップショットをサポートし、バックアップ取得時間を短縮します。
※pg_rmanの機能概要についてはこちらをご覧ください。

pg_rmanの使い方

では、実際にpg_rmanによるバックアップ・リカバリの動作を確認してみましょう。
この章ではpg_rmanの初期設定や必須オプション、及びバックアップ・リカバリの手順について解説します。本ページでご紹介するバックアップ・リカバリ例の流れは以下の通りです。
① 10万件のテストデータを作成し、全体バックアップを取得する。
② レコードを1万件追加し(総レコード数11万件)、増分バックアップを取得する。
③ レコードをさらに1万件追加し(総レコード数12万件)、その後障害が発生したものとして最新状態にリカバリする(レコード12万件の状態に戻る)[図1]。
④ ③とは別に、時刻指定パラメータありでリカバリを実行する(レコード11万件の状態に戻る)[図2]。

図1 バックアップ・リカバリ(最新状態)のイメージ
図2 バックアップ・リカバリ(時刻指定)のイメージ
初期設定

pg_rmanは、取得したバックアップファイルや管理情報を「バックアップカタログ」という領域に保存します。このため、まず最初にバックアップカタログを初期化する必要があります。以下の項目をpostgresユーザーで実行します。

$ vi ~/.bash_profile                                                                    #バックアップカタログパス環境変数化
#下記2行を追記して上書き保存
BACKUP_PATH=[バックアップカタログパス]       
export BACKUP_PATH
$ source ~/.bash_profile
$ pg_rman init                                                                            #バックアップカタログの初期化

initコマンドを実行することにより、バックアップカタログパスにpg_rmanの各種管理情報ファイルが作成されます。

必須オプション

バックアップ・リカバリ実行時には、以下の3つが必須オプションとなります。

表1 バックアップ・リカバリ時の必須オプション

必須オプション

項目名

補足説明

-B PATH

バックアップカタログパス
(pg_rman管理)

バックアップ先 / リストア元 (絶対パス)

-D PATH

データベースクラスタパス
(PostgreSQL本体)

バックアップ元 / リストア先 (絶対パス)

-A PATH

WALアーカイブパス (PostgreSQL本体)

バックアップ元 / リストア先 (絶対パス)

(例)
#バックアップの実行
$ pg_rman backup -b full -B [バックアップカタログパス(pg_rman管理)] -D [データベースクラスタパス(PostgreSQL本体)] -A [WALアーカイブパス(PostgreSQL本体)]
#リカバリの実行
$ pg_rman restore -B [バックアップカタログパス(pg_rman管理)] -D [データベースクラスタパス(PostgreSQL本体)] -A [WALアーカイブパス(PostgreSQL本体)]

以降のバックアップ・リカバリコマンドの実行例では、3つの必須オプションを環境変数またはpg_rman.iniファイル内で設定することでオプションの指定を省略しています。実際のバックアップ・リカバリ実行時には必要に応じて前述の3つの必須オプションをパラメータ指定してください。

バックアップ

ここからは①~④の手順に沿って、バックアップ・リカバリの動作について解説します。10万件のテストデータを作成し全体バックアップを取得した後、レコードを1万件追加しその分の増分バックアップを取得します。

図3 全体バックアップ・増分バックアップのイメージ

①全体バックアップ
10万件のテストデータを作成し、DBクラスタ全体とWALアーカイブのバックアップを取得します。


1. テスト用のテーブル・レコードを作成します。

$ pgbench -i -s 1
postgres=# SELECT COUNT(*) FROM pgbench_accounts;
 count
--------
 100000
(1 行)

pgbenchはPostgreSQL本体付属のクライアントアプリケーションであり、PostgreSQL上でベンチマーク試験を行うことができます。上記のコマンドによって作成されるテーブルのうち、本ページではレコード数が10万件であるpgbench_accountsを使用します。

2. 全体バックアップを実行します。

$ pg_rman backup -b full

-bオプションでは、バックアップ対象を指定しています。全体バックアップですので、ここでは"full"を指定します。

表2 -bオプションの詳細
指定値

バックアップ対象

説明

詳細情報

full

全体バックアップ

全体バックアップと
アーカイブWALバックアップを取得

データベースクラスタ全体を
バックアップします。

incremental

増分バックアップ

増分バックアップと
アーカイブWALバックアップを取得

最新の検証済みバックアップの
開始以降に変更のあった
ファイル・ページのみを
バックアップします。(※)

archive

アーカイブWAL

データベースはバックアップせず、
WALバックアップのみを取得

アーカイブ WAL のみ
バックアップします。(※)

※実行するにはすでに取得および検証済の全体バックアップが存在する必要があります。

3. バックアップデータをリスト表示します。なお、この時点ではデータは未検証です。

$ pg_rman show detail                                                                                     

detail オプションは詳細表示を行います。全体バックアップですので、Modeは"FULL"となっています。また、Status "DONE"はデータが未検証であることを示しています。

4. バックアップデータを検証します。

$ pg_rman validate

5. バックアップデータをリスト表示します。データは検証済みです。

$ pg_rman show detail

データ検証済みのため、Statusは"OK"となっています。

②増分バックアップ
レコードを1万件追加し(総レコード数11万件)、DBクラスタ増分とWALアーカイブのバックアップを取得します。

1. テスト用のレコードを1万件追加します。

$ psql
postgres=# INSERT INTO pgbench_accounts SELECT GENERATE_SERIES(100001,110000),NULL,NULL,NULL;

2. 更新されたテーブルのレコード数を表示します。

postgres=# SELECT COUNT(*) FROM pgbench_accounts;
 count
--------
 110000
(1 行)

3. 増分バックアップを実行します。

$ pg_rman backup -b incremental

増分バックアップですので、-bオプションでincrementalを指定します。

4. バックアップデータをリスト表示します。なお、この時点ではデータは未検証です。

$ pg_rman show detail

5. バックアップデータを検証します。

$ pg_rman validate

6. バックアップデータをリスト表示します。データは検証済みです。

$ pg_rman show detail

リカバリ

今まで取得したバックアップを用いてリカバリを行います。本ページでは、次の二つの例をご紹介します。
・最新状態にリカバリ
・指定した時刻にリカバリ
テスト用のレコード数を1万件追加(総レコード数12万件)した後、障害が発生したものとして上記二つのリカバリを実行します。

③最新状態にリカバリ

図4 リカバリ(最新状態)のイメージ

1. テスト用のレコードを追加します。

$ psql
postgres=# INSERT INTO pgbench_accounts SELECT GENERATE_SERIES(110001,120000),NULL,NULL,NULL;

レコード数を11万件から12万件へ更新しています。

2. 更新されたテーブルのレコード数を表示します。

postgres=# SELECT COUNT(*) FROM pgbench_accounts;
 count
--------
 120000
(1 行)

3. 障害発生のシミュレートとして、DBを停止しデータを消失させます。

下記のコマンドを実行すると、DBクラスタ内の「postgresql.conf」ファイルが消失し、PostgreSQLを起動できなくなります。以降でリカバリされますが、 念のため削除前にDBクラスタをDBクラスタ外の場所にバックアップしておいてください。また、リストア時に一度DBクラスタが全消去される点にもご注意ください。

$ pg_ctl stop -m immediate                 #DB停止
$ rm ${PGDATA}/postgresql.conf         #データ消失

4. 障害発生の直前の状態にリカバリします。

$ pg_rman restore

オプションなしでrestoreコマンドを実行すると障害が発生した直前の状態にリカバリされます。

5. PostgreSQLを起動します。

$ pg_ctl start

6. リカバリ後のテーブル内のレコード数を表示 します。

$ psql
postgres=# SELECT COUNT(*) FROM pgbench_accounts;
 count
--------
 120000
(1 行)

レコード数12万件の状態にリカバリされていることが確認できます。

④指定した時刻にリカバリ

図5 リカバリ(時刻指定)のイメージ

1. テーブル内のレコード数を表示します。

$ psql
postgres=# SELECT COUNT(*) FROM pgbench_accounts;

 count
--------
 120000
(1 行)

2. 障害発生をシミュレートします。

下記のコマンドを実行すると、DBクラスタ内の「postgresql.conf」ファイルが消失し、PostgreSQLを起動できなくなります。以降でリカバリされますが、 念のため削除前にDBクラスタをDBクラスタ外の場所にバックアップしておいてください。また、リストア時に一度DBクラスタが全消去される点にもご注意ください。

$ pg_ctl stop -m immediate                    #DB停止
$ rm ${PGDATA}/postgresql.conf            #データ消失

3. 時刻を指定してリカバリを実行します。

$ pg_rman restore --recovery-target-time 'YYYY-MM-DD hh:mm:ss'
(例)
$ pg_rman restore --recovery-target-time '2022-11-25 11:52:49'

--recovery-target-timeオプション付きのrestoreコマンドを実行することで時刻を指定してリカバリできます。ただし、リカバリを行う前に、実行対象のPostgreSQLサーバを停止させる必要があります。

4. PostgreSQLを起動し、リストアされたテーブル内のレコード数を表示します。

$ pg_ctl start                                                                                   #PostgreSQL起動
$ psql
postgres=# SELECT COUNT(*) FROM pgbench_accounts;             #レコード数表示
 count
--------
 110000
(1 行)

レコード数11万件の状態にリカバリされていることが確認できます。

5. リカバリの完了処理を実行します。

$ psql
postgres=# SELECT pg_wal_replay_resume();

時刻指定でのリカバリの場合、4. の時点でDBは参照のみ可能 (更新不可)の状態になっています。そのため、リカバリ後のDBの状態を確認してから5. を実行し更新可能の状態にします。この処理は時刻指定でリカバリを行う場合のみ必要です。

サンプルシナリオ

ここでは、具体的な運用を想定したバックアップ・リカバリの例をご紹介します。実施内容は以下の通りです。

表3 サンプルシナリオ内容
項目

説明

バックアップ取得日時と種別

初回 

全体バックアップ

 月曜~土曜定時  

増分バックアップ

日曜定時

全体バックアップ 

世代管理

過去2世代分を保持

下記のコマンドを実行することで表3の要件を満たしたバックアップを取得できます。OS・DBともすべて「postgres」ユーザーで実行します。

#初回および日曜定時の全体バックアップ
$ pg_rman backup -b full -Z --keep-data-generations=2 > [ログファイル出力ファイル名フルパス].log 2>&1                                                                                                                                    #バックアップ
$ pg_rman validate                                                                                                              #検証
$ pg_rman purge                                                                                                                 #不要管理情報削除

#月曜~土曜定時の増分バックアップ
$ pg_rman backup -b incremental -Z > [ログファイル出力ファイル名フルパス].log 2>&1     #バックアップ
$ pg_rman validate                                                                                                                    #検証

-Zオプションで圧縮、--keep-data-generationsオプションに2を指定して過去2世代分を保持するよう指定しています。また、バックアップ実行ログを残したい場合には> [ログファイル出力ファイル名フルパス].log 2>&1の記述も追加します。
[注意]不要なWALアーカイブファイルの削除
pg_rmanでのバックアップ取得後、不要となったWALアーカイブファイルはそのままWALアーカイブディレクトリ内に残り続けます。時間経過とともにストレージ領域の圧迫が大きくなるため、適宜メンテナンス操作を行い不要なWALアーカイブファイルを削除してください。

PostgreSQL保守Advancedサポートサービスでは、PostgreSQL技術者による24時間365日体制のサポートのもと、PostgreSQLの技術的な問い合わせや、障害調査、pg_rmanを含む指定のOSSツールのサポートに対応します。詳細はこちらをご覧ください。

また、コミュニティによるサポートが終了したバージョンについても、新規問題が検出された場合には修正物件の提供を行っております。詳しくはこちらをご覧ください。