継続的アーカイブとポイントインタイムリカバリ（PITR）

PostgreSQL 9.0.0文書
前のページ | 巻戻し | 第 24章バックアップとリストア | 早送り | 次のページ

# 24.3. 継続的アーカイブとポイントインタイムリカバリ（PITR）

PostgreSQLは常に、クラスタのデータディレクトリ以下の`pg_xlog/`ディレクトリ内で先行書き込みログ（WAL）を管理しています。 このログはデータベースのデータファイルに行われた全ての変更を記録します。 このログは主にクラッシュ時の安全性を目的としています。 システムがクラッシュしたとしても、最後のチェックポイント以降に作成されたログ項目を"やり直し"することで、データベースを整合性を維持した状態にリストアすることができます。 しかし、この存在するログファイルを使用して、データベースのバックアップ用の第3の戦略が可能になりました。 ファイルシステムレベルのバックアップとWALファイルのバックアップを組み合わせるという戦略です。 復旧が必要ならば、ファイルシステムバックアップをリストアし、その後にバックアップされたWALファイルを再生することで、システムを最新の状態にできます。 管理者にとって、この方法はこれまで説明した方法よりかなり複雑になりますが、以下のような大きな利点が複数あります。

- 開始時点のファイルシステムバックアップは完全な整合状態である必要はありません。 そのバックアップ内の内部的な不整合はログのやり直しによって修正されます （これは、クラッシュからの復旧時に行われることと大きな違いはありません）。 ですので、ファイルシステムのスナップショット機能を必要としません。 単にtarなどのアーカイブツールが必要です。

- 再生の際にWALファイルの並びを数に制限なく連ねて組み合わせられますので、単にWALファイルのアーカイブを続けることで連続したバックアップを達成できます。 これは、頻繁に完全なバックアップを行うことが困難な、大規模なデータベースでは特に価値があります。

- WAL項目の再生を最後まで行わなければならないということはありません。 やり直しを任意の時点までで停止することができ、それにより、その時点までのデータベースの整合性を持ったスナップショットを得ることができます。 このような技術がポイントインタイムリカバリを補助するものであり、元となるベースバックアップの取得時点以降の任意の時点の状態にデータベースをリストアすることが可能になります。

- 連続的に一連のWALファイルを、同一のベースバックアップをロードしている別のマシンに配送することで、"ウォームスタンバイ"システムを保有することができます。 つまり、任意の時点でその2番目のマシンを、ほぼ現時点のデータベースの複製を持った状態で有効にすることができます。

> 注意: pg_dumpとpg_dumpallはファイルシステムレベルのバックアップを生成しませんので、継続的アーカイブ方式の一部として使うことはできません。 そのダンプは論理的なものであり、WALのやり直しで使うのに十分な情報を含んでいません。

通常のファイルシステムバックアップ技術の場合と同様、この方法は、一部ではなく、データベースクラスタ全体のリストア処理のみをサポートできます。 また、アーカイブ用に大量の格納領域を必要とします。 ベースバックアップはかさばる場合があり、また、高負荷なシステムではアーカイブしなければならないWALの流量をメガバイト単位で生成します。 しかし、これは、高信頼性が必要な、多くの状況でむしろ好まれるバックアップ手法です。

継続的アーカイブ（多くのデータベースベンダで"オンラインバックアップ"とも呼ばれます）を使用して復旧を成功させるためには、少なくともバックアップの開始時点まで遡る、連続した一連のアーカイブ済みWALファイルが必要です。 ですので、運用するためには、最初のベースバックアップを取得する前にWALファイルをアーカイブする手順を設定し試験しなければなりません。 したがって、まずWALファイルのアーカイブ機構について説明します。

## 24.3.1. WALアーカイブの設定

理論上、PostgreSQLシステムの稼動により、不定長のWAL記録の並びが生成されます。 システムは物理的にこの並びを、通常1つ16メガバイト（このセグメントサイズはPostgreSQLの構築時に変更可能です）の、WALセグメントファイルに分割します。 このセグメントファイルには、概念的なWALの並び内の位置を反映した、数字の名前が付与されます。 WALアーカイブを行わない場合、システムは通常数個のセグメントファイルを生成し、また、不要となったセグメントファイルの名前をより大きなセグメント番号に変更することでそれを"再回収"します。 直前のチェックポイントより前の内容を持つセグメントファイルは使用されないと仮定され、再回収されます。

