ログシッピングスタンバイサーバ

PostgreSQL 9.1.1文書
前のページ | 巻戻し | 第 25章高可用性、負荷分散およびレプリケーション | 早送り | 次のページ

# 25.2. ログシッピングスタンバイサーバ

継続的なアーカイブ処理を使用して、プライマリサーバが失敗した場合に操作を引き継ぐ準備がなされた、1つ以上のスタンバイサーバを持つ高可用性(HA)クラスタ構成を作成することができます。 この機能はウォームスタンバイまたはログシッピングとして広く知られています。

プライマリサーバとスタンバイサーバは、この機能を提供するために共同して稼動しますが、サーバとサーバはゆるく結合しています。 プライマリサーバは継続的アーカイブモードで動作し、各スタンバイサーバはプライマリからWALファイルを読み取る、継続的リカバリモードで動作します。 この機能を可能にするために、データベースのテーブル変更は不要です。 したがって、他のレプリケーションの解法に比べて、管理にかかるオーバーヘッドが減少します。 この構成はプライマリサーバの性能への影響も相対的に減少させます。

あるデータベースサーバから他へ直接WALレコードを移動することは通常、ログシッピングと説明されます。 PostgreSQLはファイルベースのログシッピングを実装します。 つまりWALレコードはある時点で1つのファイル(WALセグメント)として送信されることを意味します。 WALファイル(16MB)は隣り合うシステム、同じサイトの別システム、地球の裏側のシステムなど距離に関わらず、簡単かつ安価に送付することができます。 この技法に必要な帯域幅はプライマリサーバのトランザクションの頻度に応じて変動します。 レコードベースのログシッピングはより粒度を細かくしたもので、ネットワーク接続を介してWALの変更を増分的に流します（項25.2.5参照）。

ログシッピングが非同期であることに注意しなければなりません。 つまり、WALレコードはトランザクションがコミットした後に転送されます。 結果として、プライマリサーバが災害などの致命的な失敗をうけた場合、送信されていないトランザクションが失われますので、データを損失する空白期間があります。 ファイルベースのログシッピングにおけるデータ損失の空白期間量を`archive_timeout`パラメータを用いて制限することができます。 これは数秒程度まで小さく設定することができます。 しかし、低く設定するとファイル転送に必要な帯域幅が増大します。 ストリーミングレプリケーション（項25.2.5参照）により、データを損失する期間を非常に小さくすることができます。

リカバリ処理の性能は十分よく、一度実施されれば、スタンバイサーバが完全な状態から逸脱するのは一時的にしかすぎません。 結果としてこれは、高可用性を提供するウォームスタンバイ構成と呼ばれます。 保管されたベースバックアップからサーバをリストアし、ロールフォワードを行うことはおそらく長時間かかりますので、これは高可用性のための解法とはいえず、災害からのリカバリのための解法です。 スタンバイサーバは読み取り専用の問い合わせに使用することもできます。 この場合ホットスタンバイサーバと呼ばれます。 詳細については項25.5を参照してください。

## 25.2.1. 計画

プライマリサーバとスタンバイサーバを、少なくともデータベースサーバという見地でできる限り同じになるように作成することを通常勧めます。 具体的には、テーブル空間に関連するパス名はそのまま渡されますので、テーブル空間機能を使用する場合には、プライマリとスタンバイサーバの両方でテーブル空間用のマウントパスを同じにしておかなければなりません。 CREATE TABLESPACEをプライマリで実行する場合、そのコマンドを実行する前に必要な新しいマウントポイントをプライマリとすべてのスタンバイサーバで作成しなければならないことに注意してください。 ハードウェアをまったく同じにする必要はありませんが、経験上アプリケーションとシステムの運用期間に渡って2つの同じシステムを管理する方が、異なる2つのシステムを管理するよりも簡単です。 いずれにしてもハードウェアアーキテクチャは必ず同じでなければなりません。 例えば32ビットシステムから64ビットシステムへのシッピングは動作しません。

