お問い合わせ
03-5979-2701
PowerGres
PowerGres V9.1 体験記 戻る

第 2 回 オンラインバックアップとリカバリをやってみよう

対象バージョン: PowerGres Plus V9.1
本文では CentOS 5 (64 ビット版) において PowerGres Plus V9.1(Linux 版)を使用して解説しています。

PowerGres Plus は、バックアップ戦略の一つである、オンラインバックアップにトランザクションログの二重化機能を用いることで、PostgreSQL では復旧不可能な障害が発生しても、簡単に障害発生直前まで復旧できるようになっています。

第 2 回では、オンラインバックアップにおける PowerGres Plus と PostgreSQL の差異について触れ、障害からの復旧手順を紹介します。

  1. PowerGres Plus のオンラインバックアップ
    1. PostgreSQL の 3 つのバックアップ戦略
    2. PostgreSQL のオンラインバックアップとその問題点
    3. 二重化されたトランザクションログを用いたオンラインバックアップ
  2. オンラインバックアップの設定
    1. トランザクションログの二重化とアーカイブログの有効化
    2. ベースバックアップの取得
  3. 障害対応
    1. オペレーションミスでデータを削除してしまった
    2. トランザクションログの書き込みに失敗した
    3. 二重化したトランザクションログの書き込みに失敗した
      1. データベースサーバの振る舞いについて
      2. 障害発生時にサーバを継続稼働させる
      3. 障害発生時にサーバを停止する
  4. 次回予告

PowerGres Plus のオンラインバックアップ

PowerGres Plus のバックアップ機能であるオンラインバックアップの特徴を、PostgreSQL と比較しながら解説します。

PostgreSQL の 3 つのバックアップ戦略

PowerGres Plus のベースとなっている PostgreSQL では、主に以下の 3 つのバックアップ戦略が採用されています。

バックアップ戦略 サーバの状態 説明 復旧方法 復旧時点
オフラインバックアップ 停止 OS 付属のコマンドを用いてデータベースクラスタを物理的にコピーする。 コピーしたデータベースクラスタ再配置する。 バックアップ取得時点。
論理バックアップ 稼働 PostgreSQL 付属の pg_dump、pg_dumall コマンドを用いてデータベースを SQL として保存する。 SQL を読み込む。 バックアップ取得時点。
オンラインバックアップ 稼働 データベースクラスタの物理コピーと、アーカイブログを保存する。 コピーしたデータベースクラスタを再配置し、アーカイブログを適用していく。 バックアップ取得時点から障害発生直前までの任意の時点。

運用するデータベースの規模や方針によりますが、保守性の観点から見た場合、これらのバックアップ戦略のうち、オンラインバックアップは最も信頼性と柔軟性が高いバックアップ手法となります。

また、この他にもレプリケーション機能やミドルウェアとの連携によるバックアップ手法も考えられます。

PostgreSQL のオンラインバックアップとその問題点

オンラインバックアップ

PostgreSQL のオンラインバックアップは、ある時点のデータベースのスナップショットと、それ以降のデータの変更によって発生した差分を保存しておき、障害発生時にそれらを適用することによって、障害が発生する直前までデータベースを復旧できるようにします。データベースのスナップショットをベースバックアップと呼び、差分情報を含んでいるファイルをアーカイブログと呼びます。アーカイブログは、データベースのトランザクションログのコピーです。

データベースを障害直前の状態まで復旧するには、ベースバックアップ取得時点から障害発生時点までのトランザクションログとアーカイブログが必要です。したがって、アーカイブログの元となるトランザクションログが確実に出力されていることが重要です。

しかしながら、PostgreSQL はトランザクションログを一箇所にしか保存できず、トランザクションログを配置しているディスクが障害を起こすとデータベースの運用、最新状態までの復旧ができなくなってしまいます。

二重化されたトランザクションログを用いたオンラインバックアップ

オンラインバックアップ

そこで、PowerGres Plus ではトランザクションログと同一のファイルを出力する機能を追加し、データベース領域のディスク障害に対応しました。トランザクションログが格納されたディスクに障害が発生しても、二重化されたトランザクションを用いることで、データベースを最新の状態に復旧することが可能です。