WALデータをアーカイブする場合、完成したセグメントファイルのそれぞれの内容を取り出し、再利用のために回収される前にそのデータをどこかに保存することが必要です。 アプリケーションと利用できるハードウェアに依存しますが、数多くのの"データをどこかに保存する"方法があります。 例えば、NFSでマウントした他のマシンのディレクトリにセグメントファイルをコピーすること、あるいは、テープ装置に書き出すこと（元々のファイル名を識別する手段があることを確認してください）、それらを一度にまとめてCDに焼くこと、そのほか全く異なったなんらかの方法などです。 柔軟性をデータベース管理者に提供するために、PostgreSQLは、どのようにアーカイブがなされたかについて一切想定しないようになっています。 その代わりにPostgreSQLは、管理者に完全なセグメントファイルをどこか必要な場所にコピーするシェルコマンドを指定させます。 このコマンドは単純な`cp`でも構いませんし、また、複雑なシェルスクリプトを呼び出しても構いません。 全て管理者に任されています。

WALアーカイブを有効にするにはwal_level構成パラメータを`archive`（または`hot_standby`）に、archive_modeを`on`設定し、archive_command 構成パラメータで使用するシェルコマンドを指定します。 実行するには、これらの設定を `postgresql.conf` ファイルに常に置きます。 `archive_command` では、`%p`はアーカイブするファイルのパス名に置換され、`%f`はファイル名部分のみに置換されます。 （パス名は、サーバの現在の作業用ディレクトリ、つまり、クラスタのデータディレクトリから見て相対的なものです。） コマンド内に`%`文字自体を埋め込む必要があれば`%%`を使ってください。 最も簡単でよく使用されるコマンドは以下のようなものになります。

    archive_command = 'cp -i %p /mnt/server/archivedir/%f </dev/null'  # Unix
    archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows

これは、アーカイブ可能なWALセグメントを`/mnt/server/archivedir`ディレクトリにコピーします （これは一例です。推奨するものではなく、また、全てのプラットフォームで動作しない可能性があります）。`%p`および`%f`パラメータが置き換えられたあと、実行された実コマンドは以下のようになります。

    cp -i pg_xlog/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065 </dev/null

類似したコマンドがアーカイブされるそれぞれの新規ファイルに生成されます。

このアーカイブ用コマンドはPostgreSQLサーバを稼動させるユーザと同じ所有権で実行されます。 アーカイブされる一連のWALファイルには、実質、データベース内の全てが含まれていますので、アーカイブしたデータをのぞき見から確実に保護しなければならないでしょう。 例えば、グループや全員に読み込み権限を付与していないディレクトリにデータをアーカイブしてください。

アーカイブ用コマンドが成功した場合のみにゼロという終了ステータスを返すことが重要です。 PostgreSQLは、ゼロという結果に基づいて、そのファイルのアーカイブが成功したことを想定し、そのファイルを削除したり回収するかもしれません。 しかし、非ゼロのステータスは、PostgreSQLに対してファイルがアーカイブされなかったことを通知し、成功するまで定期的に再試行させます。

通常アーカイブ用コマンドは既存のアーカイブ済みファイルの上書きを行わないように設計されなければなりません。 これは、管理者のミス（例えば2つの異なるサーバの出力を同一のアーカイブ用ディレクトリに送信してしまうなど）といった場合からアーカイブ状況の整合性を保護するための安全策として重要です。 実際に既存のファイルを上書きしないこと、かつ、その場合に非ゼロのステータスを返すことを確認するために使用するアーカイブ用コマンドを試験することを勧めます。 多くのUnixプラットフォームでは`cp -i`とするとファイルを上書きする前に確認プロンプトを表示し、`< /dev/null`とすればプロンプト(と上書き)が失敗します。 プラットフォームがこの振舞いをサポートしていない場合は、アーカイブ済みファイルが存在するかどうかを検査するコマンドを追加しなければなりません。 例えば、以下のようなコマンドは、ほとんどのUnix系のプラットフォームで正しく動作します。

    archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'

アーカイブ設定を設計する時には、操作者の介入が必要であったり、アーカイブ場所の容量不足の理由でアーカイブ用コマンドが繰り返し失敗した時にどうなるかを考慮してください。 例えば、オートチェンジャ機能のないテープに書き出している場合に発生する可能性があります。 テープが一杯になった場合、テープを交換するまでアーカイブを行うことができなくなります。 こうした状況を相応の早さで解消できるよう、適切に操作者に対しエラーや要求を確実に連絡できるようにしなければなりません。 この状況が解消するまで、WALセグメントファイルは`pg_xlog/`ディレクトリ内に格納され続けます。（`pg_xlog/`を含むファイルシステムがいっぱいになると、PostgreSQLはパニック停止します。コミットされたトランザクションは失われませんが、データベースはいくらかの容量を開放するまでオフラインのままです。）