マイナーリリースの更新ではディスク書式を変更しないというのがPostgreSQLグローバル開発グループの方針ですので、プライマリサーバとスタンバイサーバとの間でマイナーリリースレベルの違いがあってもうまく動作するはずです。 しかし、この場合、公的なサポートは提供されません。 できる限りプライマリサーバとスタンバイサーバとで同じリリースレベルを使用してください。 新しいマイナーリリースに更新する場合、もっとも安全な方針はスタンバイサーバを先に更新することです。 新しいマイナーリリースは以前のマイナーリリースのWALファイルを読み込むことはできますが、逆はできないかもしれません。

## 25.2.2. スタンバイサーバの動作

スタンバイモードでは、サーバは継続的にマスタサーバから受け取ったWALを適用します。 スタンバイサーバはWALアーカイブ(restore_command参照)から、または直接TCP接続(ストリーミングレプリケーション)を介してマスタサーバから、WALを読み取ることができます。 またスタンバイサーバはスタンバイクラスタの`pg_xlog`ディレクトリにあるすべてのWALをリストアしようと試みます。 これはよくサーバの再起動後、スタンバイが再起動前にマスタから流れ込んだWALを再生する時に発生します。 しかしまたファイルを再生する任意の時点で、手作業で`pg_xlog`にコピーすることもできます。

起動時、スタンバイサーバは`restore_command`を呼び出して、アーカイブ場所にある利用可能なすべてのWALをリストアすることから始めます。 そこで利用可能なWALの終端に達し、`restore_command`が失敗すると、`pg_xlog`ディレクトリにある利用可能な任意のWALのリストアを試みます。 ストリーミングレプリケーションが設定されている場合、これに失敗すると、スタンバイはプライマリサーバへの接続を試み、アーカイブまたは`pg_xlog`内に存在した最終の有効レコードからWALのストリーミングを開始します。 ストリーミングレプリケーションが未設定時にこれに失敗する場合、または、接続が後で切断される場合、スタンバイは最初に戻り、アーカイブからのファイルのリストアを繰り返し行います。 このアーカイブ、`pg_xlog`、ストリーミングレプリケーションからという再試行の繰り返しはサーバが停止する、あるいはトリガファイルによるフェールオーバが発行されるまで続きます。

`pg_ctl promote`が実行された時またはトリガファイル(`trigger_file`)が存在する時、スタンバイモードは終了し、サーバは通常の動作に切り替わります。 フェールオーバの前に、アーカイブまたは`pg_xlog`内の即座に利用可能なWALをすべてリストアします。 しかし、マスタへの接続を行おうとはしません。

## 25.2.3. スタンバイサーバのためのマスタの準備

項24.3で説明したように、スタンバイからアクセス可能なアーカイブディレクトリに対してプライマリで継続的なアーカイブを設定してください。 このアーカイブ場所はマスタが停止した時であってもスタンバイからアクセス可能でなければなりません。 つまり、マスタサーバ上ではなく、スタンバイサーバ自身上に存在するか、または他の高信頼性サーバ上に存在しなければなりません。

ストリーミングレプリケーションを使用したい場合、スタンバイサーバ(複数可)からのレプリケーション接続を受け付けるようにプライマリサーバで認証を設定してください。 つまり、ロールを作成し適切な項目を提供、あるいは、そのデータベースフィールドとして`replication`を持つ項目を`pg_hba.conf`内に設定してください。 また、プライマリサーバの設定ファイルにおいて`max_wal_senders`が十分大きな値に設定されていることを確認してください。

項24.3.2に記述したように、スタンバイサーバの再起動のために、ベースバックアップを取得してください。

## 25.2.4. スタンバイサーバの設定