バックアップディレクトリはデータベースクラスタと異なるディスクに配置しましょう

PowerGres Plus の二重化されたトランザクションログを利用する場合は、二重化されたトランザクションログが格納されるバックアップディレクトリをデータベースクラスタと異なるディスクに配置する必要があります。

ディレクトリ配置

トランザクションログが出力されるディスクと同一ディスクにバックアップディレクトリを配置してしまうと、トランザクションを二重化した意味がなくなってしまいます。

オンラインバックアップの設定

PowerGres Plus を使ってオンラインバックアップの設定を行っていきましょう。

第 1 回を参考に、データベースクラスタの作成を完了させ、サービスを開始してください。

ただし、今回はディスク障害からの復旧を行うことを目的としており、ディスク障害をシュミレートするために USB メモリを利用します。

はじめは、データベースクラスタを USB メモリ内に作成します。

トランザクションログの二重化とアーカイブログの有効化

PowerGres Plus では、バックアップディレクトリを指定した状態でデータベースクラスタの初期化を完了させると、トランザクションログの二重化およびトランザクションログのアーカイブ化を有効にする以下の設定が postgresql.conf に適用されます。

パラメータ 設定値 パラメータの説明
wal_level hot_standby トランザクションログに出力する情報量を指定します。
archive_mode on アーカイブモードの有効化。
archive_command '"/opt/powergresplus91/bin/pgx_xlogcopy.cmd" "%p" "/var/lib/pgsql/backups/archived_xlog/%f"' トランザクションログをアーカイブする際のコマンド。
backup_destination '/var/lib/pgsql/backups' バックアップディレクトリを指定します。

ベースバックアップの取得

オンラインバックアップで使用するベースバックアップを取得します。

「オンラインバックアップ」をクリックし、「ベースバックアップ」タブの「ベースバックアップを作成」ボタンをクリックします。

オンラインバックアップ画面

ベースバックアップが作成されると「作成済みベースバックアップ」欄に作成日時とベースバックアップのサイズが表示されます。

オンラインバックアップ画面

障害対応

それでは、3 種類の障害を発生させてデータを復旧してみましょう。

オペレーションミスでデータを削除してしまった

オペレーションミスで削除してしまったデータの復旧を例に、オンラインバックアップによる任意時点へのリカバリ手順について解説します。

例えば、WHERE 句を指定せずに誤って DELETE 文を実行してデータを削除してしまった場合、SQL 文としては正常な操作なので当然すべてのデータが削除されます。そういった場合にもオンラインバックアップを設定しておけば、スナップショットの取得後から現在までの任意の時点にリカバリすることが可能です。

まず、psql から testdb に接続して、employee テーブルを確認します。

\c testdb
SET ROLE testuser;
SELECT * FROM employee;
障害対応01

現在時刻を確認しておきます。

SELECT CURRENT_TIMESTAMP;
障害対応01

社員を 1 名追加します。

INSERT INTO employee VALUES (
2101027,
'大沢 真利子',
'staff',
'2010-08-19'
);
SELECT * FROM employee;

大沢さんが追加されたことを確認しておきましょう。

障害対応01

ここで、DELETE 文に WHERE 句をつけないで、すべての行を消してしまうオペレーションミスを行います。

SELECT CURRENT_TIMESTAMP;
DELETE FROM employee;
障害対応01

今度はここから、大沢さんが INSERT されたところまで復旧させてみましょう。

オペレーションミスなどのようにデータ自体が破損していない場合には、まだアーカイブログとして保存されていないトランザクションログを強制的にアーカイブ化することにより、より直近の状態まで復旧することができるようになります。

「ベースバックアップ」タブの「トランザクションログを強制的にアーカイブ化」ボタンをクリックします。

障害対応01

「オンラインバックアップ」をクリックし、「リカバリ」タブの「日付を指定してリカバリする」を選択します。先ほどタイムスタンプを取ったのは、「指定した日時の直前までリカバリする」で、時刻を入力したかったからです。DELETE する直前の時刻に設定し、「リカバリを実行」ボタンをクリックします。実際にはオペレーションミスを行ってしまったことに後から気付いて正確な時刻が不明な場合もあります。その場合にはリカバリを繰り返してどの時点まで戻すべきかを調節する必要があります。