サーバのWALデータの生成に要する平均速度に追いついている限り、アーカイブ用コマンドの処理速度は重要ではありません。 アーカイブプロセスが多少遅れたとしても通常の操作は続けられます。 アーカイブ処理がかなり遅くれると、災害時に損失するデータの量が増加することになります。 また、これは`pg_xlog/`ディレクトリ内に多くのアーカイブ処理待ちのセグメントファイルが格納され、ディスク容量が不足する状況になる可能性があることを意味します。 アーカイブ処理が確実に意図通りに動作しているかを監視することを推奨します。

アーカイブ用コマンドを作成する時、アーカイブされるファイル名は最長64文字までで、ASCII文字と数字とドットのどんな組合せを使用しても構いません。 元の相対パス（`%p`）を保存する必要はありませんが、ファイル名（`%f`）を保存する必要はあります。

WALアーカイブによってPostgreSQLデータベースでなされた変更は全てリストアすることができますが、設定ファイルはSQL操作ではなく手作業で変更されますので、設定ファイル（`postgresql.conf`、`pg_hba.conf`、および`pg_ident.conf`）になされた変更までリストアしないことに注意してください。 通常のファイルシステムバックアップ手続きでバックアップされる場所に設定ファイルを保持したい場合があります。 設定ファイルの設置場所を変更するには項18.2を参照してください。

アーカイブコマンドは完全なWALセグメントに対してのみ呼び出されます。 このため、サーバが少ししかWAL流量がない（処理を行わないなぎの期間がある）場合、トランザクションの完了とアーカイブ格納領域への安全な記録との間に長期にわたる遅延があることになります。 古い未アーカイブのデータをどうするかについて制限を付けるために、archive_timeoutを設定して、強制的にサーバを新しいWALセグメントにある程度の間隔で切り替えるようにすることができます。 強制切り替えにより早期にアーカイブされたアーカイブ済みファイルは完全に完了したファイルと同じ大きさを持つことに注意してください。 そのため、非常に小さな`archive_timeout`を使用することはお勧めしません。 格納領域を膨張させてしまいます。 通常ならば分単位の`archive_timeout`設定が合理的です。

終わったばかりのトランザクションをできるだけ早くアーカイブさせたい場合、`pg_switch_xlog`を使用して手作業でセグメント切り替えを強制することができます。 この他のWAL管理に関連した関数を表9-56に列挙します。

`wal_level`が`minimal`の場合、項14.4.7に書かれているように、いくつかのSQLコマンドはWALロギングを回避するため最適化されます。 アーカイビングもしくストリーミングレプリケーションがこれら構文の１つを実行中に作動させられると、アーカイブ復旧のための十分な情報をWALが含まなくなります。（クラッシュ復旧は影響を受けません。） このことにより、`wal_level`はサーバの起動時のみ変更可能です。とは言っても、`archive_command`は構成ファイルを再読み込みすることで変更できます。一時的にアーカイビングを停止したい場合、１つの方法は`archive_command`を空文字列（`''`）に設定することです。このようにすると、動作する`archive_command`が再構築されるまでWALファイルは`pg_xlog/`に蓄積します。

## 24.3.2. ベースバックアップの作成

ベースバックアップの作成手順は比較的簡単です。

1. WALアーカイブが有効であり、正常に動作することを確認してください。

2. データベースにスーパーユーザとして接続し、以下のコマンドを発行してください。

       SELECT pg_start_backup('label');

   ここで`label`は、バックアップ操作を一意に識別するために使用する任意の文字列です （推奨方法は、格納先のバックアップダンプファイルの完全パスを使用することです）。 `pg_start_backup`は、開始時刻やラベル文字列などのバックアップ情報を持つ`backup_label`という名前のバックアップラベルファイルを、クラスタディレクトリ内に作成します。

   このコマンドを実行した時にクラスタ内のどのデータベースに接続したのかは注意する必要はありません。 この関数が返す結果は無視できますが、エラーが発生した場合は作業を進める前に対応してください。

   デフォルトで、`pg_start_backup`は終了までに長い時間がかかる場合があります。その理由はあるチェックポイントを実行し、そして、デフォルトでは設定したチェックポイント間隔の半分である、そのチェックポイントに必要なI/Oがかなりの時間にわたって広がるためです（設定パラメータについてはcheckpoint_completion_targetを参照してください）。通常これは、問い合わせ処理における影響を極小化するので望ましいことです。バックアップをなるべく早く行いたいのであれば、以下を使用します。

       SELECT pg_start_backup('label', true);

   これはチェックポイントをできる限り早く行うよう強制します。

3. (pg_dumpやpg_dumpallではなく)tarやcpioなどの使い慣れた任意のファイルシステムバックアップツールを使用して、バックアップを実行してください。 この作業時に、データベースの通常の操作を停止することは不要ですし、望ましい方法でもありません。