スタンバイサーバを設定するためには、プライマリサーバから取得したベースバックアップをリストアしてください(項24.3.3参照)。 スタンバイのクラスタデータディレクトリ内に`recovery.conf`リカバリコマンドファイルを作成し、`standby_mode`を有効にしてください。 WALアーカイブからファイルをコピーする簡単なコマンドを`restore_command`に設定してください。 高可用性のために複数のスタンバイサーバを持たせようとしている場合、`recovery_target_timeline`を`latest`に設定し、スタンバイサーバが他のスタンバイにフェールオーバする時に発生するタイムラインの変更に従うようにします。

> 注意: ここで説明した組込みのスタンバイモードといっしょにpg_standbyや類似ツールを使用しないでください。 `restore_command`はファイルが存在しない場合に即座に終了しなければなりません。 サーバが必要に応じてそのコマンドを再度実行します。 pg_standbyのようなツールを使用するためには項25.4を参照してください。

ストリーミングレプリケーションを使用したい場合には、ホスト名(またはIPアドレス)とプライマリサーバとの接続に必要な追加情報を含む、libpq接続文字列で`primary_conninfo`を記述してください。 プライマリで認証用のパスワードが必要な場合は`primary_conninfo`にそのパスワードも指定する必要があります。

スタンバイサーバを高可用性を目的に設定しているのであれば、スタンバイサーバはフェールオーバの後プライマリサーバとして動作しますので、プライマリサーバと同様にWALアーカイブ処理、接続、認証を設定してください。

WALアーカイブを使用している場合、archive_cleanup_commandパラメータを使用してスタンバイサーバで不要となったファイルを削除することで、その容量を最小化することができます。 特にpg_archivecleanupユーティリティは、典型的な単一スタンバイ構成（pg_archivecleanup参照）における`archive_cleanup_command`と共に使用されるように設計されています。 しかし、バックアップを目的にアーカイブを使用している場合には、スタンバイから必要とされなくなったファイルであっても、最新のベースバックアップの時点からリカバリするために必要なファイルを保持しなければならないことに注意してください。

`recovery.conf`の簡単な例を以下に示します。

    standby_mode = 'on'
    primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
    restore_command = 'cp /path/to/archive/%f %p'
    archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'

スタンバイサーバの台数に制限はありませんが、ストリーミングレプリケーションを使用するなら、プライマリサーバに同時に接続できるように`max_wal_senders`を十分な数に設定してください。

## 25.2.5. ストリーミングレプリケーション

ストリーミングレプリケーションによりスタンバイサーバはファイルベースのログシッピングよりもより最近の状態を維持できるようになります。 スタンバイは、WALレコードが生成された時にWALファイルがいっぱいになるまで待機せずにWALレコードをスタンバイに流し出すプライマリと接続します。

ストリーミングレプリケーションは非同期です。 このため、プライマリでトランザクションがコミットされてから、その変更がスタンバイ側で参照可能になるまでの間にわずかな遅延がまだあります。 しかし、この遅延はファイルベースのログシッピングよりも非常に小さなもので、ロードを維持できる程度の能力があるスタンバイであれば通常は1秒以下です。 ストリーミングレプリケーションでは、データ損失期間を減らすための`archive_timeout`を必要としません。

ファイルベースの継続的アーカイブのないストリーミングレプリケーションを使用している場合、マスタにおいて`wal_keep_segments`の値を、スタンバイが古いWALセグメントに追随する必要がある時にそれらががあまりに早く回収されないことが確実になるように、十分大きく設定しなければなりません。 スタンバイ側が大きく遅れてしまった場合、新しいベースバックアップから再初期化する必要があります。 スタンバイからアクセスできるようにWALアーカイブを設定する場合は、スタンバイは常に追随するためにアーカイブを使用することができますので、`wal_keep_segments`は必要ありません。

ストリーミングレプリケーションを使用するためには、項25.2の説明のようにファイルベースのログシッピングを行うスタンバイサーバを設定してください。 ファイルベースのログシッピングを行うスタンバイをストリーミングレプリケーションを行うスタンバイに切り替える手順は、`recovery.conf`内の`primary_conninfo`設定をプライマリサーバを指し示すように設定することです。 スタンバイサーバがプライマリサーバ上の`replication`疑似データベースに接続できる(項25.2.5.1参照)ように、プライマリでlisten_addressesと認証オプション(`pg_hba.conf`参照)を設定してください。