障害対応01

その後 psql で testdb の employee テーブルの状態を確認してみましょう。DELETE 直前の INSERT 直後の状態であり、障害復旧できている事が確認できます。

\c testdb
SET ROLE testuser;
SELECT * FROM employee;
障害対応01

トランザクションログの書き込みに失敗した

続いては、ディスク障害からの復旧です。

ディスク障害によって、トランザクションログの書き込みに失敗した場合、データベースサーバはデータベースクラスタに障害が発生していると判断して、サービスを停止します。

このような場合であっても、オンラインバックアップ機能を用いてデータベースを復旧させることは可能です。ただし、PostgreSQL では、障害発生直前まで復旧できるとは限りません。障害発生直前のデータベースの変更情報を含んだトランザクションログが、壊れてしまう、もしくはアーカイブ化されていない場合もあるからです。ベースバックアップに差分情報を適用しようとしても、その差分情報がなければデータの復旧のしようがありません。

しかし、PowerGres Plus であれば、バックアップディレクトリに格納されている二重化されたトランザクションログを用いて、データベースを最新の状態まで復旧できます。

現在の状態を把握しておきましょう。先ほどの任意の時点に戻した状態になっています。

SELECT * FROM employee;
障害対応02

トランザクションログを強制的にアーカイブ化しておきます。

障害対応02

employee テーブルに削除、更新、挿入など変更操作を行います。

UPDATE employee
SET position = 'staff'
WHERE number = 1782822;
INSERT INTO employee VALUES (
2101028,
'PITR 最新状態次郎',
'chief', '2012-06-17'
);
DELETE FROM employee
WHERE number = 2081577;
SELECT * FROM employee;
障害対応02

ディスク障害発生を模すために、データベースクラスタが格納されている USB メモリを抜いてしまいます。

障害発生です。サービスが停止してしまいました。

障害対応02

障害が復旧したということで、USB メモリ内のデータを削除したうえで、挿し直します。

管理ツールを以下のコマンドで再起動し、リカバリを行います。

[postgres@node1 ~]$ powergres-mgr &

管理ツールを再起動すると、データベースクラスタを削除してしまったので postgresql.conf ファイルも無くなっています。「OK」ボタンをクリックします。

障害対応02

リカバリを行います。「オンラインバックアップ」の「リカバリ」のタブの「最新の状態までリカバリする」にチェックを入れ、「リカバリを実行」ボタンをクリックします。

障害対応02

リカバリが完了すると、データベースサーバが停止した直前の状態までデータベースは復旧します。psql で testdb の employee テーブルを確認してみましょう。

\c testdb
SET ROLE testuser;
SELECT * FROM employee;
障害対応02

上記の通り、PowerGres Plus ではトランザクションログが二重化されているので、まだアーカイブ化されていないトランザクションログが格納されているディスクに障害があったとしても、確実に最新の状態まで復旧することができます。

二重化したトランザクションログの書き込みに失敗した

二重化したトランザクションログが格納されているディスクに障害が発生した場合を想定します。再びセットアップを行いますが、今度はバックアップディレクトリを USB メモリ内に作成します。

データベースサーバの振る舞いについて

バックアップディレクトリが配置されているディスクが故障したり、空き容量が不足すると二重化されたトランザクションログの出力が失敗します。

二重化されたトランザクションログの出力に失敗したときのデータベースサーバの振る舞いを、PowerGres Plus 専用の設定パラメータである、exit_on_wal_multiplexing_error を用いて以下の通り設定できます。デフォルトの設定値は off です。

パラメータ名 設定値 データベースの振る舞い 主な用途
exit_on_wal_multiplexing_error off サービスは継続稼働する。 可用性を重視する。
on サービスが停止する。 データ保護を重視する。

いずれの場合においても、バックアップディレクトリを復旧すれば、問題は解決されます。

障害発生時にサーバを継続稼働させる

二重化されたトランザクションログが格納されているディスクに障害が発生した際に、データベースサーバを継続稼働させる場合の復旧手順を確認してみましょう。