4. 再度、スーパーユーザとしてデータベースに接続し、以下のコマンドを発行してください。

       SELECT pg_stop_backup();

   これはバックアップモードを終了し、次のWALセグメントへの自動切換えを行います。 この切り替えの理由は、バックアップ期間中に書き出された最後のWALファイルがアーカイブできるよう準備することです。

5. バックアップ間で使用されたWALセグメントファイルがアーカイブされれば完了です。`pg_stop_backup`の結果で識別されるファイルは、バックアップファイル一式を完結させるのに必要となる最終セグメントです。`archive_mode`が有効であれば`pg_stop_backup` は最終セグメントがアーカイブされるまで戻りません。 すでに`archive_command`を設定していますので、これらのファイルのアーカイブ操作は自動的に発生します。ほとんどの場合、これは瞬時に行われます。しかし、バックアップの完了を確認できるよう、アーカイブシステムを監視し、遅延が無いことの確認をお勧めします。 アーカイブコマンドの失敗によりアーカイブ処理が遅れてしまったとしても、アーカイブが成功し、そしてバックアップが完了するまで再試行を繰り返すようになっています。 `pg_stop_backup`実行においての時間期限を設けたい場合、適切な`statement_timeout`の値を設定してください。

ファイルシステムの中には複写している途中でファイルが変更されると警告もしくはエラーを報告するものがあります。稼働しているデータベースのベースバックアップを取っている場合には、この情況は正常でエラーではありません。しかし、この種の警告と本当のエラーとを区別できるか確認が必要です。例えば、rsyncのバージョンによっては"消滅したソースファイル"に対して別の退出コードを返し、そしてこの退出コードをエラーではないと受け付けるするドライバスクリプトを記述することができます。同時にGNU tarのバージョンによっては、tarがそれを複写していた途中でファイルが切り詰められると、致命的エラーと識別できないエラーコードを返します。ありがたいことに、GNU tarのバージョン1.16もしくはそれ以降では、バックアップ中にファイルが変更されると`1`で、それ以外のエラーの時は`2`でプログラムから抜けます。

`pg_start_backup`から実際のバックアップの開始時刻までの経過時間やバックアップの終了時刻から`pg_stop_backup`までの経過時間は気にする必要はありません。 数分の遅れは何も問題ありません。 （しかし、通常`full_page_writes`を無効にしてサーバを稼動している場合、バックアップモードでは`full_page_writes`が実質的に強制されていますので、`pg_start_backup`から`pg_stop_backup`までの間の性能劣化に気が付くでしょう。） しかし、これらの操作を順番に、重なることなく実施することについて十分に注意する必要があります。 さもないと、バックアップを台無しにしてしまいます。

バックアップダンプに、データベースクラスタディレクトリ（例えば`/usr/local/pgsql/data`）以下にある全てのファイルが含まれていることを確認してください。 このディレクトリ以下に存在しないテーブル空間を使用している場合、注意して、同様にそれらを含めてください （そして、バックアップダンプがリンクとしてシンボリックリンクをアーカイブしていることを確認してください。 さもないとリストアはテーブル空間を壊してしまいます）。

しかし、クラスタの`pg_xlog/`サブディレクトリにあるファイルをバックアップダンプから省くことができます。 このちょっとした調整は、リストア処理中の失敗の危険性を低減できますので、行う価値があります。 `pg_xlog/`がクラスタディレクトリ外のどこかを指し示すシンボリックリンクの場合は調整が簡単です。 これは性能上の理由でよく使用される設定です。

このバックアップを使用したいと思ったら、ファイルシステムバックアップの実行期間とそれ以降に生成されたすべてのWALセグメントファイルをまず取っておかなければなりません。 これを手伝うために、`pg_stop_backup`関数はバックアップ履歴ファイルを生成し、WALアーカイブ領域に保存します。 このファイルの名前は、ファイルシステムバックアップに必要な最初のWALセグメントファイルにちなんで付けられます。 例えば、最初のWALファイルが`0000000100001234000055CD`の場合、バックアップ履歴ファイルは`0000000100001234000055CD.007C9330.backup`といった名前になります。 （このファイル名の２番目の番号はWALファイル内の正確な位置を示し、これは通常無視できます。） バックアップの期間（バックアップ履歴ファイルで指定されたように）に使用された、ファイルシステムバックアップとWALセグメントファイルを安全にアーカイブした後、数値的に小さい名前を持つWALセグメントは、ファイルシステムバックアップの回復にもう必要がないので、削除できます。 とは言っても、データが回復できることを完全に保証するため、いくつかのバックアップセットの保存を検討すべきでしょう。