キープアライブソケットオプションをサポートするシステムでは、tcp_keepalives_idle、tcp_keepalives_intervalおよびtcp_keepalives_countを設定することで、プライマリの接続切断の即時検知に有用です。

スタンバイサーバからの同時接続数の最大値を設定してください（詳細はmax_wal_sendersを参照）。

スタンバイが起動し、`primary_conninfo`が正しく設定されると、スタンバイはアーカイブ内で利用可能なWALファイルをすべて再生した後にプライマリと接続します。 接続の確立に成功すると、スタンバイでWAL受信プロセスが存在し、プライマリで対応するWAL送信プロセスが存在します。

### 25.2.5.1. 認証

信頼できるユーザのみがWALストリームを読み取ることができるように、レプリケーション用のアクセス権限を設定することは非常に重要です。 WALから機密情報を取り出すことは簡単だからです。 スタンバイサーバはプライマリに対して`REPLICATION`権限を持つアカウントとして認証されなければなりません。 このため、`REPLICATION`および`LOGIN`権限を持つロールをプライマリ上で作成しなければなりません。

> 注意: レプリケーションに専念するユーザアカウントを使用することを勧めます。 `REPLICATION`権限はデフォルトでスーパーユーザアカウントに付与されていますが、レプリケーションでスーパーユーザアカウントを使用することは勧めません。 `REPLICATION`権限は非常に高度な権限を与えますが、`SUPERUSER`権限が行うような主システムにおけるデータの変更は許されていません。

レプリケーション用のクライアント認証は`pg_hba.conf`内でその`database`フィールドに`replication`を指定したレコードで制御されます。 例えば、スタンバイがIPアドレス`192.168.1.100`のホストで稼動し、レプリケーション用のアカウントの名前が`foo`である場合、管理者はプライマリ上の`pg_hba.conf`に以下の行を追加することができます。

    # 利用者 foo のホスト 192.168.1.100 からプライマリサーバへのレプリケーションスタンバイとしての接続を
    # 利用者のパスワードが正しく入力されたならば許可する
    #
    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    host    replication     foo             192.168.1.100/32        md5

プライマリサーバのホスト名とポート番号、接続する利用者名およびパスワードは、`recovery.conf`ファイルで指定します。 パスワードはスタンバイサーバの`~/.pgpass`ファイルでも設定できます（`database`フィールドの`replication`を指定します）。 例えば、プライマリサーバが稼動するホストの IP アドレスが`192.168.1.50`でポート番号が`5432`であり、レプリケーションのアカウント名が`foo`であり、パスワードが`foopass`である場合、管理者はスタンバイサーバの`recovery.conf`ファイルに次行を追加できます。

    # プライマリサーバが 192.168.1.50 のホストの 5432ポートで稼動し
    # 利用者名が foo でパスワードが foopass とする
    primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'

### 25.2.5.2. 監視

ストリーミングレプリケーションの重要な健全性尺度は、プライマリサーバで生成されたがスタンバイサーバではまだ適用されていないWALレコードの量です。 プライマリサーバの現在のWAL書き込み位置とスタンバイサーバの受理したWALの最終位置を比較すれば、この遅延を計算できます。 これらの位置は、プライマリサーバでは`pg_current_xlog_location`を、スタンバイサーバでは`pg_last_xlog_receive_location`を使用すれば検索できます（詳細は表9-56および表9-57を参照）。 スタンバイサーバの最終位置は、`ps`コマンドを使用して WAL 受理プロセスの状態としても表示できます（詳細は項27.1を参照）。