二重化されたトランザクションログはバックアップディレクトリに格納されています。したがって、上記の障害が発生すると、アーカイブログの出力も失敗することになります。PowerGres Plus では、トランザクションログのアーカイブ化に失敗すると、そのトランザクションログは蓄積していき、バックアップディレクトリ側の障害が取り除かれると自動的にアーカイブ化され、不要となったタイミングで削除される設定にデフォルトではなっています。

はじめに、トランザクションログの確認しておきましょう。

[postgres@node01 ~]$ ls /var/lib/pgsql/data/pg_xlog
000000010000000000000016  000000010000000000000017  000000010000000000000018  000000010000000000000019  00000001000000000000001A  archive_status

バックアップディレクトリが配置されている USB メモリを抜いてしまいます。

続けて、データベースに多数の更新をかけるために、pgbench を実行します。

トランザクションログが出力されるように、pgbench のイニシャライズを行いましょう。

[postgres@node1 ~]$ pgbench -i -s 10
Password:
creating tables...
10000 tuples done.
20000 tuples done.
:
:
990000 tuples done.
1000000 tuples done.
set primary key...
NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "pgbench_branches_pkey" for table "pgbench_branches"
NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "pgbench_tellers_pkey" for table "pgbench_tellers"
NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "pgbench_accounts_pkey" for table "pgbench_accounts"
vacuum...done.

サーバの起動状態とトランザクションログの状態を確認します。

[postgres@node1 ~]$ pg_ctl status -D /var/lib/pgsql/data
pg_ctl: サーバが動作中です(PID: 8660)
/opt/powergresplus91/bin/postgres "-D" "/var/lib/pgsql/data" "-p" "5432"
[postgres@node ~]$ ls /var/lib/pgsql/data/pg_xlog
000000010000000000000017  00000001000000000000001A  00000001000000000000001D  000000010000000000000020  000000010000000000000023  000000010000000000000026
000000010000000000000018  00000001000000000000001B  00000001000000000000001E  000000010000000000000021  000000010000000000000024  000000010000000000000027
000000010000000000000019  00000001000000000000001C  00000001000000000000001F  000000010000000000000022  000000010000000000000025  archive_status

サーバは停止しておらず、トランザクションログも削除されることなく蓄積しています。

バックアップディレクトリ側の障害が復旧したことにします。USB メモリ内のデータを削除したうえで USB メモリを差し直します。

トランザクションログのアーカイブ化が実行され、累積していたトランザクションログがなくなっていることが確認できます。

[postgres@node01 ~]$ ls /media/disk/backups
000000010000000000000027  000000010000000000000029  00000001000000000000002B  00000001000000000000002D  archive_status
000000010000000000000028  00000001000000000000002A  00000001000000000000002C  00000001000000000000002E

障害発生時にサーバを停止する

障害が発生した際に、データベースサーバを停止させる場合の復旧手順を確認してみましょう。

exit_on_wal_multiplexing_error を変更します。

「設定」の「互換性 他」タブの「PowerGres Plus オプション」セクションの exit_on_wal_multiplexing_error を on に変更して、「適用(A)」ボタンをクリックします。

障害対応03

「サービス」の「サービスの再起動」ボタンをクリックします。

障害対応03

USB メモリを抜いて、障害を発生させます。

続けてトランザクションログが出力されるように、pgbench を実行します。

[postgres@node1 ~]$ pgbench -i -s 15
Password:
WARNING:  terminating connection because of crash of another server process
DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT:  In a moment you should be able to reconnect to the database and repeat your command.

サービスが停止しました。

[postgres@node1 ~]$ pg_ctl status -D /var/lib/pgsql/data
pg_ctl: サーバが動作していません

サービスが停止した後は、バックアップディレクトリ側の障害を復旧し、再びサービスを起動します。

次回予告

このように、PowerGres Plus ではトランザクションログの二重化機能により PostgreSQL では復旧不可能な障害が発生しても、簡単に障害発生直前まで復旧することが可能です。

次回は、PowerGres Plus によるデータ暗号化の設定方法をご紹介いたします。

PowerGres Plus のデータ暗号化は、クライアント側の処理を変更することなく、簡単にデータを暗号化できます。SQL 実行時のオーバーヘッドも ほとんどありません。

PowerGres Plus のデータ暗号化の性能検証結果もあわせて紹介いたします。