バックアップ履歴ファイルは小さなテキストファイルです。それには`pg_start_backup`に与えたラベル文字列と、バックアップ開始と終了の時刻とWALセグメントが入っています。関連付けられたダンプファイルを特定するためラベルを使用するのであれば、どのダンプファイルをリストアすべきかを知るにはアーカイブされた履歴ファイルで充分です。

最後のベースバックアップまで遡ることができる全てのアーカイブ済みWALファイルを保持する必要がありますので、ベースバックアップの実行間隔は通常、アーカイブ済みWALファイルを格納する領域をどれだけ拡張したいかによって決定されます。 また、復旧処理に費すことができる時間がどの位許されるかについても考慮しなければなりません。 復旧が必要になった時に、システムはこれらのセグメントを全てやり直しする必要がありますが、最後のベースバックアップからの経過時間が長ければその分やり直しに時間がかかります。

また、`pg_start_backup`関数がデータベースクラスタディレクトリ内に`backup_label`という名前のファイルを作成することに注意してください。 これは、`pg_stop_backup`によって削除されます。 当然ながら、このファイルはバックアップダンプファイルの一部としてアーカイブされます。 バックアップラベルファイルには、`pg_start_backup`に付与したラベル文字列と`pg_start_backup`が実行された時刻、最初のWALファイルの名前が含まれます。 したがって、当惑した時にバックアップダンプファイルの中身を検索し、そのダンプファイルがどのバックアップセッションに由来したものかを確認することができます。

サーバが停止している時にバックアップダンプを作成することも可能です。 この場合、わかりきったことですが、`pg_start_backup`や`pg_stop_backup`を使用することができません。 そのため、どのバックアップダンプが、どのWALファイルと関連し、どこまで戻せばよいかを独自の方法で残さなければなりません。 通常は、上述の継続的アーカイブ手順に従う方をお勧めします。

## 24.3.3. 継続的アーカイブによるバックアップを使用した復旧

さて、最悪の事態が発生し、バックアップから復旧する必要が出てきたものとします。 以下にその手順を説明します。

1. もし稼動しているのであればサーバを停止してください。

2. もし容量があるのであれば、後で必要になる場合に備えてクラスタデータディレクトリ全体とテーブル空間を全て一時的な場所にコピーしてください。 この予防措置は、既存のデータベースを2つ分保持できるだけの空き領域を必要とします。 十分な領域がない場合でも、少なくともクラスタの`pg_xlog`サブディレクトリの内容は保存すべきです。 ここには、システムが停止する前にアーカイブされなかったログファイルが含まれているかも知れないからです。

3. クラスタデータディレクトリ以下、および、使用中のテーブル空間の最上位ディレクトリ以下にある既存の全てのファイルとサブディレクトリを削除してください。

4. ファイルシステムバックアップからデータベースファイルをリストアします。ファイルが正しい所有権（`root`ではなくデータベースシステムユーザです！）でリストアされていることを確認してください。テーブル空間を使用している場合は、`pg_tblspc/`内のシンボリックリンクが正しくリストアされていることを検証する必要があります。

5. `pg_xlog/`内にあるファイルをすべて削除してください。 これらはファイルシステムバックアップから生成されたものであり、おそらく現在のものより古く使用できないものです。 `pg_xlog/`をまったくアーカイブしていなければ、適切な権限で再作成してください。以前シンボリックリンクとして設定していたのであれば、そのように確実に再構築するように注意してください。

6. 手順2で退避させた未アーカイブのWALセグメントファイルがあるのであれば、`pg_xlog/`にコピーしてください。 （問題が発生し、初めからやり直さなければならない場合に未変更のファイルが残るように、移動させるのではなくコピーすることが最善です。）

7. 復旧コマンドファイル`recovery.conf`（第26章を参照）をクラスタデータディレクトリに作成してください。 また、一時的に`pg_hba.conf`を編集し、復旧の成功を確認できるまで一般ユーザが接続できないようにする必要があるかもしれません。

8. サーバを起動してください。 サーバは復旧モードに入り、必要なアーカイブ済みWALファイル群の読み込みを行います。 外部的なエラーにより復旧が中断したら、サーバを単に再起動させて、復旧処理を継続してください。 復旧処理が完了したら、（誤って後で復旧モードに再度入らないように）postmasterは`recovery.conf`の名前を`recovery.done`に変更します。 その後通常のデータベース操作を開始します。

9. データベースの内容を検査し、希望する状態まで復旧できていることを確認してください。 復旧できなかった場合は手順1に戻ってください。 全て問題なければ、ユーザが接続できるように`pg_hba.conf`を正常状態に戻してください。