`pg_stat_replication`ビューを介してWAL送信処理プロセスのリストを入手することができます。 `pg_current_xlog_location`と`sent_location`フィールドとの違いが大きい場合、マスタサーバが高負荷状態であることを示している可能性があります。 一方でスタンバイサーバ上の`sent_location`と`pg_last_xlog_receive_location`の値の差異は、ネットワーク遅延、またはスタンバイっが高負荷状態であることを示す可能性があります。

## 25.2.6. 同期レプリケーション

PostgreSQLのストリーミングレプリケーションはデフォルトで非同期です。 プライマリサーバがクラッシュした場合、コミットされた一部のトランザクションがスタンバイサーバに複製されず、データ損失を引き起こす可能性があります。 データ損失量はフェールオーバ時点のレプリケーション遅延に比例します。

同期レプリケーションは、あるトランザクションでなされた変更はすべて、１つの同期スタンバイサーバに転送されていることを確実にする機能を提供します。 これはトランザクションコミットで提供される永続性の標準レベルを拡張します。 この保護レベルはコンピュータ科学理論では2-safeレプリケーションと呼ばれます。

同期レプリケーションを要求する時、書き込みトランザクションのコミットはそれぞれ、そのコミットがプライマリサーバおよびスタンバイサーバの両方で、ディスク上のトランザクションログに書き込まれたという確認を受けとるまで待機します。 データ損失が起こる可能性は、プライマリサーバとスタンバイサーバが同時にクラッシュしてしまった場合のみです。 これは非常に高い永続性を提供することができますが、それはシステム管理者が２つのサーバの設置と管理に関して注意を払っている場合のみです。 確認のための待機は、サーバがクラッシュした場合でも変更が失われないということでユーザからの信頼性が大きくなりますが、同時に要求するトランザクションの応答時間も必ず大きくなります。 最小待機時間はプライマリとスタンバイの間の往復遅延時間です。

読み取り専用のトランザクションおよびトランザクションのロールバックはスタンバイサーバからの応答を待つ必要はありません。 副トランザクションのコミットもスタンバイサーバからの応答を待つことはなく、最上位レベルのコミットのみ待機します。 データロード処理やインデックス構築など長時間実行される操作は、最終コミットメッセージまで待機しません。 準備およびコミットの両方を含め、二相コミット動作はすべてコミット待機を必要とします。

### 25.2.6.1. 基本設定

ストリーミングレプリケーションが設定されている場合、同期レプリケーションの設定には必要な追加設定は１つだけです。 synchronous_standby_namesを空でない値に設定しなければなりません。 また`synchronous_commit`は`on`に設定されていなければなりませんが、これはデフォルト値ですので、通常は変更する必要はありません。 この設定によりスタンバイがそのコミットレコードを信頼できるストレージに書き込んだことが確認できるまで、それに非常に時間がかかる場合であっても、各コミットが待たされるようになります。 `synchronous_replication`は個々のユーザによって設定することができます。 このため、トランザクション単位を基準とした永続性の保証を制御するために、設定ファイルの中で特定のユーザまたはデータベースについて設定することも、アプリケーションによって動的に設定することもできます。

コミットレコードがプライマリ上のディスクに書き出された後、WALレコードがスタンバイに送信されます。 スタンバイにて`wal_receiver_status_interval`がゼロに設定されていない限り、スタンバイは新しいWALデータのバッチがディスクに書き出す度にメッセージを返します。 スタンバイが、プライマリ上の`synchronous_standby_names`で指定したものと最初に一致するスタンバイである場合、そのスタンバイからの応答メッセージがコミットレコードの受領を確認するまでの待機を解除するために使用されます。 これらのパラメータにより管理者はどのスタンバイサーバが同期スタンバイとすべきかを指定することができます。 同期レプリケーションの設定は主にマスタでなされることに注意してください。

高速シャットダウンが要求された場合、ユーザは待機を停止します。 しかし非同期レプリケーションを使用している時、送信中のWALレコードが現在接続しているスタンバイサーバに転送されるまで、サーバは完全に停止しません。

