PowerGres Plus は、バックアップ戦略の一つである、オンラインバックアップにトランザクションログの二重化機能を用いることで、PostgreSQL では復旧不可能な障害が発生しても、簡単に障害発生直前まで復旧できるようになっています。
第 2 回では、オンラインバックアップにおける PowerGres Plus と PostgreSQL の差異について触れ、障害からの復旧手順を紹介します。
PowerGres Plus のバックアップ機能であるオンラインバックアップの特徴を、PostgreSQL と比較しながら解説します。
PowerGres Plus のベースとなっている PostgreSQL では、主に以下の 3 つのバックアップ戦略が採用されています。
バックアップ戦略 | サーバの状態 | 説明 | 復旧方法 | 復旧時点 |
---|---|---|---|---|
オフラインバックアップ | 停止 | OS 付属のコマンドを用いてデータベースクラスタを物理的にコピーする。 | コピーしたデータベースクラスタ再配置する。 | バックアップ取得時点。 |
論理バックアップ | 稼働 | PostgreSQL 付属の pg_dump、pg_dumall コマンドを用いてデータベースを SQL として保存する。 | SQL を読み込む。 | バックアップ取得時点。 |
オンラインバックアップ | 稼働 | データベースクラスタの物理コピーと、アーカイブログを保存する。 | コピーしたデータベースクラスタを再配置し、アーカイブログを適用していく。 | バックアップ取得時点から障害発生直前までの任意の時点。 |
運用するデータベースの規模や方針によりますが、保守性の観点から見た場合、これらのバックアップ戦略のうち、オンラインバックアップは最も信頼性と柔軟性が高いバックアップ手法となります。
また、この他にもレプリケーション機能やミドルウェアとの連携によるバックアップ手法も考えられます。
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 文としては正常な操作なので当然すべてのデータが削除されます。そういった場合にもオンラインバックアップを設定しておけば、スナップショットの取得後から現在までの任意の時点にリカバリすることが可能です。
社員を 1 名追加します。
INSERT INTO employee VALUES ( 2101027, '大沢 真利子', 'staff', '2010-08-19' ); SELECT * FROM employee;
大沢さんが追加されたことを確認しておきましょう。
ここで、DELETE 文に WHERE 句をつけないで、すべての行を消してしまうオペレーションミスを行います。
SELECT CURRENT_TIMESTAMP; DELETE FROM employee;
今度はここから、大沢さんが INSERT されたところまで復旧させてみましょう。
オペレーションミスなどのようにデータ自体が破損していない場合には、まだアーカイブログとして保存されていないトランザクションログを強制的にアーカイブ化することにより、より直近の状態まで復旧することができるようになります。
「ベースバックアップ」タブの「トランザクションログを強制的にアーカイブ化」ボタンをクリックします。
「オンラインバックアップ」をクリックし、「リカバリ」タブの「日付を指定してリカバリする」を選択します。先ほどタイムスタンプを取ったのは、「指定した日時の直前までリカバリする」で、時刻を入力したかったからです。DELETE する直前の時刻に設定し、「リカバリを実行」ボタンをクリックします。実際にはオペレーションミスを行ってしまったことに後から気付いて正確な時刻が不明な場合もあります。その場合にはリカバリを繰り返してどの時点まで戻すべきかを調節する必要があります。
続いては、ディスク障害からの復旧です。
ディスク障害によって、トランザクションログの書き込みに失敗した場合、データベースサーバはデータベースクラスタに障害が発生していると判断して、サービスを停止します。
このような場合であっても、オンラインバックアップ機能を用いてデータベースを復旧させることは可能です。ただし、PostgreSQL では、障害発生直前まで復旧できるとは限りません。障害発生直前のデータベースの変更情報を含んだトランザクションログが、壊れてしまう、もしくはアーカイブ化されていない場合もあるからです。ベースバックアップに差分情報を適用しようとしても、その差分情報がなければデータの復旧のしようがありません。
しかし、PowerGres Plus であれば、バックアップディレクトリに格納されている二重化されたトランザクションログを用いて、データベースを最新の状態まで復旧できます。
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;
ディスク障害発生を模すために、データベースクラスタが格納されている USB メモリを抜いてしまいます。
障害発生です。サービスが停止してしまいました。
障害が復旧したということで、USB メモリ内のデータを削除したうえで、挿し直します。
管理ツールを以下のコマンドで再起動し、リカバリを行います。
[postgres@node1 ~]$ powergres-mgr &
リカバリが完了すると、データベースサーバが停止した直前の状態までデータベースは復旧します。psql で testdb の employee テーブルを確認してみましょう。
\c testdb SET ROLE testuser; SELECT * FROM employee;
上記の通り、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)」ボタンをクリックします。
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 のデータ暗号化の性能検証結果もあわせて紹介いたします。