ここで重要となるのは、復旧設定ファイルを設定することです。 このファイルで、どのように復旧させたいのかやどこまで復旧させたいかを記述します。 `recovery.conf.sample`（通常はインストレーションの`share/`ディレクトリに格納されています）を手本として使用することができます。 `recovery.conf`で絶対に指定しなければならないことは、アーカイブ済みWALファイルセグメントをどのように戻すかをPostgreSQLに通知する`restore_command`です。 `archive_command`同様、これはシェルコマンド文字列です。 ここには、対象のログファイルの名前で置換される`%f`やログファイルのコピー先を示すパスで置換される`%p`を含めることができます。 （パス名は現在の作業用ディレクトリ、つまり、クラスタのデータディレクトリから見た相対パスです。） コマンド内に`%`文字自体を埋め込む必要があれば`%%`と記載してください。 最も簡単でよく使われるコマンドは以下のようなものです。

    restore_command = 'cp /mnt/server/archivedir/%f %p'

これは事前にアーカイブされたWALセグメントを`/mnt/server/archivedir`ディレクトリからコピーします。 当然ながら、もっと複雑なもの使用することができます。 例えば、操作者に適切なテープをマウントさせることを要求するようなシェルスクリプトでさえ可能です。

このコマンドが失敗した時に非ゼロの終了ステータスを返すことが重要です。 このコマンドは、アーカイブに存在しないファイル要求するかもしれませんが、その場合でも非ゼロを返さなければなりません。 これはエラー状態ではありません。 必要なファイルの全てがWALセグメントファイルではありません。 `.backup`、または`.history`が付いているファイルが要求されることを想定しなければなりません。 `.backup`、または`.history`が付いているファイルに対しての要求を期待することもあるでしょう。同時に、`%p`パスのファイル名部分は`%f`と異なることに注意してください。これらが相互に置き換え可能であるとは考えないでください。

アーカイブ場所で見つけられなかったWALセグメントは`pg_xlog/`から検索されます。 これにより、最近の未アーカイブのセグメントを使用することができます。 しかし、アーカイブ場所から利用できるセグメントは`pg_xlog/`内のファイルよりも優先的に使用されます。 システムはアーカイブ済みファイルから取り出す時に既存の`pg_xlog/`の内容を上書きしません。

通常は利用可能な全てのWALセグメントを使用して復旧処理が行われます。その結果、データベースを現時点まで（もしくは、利用可能なWALセグメントで得られる限り現在に近い時点まで）リストアします。従って、通常の復旧は"file not found"メッセージで終了します。エラーメッセージの正確な文言は`restore_command`の選択によります。また、復旧の開始時点で`00000001.history`のようなファイル名のエラーメッセージが出ることがあります。これも単純な復旧作業では不具合を意味するものでなく正常です。論議については項24.3.4を参照してください。

もし以前のある時点まで復旧させたい場合（例えば、経験不足のデータベース管理者が主トランザクションテーブルを消去した直前）、`recovery.conf`に要求する停止時点を指定するだけです。停止時点は、"recovery target"として既知の停止時点で指定することも、日付と時刻で指定することも、完了した特定のトランザクションIDで指定することもできます。 本ドキュメントの執筆時点では使用するトランザクションIDの識別を補助するツールがありませんので、ほとんどの場合は日付と時刻による指定のみを使用することになるでしょう。

> 注意: 停止時点はバックアップの終了時刻、つまり、`pg_stop_backup`の最終時刻より後の時点でなければなりません。 バックアップを行っている最中のある時点までベースバックアップを使用して復旧させることはできません （こうした時点まで復旧させるには、その前のベースバックアップまで戻って、そこからロールフォワードしてください）。

復旧時にWALデータの破損がわかると、復旧はその時点で止まり、サーバは起動しません。 こうした場合、"復旧対象"に破損時点より前の時点を指定することで、復旧処理が正常に完了できるよう、復旧プロセスを初めからやり直すことができます。 システムクラッシュなど外的理由により復旧処理が失敗した場合やWALアーカイブがアクセスできなくなった場合、復旧処理を単に再起動させることができます。 この場合は失敗した時点とほぼ同じところから再開します。 復旧処理の再起動は、次のような通常操作時のチェックポイント処理とほぼ同様に動作します。 サーバは定期的にすべての状態をディスクに強制し、再度スキャンする必要がない処理済みのWALデータを示す`pg_control`ファイルを更新します。

## 24.3.4. 時系列