### 25.2.6.2. 性能に関する考慮

通常、同期レプリケーションは、アプリケーションが満足できる程度に実行されることを確実にするために、注意深くスタンバイサーバを計画し設置しなければなりません。 待機のためにシステムリソースを使用することはありませんが、トランザクションロックは転送が確認されるまで継続して保持されます。 結果として同期レプリケーションを注意せずに使用すると、応答時間が増加する、および競合がより高くなるため、データベースアプリケーションの性能は低下します。

PostgreSQLではアプリケーション開発者がレプリケーション経由で必要とする永続性レベルを指定することができます。 これをシステム全体に対して指定することができますし、特定のユーザ、接続、個々のトランザクションに対してさえ指定することもできます。

例えばアプリケーションの作業量が、重要な顧客詳細の変更が10%、ユーザ間のチャットメッセージなど、あまり重要ではなく、失ったとしても業務をより簡単に戻すことができるようなデータの変更が90% という構成を考えてみます。

（プライマリ上で）アプリケーションレベルで指定する同期レプリケーションオプションを使用して、作業全体を低速化させることなく、最も重要な変更に対して同期レプリケーションを企てることができます。 アプリケーションレベルのオプションは、高い性能が求められるアプリケーションで同期レプリケーションの利点が得られる、重要かつ現実的な手段です。

生成されるWALデータの割合よりネットワーク帯域幅が大きくなければならないことを考慮しなければなりません。

### 25.2.6.3. 高可用性に関する検討

`synchronous_commit`が`on`に設定された場合、なされたコミットは同期スタンバイの応答まで待機されます。 応答は最後のまたは唯一のスタンバイがクラッシュした場合には決して返されません。

データ損失を防止するための最善の解法は、最後に残る同期スタンバイを失わないことを確実にすることです。 `synchronous_standby_names`を使用して複数の潜在的な同期スタンバイを指名することで実現することができます。 最初に指名されたスタンバイは同期スタンバイとして使用されます。 この後に列挙されたスタンバイは、最初のスタンバイが失敗した場合に同期スタンバイの役割を引き継ぎます。

スタンバイが最初にプライマリに付与された時、それはまだ適切に同期されていません。 これは`catchup`モードと呼ばれます。 最初にスタンバイとプライマリ間の遅延がゼロになった時に、実時間`streaming`状態に移ります。 追従（catchup）期間はスタンバイが作成された直後は長くなるかもしれません。 スタンバイが停止している場合、追従期間はスタンバイの停止期間にしたがって長くなります。 スタンバイは、`streaming`状態に達した後でのみ、同期スタンバイになることができます。

コミットが受領通知を待機している間にプライマリが再起動した場合、プライマリデータベースが復旧した後、待機中のトランザクションは完全にコミットされたものと記録されます。 すべてのスタンバイがプライマリのクラッシュ時点で送信中のWALデータのすべてを受信したかどうかを確認する方法はありません。 トランザクションの一部は、プライマリではコミットされたものと表示されていたとしても、コミットされていないと表示されるかもしれません。 提供できる保証は、WALデータがスタンバイで安全に受信したことが分かるまで、アプリケーションは明示的なトランザクションコミットの成功に関する受領通知を受けとらないことです。

最終スタンバイサーバを本当に失った場合、`synchronous_standby_names`を無効にし、プライマリサーバの設定ファイルを再読み込みしなければなりません。

プライマリが残りのスタンバイサーバと孤立された場合、残りのスタンバイサーバの中から最善の候補にフェールオーバさせなければなりません。

トランザクションの待機中にスタンバイサーバを再作成する必要がある場合、pg_start_backup()およびpg_stop_backup()を実行するコマンドを`synchronous_commit` = `off`であるセッション内で確実に実行してください。 さもないとこれらの要求はスタンバイに現れるまで永遠に待機します。

前のページ | ホーム | 次のページ
様々な解法の比較 | 上に戻る | フェールオーバ