ホットスタンバイホットスタンバイという単語は、サーバがアーカイブリカバリを実行している最中にサーバに接続し読み取り専用の問い合わせを実行することができる機能を説明するために使われます。これは、レプリケーションという目的およびバックアップからのリストアの両方で高い精度で好ましい状態にするために有用です。ホットスタンバイという単語はまた、ユーザが問い合わせを実行しながら、または、開いている接続を維持しながら、またはその両方で、サーバをリカバリ状態から通常の動作に移すことができる機能も示すものです。ホットスタンバイモードにおける問い合わせは、通常の問い合わせに類似していますが、利用上および管理上の差異が多少あり、以下に説明します。ユーザのための概説スタンバイサーバでhot_standbyパラメータが真に設定されている場合、リカバリによりシステムが一貫性を持つようになった後接続を受け付け始めます。した接続はすべて読み取り専用に限定されます。一時テーブルであっても書き込むことはできません。スタンバイ上のデータはプライマリサーバから届くまでに多少の時間がかかります。このため、プライマリとスタンバイの間にはある程度の遅延があります。したがって、同じ問い合わせをほとんど同時にプライマリとスタンバイに対して実行すると、異なる結果が返る可能性があります。スタンバイ上のデータはプライマリに対して最後には一貫性を持つといいます。あるトランザクションのコミットレコードがスタンバイ上で再生されると、そのトランザクションでなされた変更はスタンバイで獲得されるすべての新規スナップショットで可視になります。現在のトランザクション隔離レベルに応じて、スナップショットは各問い合わせの開始時または各トランザクションの開始時に獲得されます。詳細については項13.2を参照してください。ホットスタンバイ中に開始されたトランザクションは以下のコマンドを発行することができます。以下のモードが明示された場合に限ります。LOADホットスタンバイ中に開始したトランザクションではトランザクションIDを割り当てられません。システムのログ先行書き込みに書き出すことができません。このため、以下の動作はエラーメッセージを生成します。データ操作言語(DML)。FROMおよびTRUNCATE。リカバリ中にトリガ内で実行されてしまう場合でも許されていない動作であることに注意してください。現在のホットスタンバイ環境では行うことができないトランザクションIDの割り当てを行うことなく、テーブル行の読み書きを行うことができませんので、この制限は一時テーブルであっても適用されます。データ定義言語(DDL)。CREATE、DROP、ALTERおよびCOMMENT。この制約は一時テーブルに対しても適用されます。これらの操作の実行がシステムカタログテーブルの更新を必要とするためです。背後のデータファイルを更新することなく行ロックを獲得することはできないためです。MODEより高いモードを明示的に要求するLOCK短いデフォルト構文のLOCK。MODEを要求するためです。読み取り専用トランザクションでも、プリペア相(二相コミットの第1相)においてWALの書き込みが必要だからです。nextval()とsetval()LISTEN、UNLISTENおよびNOTIFY通常の操作では、"読み取り専用"トランザクションにはシーケンスの更新およびLISTENとUNLISTENとNOTIFYの使用が許可されています。ホットスタンバイセッションの操作では、通常の読み取り専用セッションよりも少し厳しい制約を受けます。将来のリリースではこの制約の一部が緩和されるかもしれません。ホットスタンバイ中は、transaction_read_onlyパラメータは常に真であり、変更することはできません。データベースを変更するような試行がない限り、ホットスタンバイ中の接続は他のデータベース接続とほとんど同じように動作します。フェールオーバまたはスイッチオーバが発生すると、データベースは通常処理モードに切り替わります。サーバのモードが変わってもセッションは接続を保持します。ホットスタンバイが完了すると、読み書き可能なトランザクションを(ホットスタンバイ中に始まったセッションからであっても)始められるようになります。transaction_read_onlyを発行することで、そのセッションが読み取り専用かどうかを調べることができます。ユーザがスタンバイサーバに関する情報にアクセスできる関数群(表9-61)があります。これらによりデータベースの現状認識を行うプログラムを作成することができます。これらを使用して、リカバリの進行状況を監視するために使用したり、データベースを特定の状態にリストアする複雑なプログラムを作成したりすることができます。問い合わせコンフリクトの処理プライマリサーバとスタンバイサーバは、多方面でゆるく結合しています。プライマリサーバの動作はスタンバイサーバに影響します。その結果、負の相互作用またはコンフリクトの可能性があります。分かりやすいコンフリクトは性能です。プライマリサーバで巨大なデータがロードされた場合、スタンバイサーバにおいて同様に巨大なWALレコードが生成されるので、スタンバイサーバにおける問い合わせは互いにI/Oなどのシステム資源を奪い合います。ホットスタンバイで発生する可能性があるコンフリクトの種類には他にもあります。これらのコンフリクトは、問い合わせをキャンセルしなければならない可能性があり、解消させるためにはセッションの接続を閉ざすことになる場合もあるため、致命的なコンフリクトです。ユーザにはこうしたコンフリクトを扱うための複数の方法が提供されます。コンフリクトする状況には以下があります。プライマリサーバで獲得されたアクセス排他ロックは、スタンバイの問い合わせにおけるテーブルアクセスとコンフリクトします。明示的なLOCKコマンドおよび各種DDL操作を含みます。プライマリでテーブル空間を削除することは、一時作業ファイル用にそのテーブル空間を使用するスタンバイ側の問い合わせとコンフリクトします。プライマリでデータベースを削除することは、スタンバイ側でそのデータベースに接続するセッションとコンフリクトします。WALからレコードを消去するバキュームアプリケーションは、削除される任意の行を"見る"ことができるスナップショットを持つスタンバイでのトランザクションとコンフリクトします。WALからレコードを消去するバキュームアプリケーションは、消去されるデータが可視か否かに関係なく、スタンバイで対象ページにアクセスする問い合わせとコンフリクトします。プライマリサーバでは、こうした状況は単に待たされるだけです。ユーザはコンフリクトする操作をキャンセルすることを選ぶことができます。スタンバイ側には選択肢がありません。WALに記録された操作はすでにプライマリで発生したものですので、スタンバイではその適用に失敗してはなりません。申請されたWALを無制限に待機させることを許すことは、まったく望まない結果になってしまうかもしれません。スタンバイの状態がプライマリの状態とだんだんとかけ離れてしまうからです。したがって適用すべきWALレコードとコンフリクトするスタンバイの問い合わせを強制的に取り消す仕組みが用意されています。TABLEを行う管理者を考えてみます。TABLEが適用されたら問い合わせを継続できないことは明確です。TABLEは待機されます。TABLEがプライマリで実行された時、プライマリ側でスタンバイで稼動する問い合わせに関する情報がありませんので、スタンバイ側のこうした問い合わせを待機させることはできません。スタンバイ側で問い合わせが実行している時にWALの変更レコードがスタンバイに届けば、コンフリクトが発生します。TABLEを適用できるようにコンフリクトする問い合わせを取り消すかのいずれかを行わなければなりません。コンフリクトする問い合わせが短ければ、申請されたWALを多少遅延させることで、問い合わせを完了させることが通常望まれます。申請されたWALが長く遅延することはたいていは望まれません。したがって、取り消し機能はmax_standby_archive_delayとmax_standby_streaming_delayというパラメータを持ちます。これらは申請されたWALに許される遅延を定義するものです。コンフリクトする問い合わせは、何らかの新しく受信したWALデータを適用するための各種遅延設定を超えたら取り消されます。アーカイブからWALデータを読み取る場合(つまりベースバックアップからの初期リカバリや大きく遅延したスタンバイサーバの"追従")とストリーミングレプリケーションとで異なる遅延値を指定することができるように2つのパラメータが存在します。高可用性のために存在するスタンバイサーバでは、スタンバイ側の問い合わせによって発生する遅延のためにプライマリと大きく遅延が発生することがないように、遅延パラメータを相対的に短く設定することが最善です。スタンバイサーバが長時間かかる問い合わせを実行するためのものであれば、長い遅延もしくは制限を設けないことが好まれるかもしれません。長時間かかる問い合わせがWALレコードの適用を遅延させてしまう場合、スタンバイサーバ上の他のセッションがプライマリにおける最近の変更を参照することができなくなることは覚えておいてください。max_standby_archive_delayまたはmax_standby_streaming_delayで指定した遅延を超えると、コンフリクトする問い合わせは取り消されます。DATABASEを再生する場合では、コンフリクトするセッション全体が終了します。コンフリクトが待機中のトランザクションで保持されるロックについてのものであれば、そのコンフリクトするセッションが終了します(この動作は将来変更されるかもしれません)。取り消された問い合わせは直ちに再試行されます(もちろん新規のトランザクション開始後に)。問い合わせの取り消しは、再生されるWALレコードの性質に依存するので、取り消された問い合わせが再度実行された場合には正常に動作するかもしれません。遅延パラメータはスタンバイサーバでWALデータを受信してからの経過時間と比べられることに注意してください。したがって、スタンバイ上で任意の問い合わせに許される猶予期間は、この遅延パラメータよりも大きくなることは決してありません。これまでの問い合わせを完了させるために待機した結果、あるいは、大量の更新負荷に追従することができなくなった結果、スタンバイがすでに遅延している場合は相当小さくなります。スタンバイ側の問い合わせとWAL再生の間でもっともよくあるコンフリクト理由は"早すぎる消去"です。通常PostgreSQLはMVCC規則にしたがって正確なデータの可視性を確実にするために、古い行バージョンを参照するトランザクションが存在しない場合それらを消去することが許されています。この規則はマスタ上で実行するトランザクションのみに適用させることができます。したがって、スタンバイ上のトランザクションでまだ可視である行バージョンを、マスタ上の消去処理が削除してしまう可能性があります。熟練したユーザは、行バージョンの消去と行バージョンの凍結の両方ともスタンバイ側の問い合わせとコンフリクトする可能性があることに気づくはずです。FREEZEは、更新または削除された行がないテーブルであったとしてもコンフリクトを発生し易いものです。プライマリサーバにおいて規則的かつ頻繁に更新されるテーブルは、スタンバイサーバにおける問い合わせの取り消しの原因になりやすいことを利用者は理解するべきです。そのような場合、max_standby_archive_delayまたはmax_standby_streaming_delayの設定値はstatement_timeoutの設定と同様に考えることができます。取り消しの数が受け入れがたいほど多い場合、他に救済的な処理法があります。1つ目の選択肢は、hot_standby_feedbackパラメータを設定することです。これはVACUUMによる最近不要になった行の削除を防止しますので、消去によるコンフリクトが発生しません。これを行う場合、プライマリで不要になった行の消去が遅延することに注意しなければなりません。望まないテーブルの膨張が発生してしまうかもしれません。スタンバイ側で行うべき問い合わせをプライマリサーバ上で直接実行することと比べ、こうした消去に関する問題を優先する価値はありません。スタンバイに実行負荷を分散できるという利点があります。この場合、遅延したWALファイルにすでに、スタンバイ側で実行させたい問い合わせとコンフリクトする項目が含まれている可能性がありますので、max_standby_archive_delayは長めにしなければなりません。他の選択肢は、不要になった行が通常よりも早く消去されないようにプライマリサーバでvacuum_defer_cleanup_ageを増やすことです。これにより、max_standby_streaming_delayを長くすることなく、スタンバイでキャンセルが起こるようになる前により多くの時間、問い合わせを実行することができます。vacuum_defer_cleanup_ageはプライマリサーバ上で実行されたトランザクションを単位に測定されますので、この方法では特定の実行期間を保証することは困難です。問い合わせキャンセルの個数とその原因はスタンバイサーバ上のpg_stat_database_conflictsシステムビューを用いて参照することができます。pg_stat_databaseシステムビューには要約された情報が含まれます。管理者のための概説postgresql.confにおいてhot_standbyがonに設定されかつrecovery.confが存在すれば、サーバはホットスタンバイモードで稼動します。サーバはまず問い合わせが実行できる程度の一貫性を持つ状態を提供するために十分なリカバリを完了させなければなりませんので、ホットスタンバイでの接続が有効になるまでに多少の時間がかかるかもしれません。サーバの準備ができたことを確認するために、アプリケーションで接続試行を繰り返すか、サーバログに以下のメッセージがあるかどうかを確認します。connections一貫性に関する情報はプライマリでチェックポイント毎に一度記録されます。プライマリでwal_levelがhot_standbyに設定されていない間に書き込まれたWALを読み取っている時、ホットスタンバイを有効にすることはできません。一貫性のある状態への到達は、以下の両方が存在する間遅延することがあります。サブトランザクション数が64を超える書き込みトランザクション非常に長く実行される書き込みトランザクションファイルベースのログシッピング(「ウォームスタンバイ」)を実行しているのであれば、次のWALファイルが届く、長くともプライマリのarchive_timeout設定まで待機しなければなりません。プライマリサーバにおける設定値が変更した場合、スタンバイサーバにおいて数個のパラメータの再設定が必要です。スタンバイサーバにおける設定値は、プライマリサーバにおける設定値以上でなければなりません。所定値未満の設定の場合、スタンバイは起動を取りやめます。所定値以上の設定により、スタンバイサーバは再起動してリカバリが再び開始されます。このパラメータは以下です。max_connectionsmax_prepared_transactionsmax_locks_per_transactionmax_standby_archive_delayおよびmax_standby_streaming_delayの値が適切であるように管理者が選択することが重要です。最善の選択は業務上の優先順位によって変化します。サーバが主に高可用性を目的としたサーバとして作業するものであれば、短い遅延を設定したいでしょう。非常に積極的な設定ですが、ゼロにしたいかもしれません。スタンバイサーバが意思決定支援のための問い合わせ用の追加サーバとして作業するものであれば、数時間程度の最大の遅延値の設定、あるいは問い合わせの完了を永遠に待つことを意味する-1という設定でさえ、許容範囲であるかもしれません。プライマリ側で「ヒントビット」として書き出されたトランザクション状態はWALに記録されません。このためスタンバイ側のデータはスタンバイ側でヒントを再度書き出すことになります。ユーザは大規模なソート用の一時ファイルを書き出し、relcache情報ファイルを再作成します。したがって、ホットスタンバイモードではデータベースのすべてが本当に読み取り専用ではありません。ローカルでは読み取り専用のトランザクションであってもdblinkモジュールを使用したリモートデータベースへの書き出しや、その他のPL関数を使用したデータベース外部への操作が可能であることに注意してください。リカバリモードの間、下記の管理者用コマンドは受理されません。ANALYZEとVACUUMとCLUSTERとREINDEX繰り返しますが、これらのコマンドの一部は、プライマリサーバにおける「読み取り専用」モードのトランザクションで実際に許可されていることに注意してください。その結果、スタンバイ側にのみ存在する追加のインデックスやスタンバイ側にのみ存在する統計情報を作成することはできません。これらの管理者用コマンドが必要な場合、プライマリ側で実行しなければなりません。最終的にこの変更はスタンバイ側に伝播します。pg_cancel_backend()とpg_terminate_backend()は利用者のバックエンドでは実行できますが、リカバリを実行する起動プロセスでは実行できません。pg_stat_activityは起動プロセスのエントリを表示しないし、リカバリトランザクションが実行中かどうかも表示しません。その結果、リカバリの間pg_prepared_xactsは常に空となります。準備した確信のもてないトランザクションの状態を解明したい場合、プライマリサーバにおいてpg_prepared_xactsを表示するビューを作成し、ビューに解明のためのコマンドを発行してください。pg_locksは通常通りバックエンドで保持されるロックを示します。pg_locksはまた、リカバリによって再生されているトランザクションで保持されるAccessExclusiveLocksのすべてを所有する、起動プロセスで管理される仮想トランザクションも表示します。起動プロセスはデータベースの変更を行うためのロックを獲得しません。このため起動プロセスにおいてAccessExclusiveLocks以外のロックはpg_locksでは表示されません。これらは存在することを想定されているだけです。存在を検知する情報が単純なので、Nagiosプラグインは稼動します。一部の報告値が異なった、混乱を招く結果となりますが、check_postgresの監視スクリプトも動作します。それでも、プライマリで行われるバキュームはその変更をスタンバイに送信します。リカバリの間WALの制御コマンドは稼動しません。pg_start_backupやpg_switch_xlogなどです。pg_stat_statementsも含み、動的に読み込み可能なモジュールは稼動します。デッドロック検出を含むアドバイザリロックは、通常リカバリにおいて稼動します。アドバイザリロックはWALに決して記録されないので、プライマリサーバでもスタンバイサーバでもWALの再実行においてコンフリクトが起こらないことに注意してください。プライマリサーバでアドバイザリロックを取得して、スタンバイサーバで同様のアドバイザリロックを掛けることはできません。アドバイザリロックは取得したサーバだけに関係するものです。SlonyやLondisteやBucardoのようにトリガに基づいたレプリケーションシステムは、スタンバイサーバで全く稼動しません。それによる変更がスタンバイサーバに送られるまでは、プライマリサーバにおいて問題なく稼動します。WALの再実行はトリガに基づいたものではありません。したがって、データベースへの付加的な書き込みを必要とするか、トリガの使用に依存するものを、スタンバイサーバを中継して他のシステムへ送ることはできません。一部のUUIDジェネレータは、データベースに新しい状態を書き出すことに依存していない限り動作可能ですが、新しいOIDを割り当てることはできません。現時点では、読み取り専用のトランザクションでは一時テーブルの作成は許されません。このため既存のスクリプトが正しく動作しない場合があります。この制限は将来のリリースで緩和されるかもしれません。これは、標準SQLとの互換性の問題でもあり、技術的な問題でもあります。TABLESPACEが成功します。一部のスタンバイ側のユーザはtemp_tablespacesパラメータを介してテーブル空間を活発に使用しているかもしれません。テーブル空間に一時ファイルが存在する場合、一時ファイルを確実に削除するためすべての問い合わせが取り消されます。このため、WAL再生を続けながらテーブル空間を削除することができます。TABLESPACEの実行により、スタンバイサーバのデータベースに接続するすべてのユーザを強制的に接続を切断させることになるWALエントリを生成します。これはmax_standby_streaming_delayの設定にかかわらず、直ちに起こります。RENAMEはユーザを切断しないので大部分の場合は気がつきませんが、プログラムがデータベースの名称に依存するときは混乱の原因となることに注意してください。ROLEを発行した場合、接続中のユーザには何も起こらず、接続し続けます。そのユーザは再接続できません。この振舞いはリカバリモードでも適用されます。USERされたとしても、スタンバイ側のユーザの接続は切断されません。リカバリの間も統計情報は収集されます。すべてのスキャン、読み取り、ブロック、インデックスの使用などは、スタンバイサーバにおいて正常に記録されます。再実行によりプライマリサーバの結果が重複して収集されることはないので、行の挿入によりpg_stat_user_tablesの挿入列の値は増加しません。リカバリの開始時点で統計情報ファイルが削除されるので、プライマリサーバとスタンバイサーバで統計情報は異なります。これは将来どうするか検討中であり、バグではありません。リカバリの間は自動バキュームは稼動しません。リカバリが終わると正常に起動します。リカバリの間バックグラウンドライタは稼動して(プライマリサーバにおけるチェックポイントに類似した)リスタートポイントを設定し、通常のブロック消去を行います。これはスタンバイサーバに保存されるヒントビット情報の更新を含むことができます。リカバリの間CHECKPOINTコマンドは受理されますが、新規のチェックポイントではなくてリスタートポイントが設定されます。ホットスタンバイパラメータリファレンス種々のパラメータが上記項25.5.2および項25.5.3で述べられています。プライマリサーバでは、wal_levelおよびvacuum_defer_cleanup_ageのパラメータを使用できます。プライマリサーバにmax_standby_archive_delayおよびmax_standby_streaming_delayを設定しても無効です。スタンバイサーバではhot_standbyとmax_standby_archive_delayとmax_standby_streaming_delayのパラメータを使用できます。サーバがスタンバイモードの間vacuum_defer_cleanup_ageを設定しても無効です。スタンバイサーバがプライマリサーバになった場合、意味を持つようになります。警告ホットスタンバイには幾つかの制限があります。将来のリリースでは改善されると思われます。現在ハッシュインデックスに対する操作はWALに記録されません。このため再生してもこれらのインデックスは更新されません。スナップショットを取ることができるようになる前に、実行中のトランザクションについての完全な知識が要求されます。(現時点では64を超える)多くのサブトランザクションを使用するトランザクションでは、実行中の最長の書き込みトランザクションが完了するまで、読み取り専用の接続の開始は遅延されます。この状況が起こると、それを説明するメッセージがサーバログに記録されます。スタンバイ問い合わせ用の有効な起動ポイントは、マスタにおけるチェックポイント毎に生成されます。マスタが停止状態にある時にスタンバイが停止した場合、プライマリが起動し、さらに起動ポイントをWALログに生成するまで再度ホットスタンバイになることができないことがあります。この状況は、通常考えられる状態では問題ではありません。一般的に、プライマリが停止し利用できなくなった場合、それはスタンバイに対して新しいプライマリに切り替わることを要求するような深刻な失敗が原因であることが多いはずです。プライマリを意図的に停止させるような状況では、それに伴いスタンバイが新しいプライマリになめらかに切り替わることも普通の手順です。リカバリの終了において、準備されたトランザクションが保持するAccessExclusiveLocksには、通常の2倍のロックテーブルへのエントリ数が必要です。通常AccessExclusiveLocksを取るプリペアドトランザクションを大量に同時実行させる、または、多くのAccessExclusiveLocksを取る大規模なトランザクションを1つ実行させることを考えている場合、max_locks_per_transactionの値を、おそらくプライマリサーバのパラメータ値の倍程度に大きくすることを勧めます。max_prepared_transactionsの設定が0ならば、これを検討する必要はまったくありません。シリアライザブルトランザクション隔離レベルはまだホットスタンバイでは利用できません。ホットスタンバイにおいてトランザクションをシリアライザブルトランザクション隔離レベルに設定しようとすると、エラーになります。