過去のある時点までデータベースを復旧できる機能は、SFタイムトラベルやパラレルユニバース（ブラックホールの先の対の宇宙）に類似した、多少の複雑性があります。 例えば、データベースの元の履歴で、火曜日の夕方5:15PMに重要なテーブルを削除し、水曜日のお昼まで手違いに気が付かなかったとします。 慌てずに、バックアップを取り出して、火曜日の夕方5:14PMの時点にリストアし、データベースを起動させます。 データベース世界のこの履歴では、そのテーブルを削除していません。 しかし、後になって、これは大した問題ではなかったことが分かり、元の履歴における水曜日に朝の何時かにまで戻したいと考えたと仮定しましょう。 データベースは既に起動していますので、元に戻したい時点に至るWALセグメントファイルの一部は上書きされていて、戻すことはできないかもしれません。 ですので、このことを避けるために、ポイントインタイムで復旧させた後に生成された一連のWAL記録と元のデータベースの履歴において生成されたWAL記録とを区別する必要があります。

こうした問題を扱うためにPostgreSQLには時系列という概念があります。 アーカイブ復旧が完了したときはいつでも、その復旧後に生成されたWAL記録を識別するための新しい時系列が生成されます。 時系列ID番号はWALセグメントファイル名の一部です。 ですので、新しい時系列はこれまでの時系列で生成されたWALデータを上書きしません。 実際、多くの異なる時系列をアーカイブすることができます。 不要な機能と考えるかもしれませんが、命綱になることがしばしばあります。 どの時点まで復旧すればよいか確実でないといった状況を考えてみてください。 その時は、過去の履歴からの分岐点として最善の時点を見つけるために、試行錯誤して何度もポイントインタイムの復旧を行う必要があるでしょう。 時系列がないと、この手続きはすぐに管理不能な混乱を招いてしまいます。 時系列を使用して、以前捨てた時系列分岐における状態を含む、過去の任意の状態に復旧させることができます。

新しい時系列が生成される度に、PostgreSQLは、どの時系列がいつどこから分岐したかを示す"時系列履歴"ファイルを作成します。 この履歴ファイルは、複数の時系列を含むアーカイブ場所から復旧する時にシステムが正しいWALセグメントファイルを選択できるようにするために必要です。 したがって、履歴ファイルは、WALセグメントファイル同様にWALアーカイブ領域にアーカイブされます。 履歴ファイルは（巨大になるセグメントファイルとは異なり）単なる小さなテキストファイルですので、安価かつ適切に無期限で保管できます。 必要ならば、履歴ファイルにコメントを追加し、この特定の時系列がどのように、なぜ生成されたかについて独自の注釈を付与することができます。 特にこうしたコメントは、実験の結果いくつもの時系列のもつれがある場合に有用です。

復旧処理のデフォルトは、ベースバックアップが取得された時点の時系列と同一の時系列に沿った復旧です。 別の子時系列に沿って復旧させたい（つまり、復旧試行以降に生成されたある状態に戻りたい）場合は`recovery.conf`で対象の時系列IDを指定しなければなりません。 ベースバックアップより前に分岐した時系列に沿って復旧することはできません。

## 24.3.5. ヒントと例

継続的アーカイブを構成するいくつかのヒントを以下にあげます。

### 24.3.5.1. スタンドアローンホットバックアップ

スタンドアローンホットバックアップを形成するためPostgreSQLのバックアップ基盤を使用することができます。これらのバックアップはポイントインタイムリカバリに使用することはできないのですが、pg_dumpによるダンプよりバックアップとリストアが概してより速く行われます。（同時にpg_dumpのダンプよりより大きくなるので、場合によっては速度による利点が打ち消されるかもしれません。）

スタンドアローンホットバックアップを準備するには、`wal_level`を`archive`（または`hot_standby`）に、`archive_mode`を`on`に設定し、スイッチファイルが存在する場合のみアーカイブを行うように`archive_command`を設定します。例えば以下のようにします。

    archive_command = 'test ! -f /var/lib/pgsql/backup_in_progress || cp -i %p /var/lib/pgsql/archive/%f < /dev/null'

このコマンドは`/var/lib/pgsql/backup_in_progress`が存在する場合にアーカイブを行い、そうでなければ（PostgreSQLが無用のWALを再利用できるように）、戻りゼロのステータスを黙って返します。

この準備によって、バックアップは以下のようなスクリプトを使用して取得されます。

    touch /var/lib/pgsql/backup_in_progress
    psql -c "select pg_start_backup('hot_backup');"
    tar -cf /var/lib/pgsql/backup.tar /var/lib/pgsql/data/
    psql -c "select pg_stop_backup();"
    rm /var/lib/pgsql/backup_in_progress
    tar -rf /var/lib/pgsql/backup.tar /var/lib/pgsql/archive/

完全なWALファイルのアーカイブが行われるように、スイッチファイル、`/var/lib/pgsql/backup_in_progress`が最初に作成されます。 バックアップの後、スイッチファイルは削除されます。 その後、アーカイブされたWALファイルは、基幹バックアップとすべての必要なWALファイル共に同じtarファイルの一部になるよう、バックアップに追加されます。 バックアップスクリプトにエラー処理を加えておくことを思い出してください。

もしアーカイブストレージの容量が懸案事項であれば、pg_compresslog、 http://pglesslog.projects.postgresql.orgを不必要なfull_page_writesの削除とWALファイルからの追跡に使用してください。pg_compresslogの出力を更に圧縮するのにgzipを使用できます。

    archive_command = 'pg_compresslog %p - | gzip > /var/lib/pgsql/archive/%f'

その結果、復旧中にgunzipとpg_decompresslogの使用が必要になります。

    restore_command = 'gunzip < /mnt/server/archivedir/%f | pg_decompresslog - %p'

### 24.3.5.2. `archive_command`スクリプト

`postgresql.conf`の記入事項が以下のように簡素となるため、多くの人が`archive_command`の定義にスクリプトの使用を選択します。

    archive_command = 'local_backup_script.sh'

アーカイブ処理手順において単一ではなくそれ以上の数のコマンドを使用したい場合はいつでも、別のスクリプトファイルの使用が推奨されます。そうするとスクリプト内で全ての複雑性が管理されます。スクリプトはbashまたはperlのようなよくあるスクリプト言語で記載できます。スクリプトによって`stderr`に書き出される全てのメッセージはデータベースサーバログに現れるので、失敗に終わった場合、複雑な構成を容易に診断できるようになります。

スクリプト内で解決される要件の例として以下があります。

- セキュアなオフサイトデータストレージへのデータのコピー

- 一回に全てではなく３時間毎に転送されるようにWALファイルのバッチ

- その他のバックアップとリカバリーソフトウェアとのインターフェイス

- エラー報告を行う監視ソフトとのインターフェイス

## 24.3.6. 警告

本ドキュメント作成時点では、継続的アーカイブ技術にいくつかの制限があります。 将来のリリースでは修正されるはずです。

- ハッシュインデックスに対する操作は現在WALログに残りません。したがって、再生してもこれらのインデックスは更新されません。 これは、新しい挿入はインデックスにより無視され、更新された行は見かけ上消え、削除された行はポインタを保持し続けるということです。 すなわち、ハッシュインデックス付きのテーブルを変更すると、スタンバイサーバでは不正確な問い合わせ結果が得られます。 復旧処理が終わった後に手作業でそうしたインデックスそれぞれに対してREINDEXを行うことが推奨されます。

- もしもベースバックアップが行われている時、CREATE DATABASEコマンドが実行され、ベースバックアップが処理を実行している期間に`CREATE DATABASE`がコピーしているtemplateデータベースが変更されると、復旧処理はこれらの変更を作成されたデータベースにも同時に伝播させることは確実です。 もちろん、これは望まれる事ではありません。 この危険を回避するには、ベースバックアップ期間中にはすべてのtemplateデータベースを変更しないことが一番です。

- CREATE TABLESPACEコマンドはリテラルの絶対パス付でWALにログが記録され、したがって、同じ絶対パスでのテーブル空間作成の時に再生されます。 これは、もしログが異なったマシン上で再生される場合には好ましくありません。 ログ再生がたとえ同一のマシンであっても、新規のデータディレクトリであれば危険です。 なぜなら、再生は元のテーブル空間の内容を上書きし続けるからです。 この種の潜在的な振舞いを防ぐためには、テーブル空間を作成もしくは削除後に新規ベースバックアップを行うのが最良の手段です。

また、デフォルトのWALフォーマットは数多くのディスクページのスナップショットを含んでいるため、かなりかさばるものになってしまっていることに触れておくべきでしょう。 これらのページスナップショットは、クラッシュから回復のために設計されています。 それというのも、回復処理の際には不完全に書き込まれているディスクページを修復しなければならないことがあるからです。 システムのハードウェアやソフトウェアによっては、不完全なディスクページの書き込みが起きてしまう危険性は無視してもよい程微小です。 この場合full_page_writesパラメータを設定してページスナップショットを無効にすることで、アーカイブされたログの総容量を大幅に縮小できます （実際に設定を行う前に、第29章の注意事項と警告を読んでください）。 ページスナップショットを無効にしても PITR処理の際にログが使用できなくなることはありません。 将来の課題は、`full_page_writes`がたとえオンになっている場合であっても不要なページを取り除き、アーカイブ済みWALデータの圧縮を行うことでしょう。 差し当たり管理者は、可能な限りチェックポイント間隔パラメータを大きくすることによって、WALに含まれるページスナップショットの数を削減することができます。

前のページ | ホーム | 次のページ
ファイルシステムレベルのバックアップ | 上に戻る | リリース間の移行