トップ  >  Postgres Plus Advanced Server 上での Warm standby の構築手順

PostgreSQL のウォームスタンバイについて

PostgreSQL のウォームスタンバイは、本来は PITR のためにつくられた機構であるリカバリモードを転用して、高可用性のための待機系 DB の構築をおこなう機能です。待機系 DB は、稼動系 DB から送られてくる WAL ログセグメントを順次読み込むことで、DB クラスタのコピーを、障害時に備えて更新し続けます。

メリット:

  • Slony-I などの SQL レベルでのレプリケーションでは、テーブルを管理対象として、行単位での複製を行なうのに対し、ウォームスタンバイでは、DB クラスタ全体のコピーを作成します。障害に備えた、完全なコピーを作成することができます
  • WAL ログと呼ばれる、データベースファイルへのバイナリレベルでのトランザクション反映の記録を転送するため、稼動系 DB への負荷を低く抑えることが可能です

デメリット:

  • ログセグメントの転送は非同期でインターバルが大きめ(16MB ぶんが溜まるごと、あるいは設定されたタイムアウトごと)なので、障害時のデータ欠損の可能性が比較的大きいです
  • リカバリモードの待機系には一切アクセスができないので、読み取り用としての負荷分散用途にはならないため、リソースがもったいないです

関連リンク:

参考: PostgreSQL-9.0 からは、従来のウォームスタンバイに代わって、より小さい単位でトランザクションログを転送する「ストリーミング・レプリケーション」と、待機系でも参照クエリを実現する「ホットスタンバイ」と呼ばれる機能が提供されます。これによって、上記デメリットが大きく低減されます。構築の手順自体は、ウォームスタンバイとほぼ同様です。

Postgres Plus Advanced Server 上での Warm standby の構築手順

1. 前提と凡例

稼動系であり、WAL ログセグメントを送出する側のホストを「稼動系サーバ」と呼称し、そのホスト名を "node0" とし、FQDN を "node0.example.com" とします。

待機系であり、WAL ログセグメントを受け取り、それを随時データベースクラスタに適用させながら、昇格トリガーを受け取るまで待機する側のホストを「待機系サーバ」と呼称し、そのホスト名を "node1" とし、FQDN を "node1.example.com" とします。

稼動系サーバ、待機系サーバ共に、Postgres Plus Advanced Server (以下 "PPAS") for Linux 8.3 R2 がデフォルトパラメータでインストールされているとします。データの保存先(データファイルや WAL ログの保存先)のディレクトリ等を変更した場合には、適宜読み替えてください。

稼動系サーバのデータベースは、すでに稼働しているとします。以下の手順で、WAL ログセグントのアーカイブ転送設定を反映させる際以外は、基本的に稼動系サーバを停止させる必要はありません。

以降、各プロンプトの例は、以下のような意味を持ちます。

  [enterprisedb@node0]$ cd /opt/PostgresPlus/8.3R2AS/稼動系ホスト "node0" 上のユーザ "enterprisedb" での実行。下線部は、環境によって異なる可能性のある部分

  [root@node1]# ls待機系ホスト "node1" 上の root ユーザでの実行

  edb=# ← データベース管理者として edb-psql コマンドで "edb" DB に接続

2. SSH 接続の準備

稼動系サーバから待機系サーバに、SSH 接続経由の rsync で WAL ログセグメントやベースバックアップを送出する設定をします。以下、パスワードなしで SSH のコネクションを張れるようにしておきます。

稼動系側で、キーを作成し、転送します。

  [enterprisedb@node0 ~]$ ssh-keygen
  Generating public/private rsa key pair.
  Enter file in which to save the key (/home/enterprisedb/.ssh/id_rsa): ← Enter
  Created directory '/home/enterprisedb/.ssh'.
  Enter passphrase (empty for no passphrase): ← Enter
  Enter same passphrase again: ← Enter
  Your identification has been saved in /home/enterprisedb/.ssh/id_rsa.
  Your public key has been saved in /home/enterprisedb/.ssh/id_rsa.pub.
  The key fingerprint is:
  bb:2a:4f:72:cd:59:fe:55:5b:a3:b4:45:b5:c8:34:77 enterprisedb@node0
  [enterprisedb@node0 ~]$ scp ~/.ssh/id_rsa.pub enterprisedb@node1.example.com:
  enterprisedb@node1.example.com's password: ← パスワードを入力し、Enter
  id_rsa.pub                                    100%  402     0.4KB/s   00:00
  [enterprisedb@node0 ~]$ 

待機系側で、キーをチェーンに追加します。

  [enterprisedb@node1 ~]$ mkdir -p ~/.ssh/
  [enterprisedb@node1 ~]$ chmod 700 ~/.ssh/
  [enterprisedb@node1 ~]$ cat id_rsa.pub >> ~/.ssh/authorized_keys
  [enterprisedb@node1 ~]$ chmod 600 ~/.ssh/authorized_keys
  [enterprisedb@node1 ~]$ rm -f ~/id_rsa.pub
  [enterprisedb@node1 ~]$ 

稼動系側から待機系側へ、パスワードなしにログインができることを確認します。

  [enterprisedb@node0]$ ssh enterprisedb@node1.example.com
  Last login: Fri Jul 31 16:04:27 2009 from node0.example.com
  [enterprisedb@node1]$ 

3. 待機系サーバの準備

待機系サーバのデータベースを(動いているようであれば)停止させます。

  [root@node1]# /etc/init.d/edb_8.3R2 stop

待機系サーバの初期データベースクラスタは稼動系のそれのコピーを用います。デフォルトで作成されたものは使いません。削除しておきます(インストール環境やディストリビューションによっては、/opt/PostgresPlus/8.3R2AS/data/ 以下のファイルで、オーナーが "root" になっていて消せないファイルがあるかも知れません。適宜 root 権限で削除しておいてください)。

  [enterprisedb@node1]$ rm -fr /opt/PostgresPlus/8.3R2AS/data/

WAL ログセグメントがアーカイブされるディレクトリを作成しておきます。

  [enterprisedb@node1]$ mkdir -p ~/archive/

4. 稼動系サーバのアーカイブ送出の設定

稼動系サーバで、/opt/PostgresPlus/8.3R2AS/data/postgresql.conf を編集し、アーカイブを作成するコマンドと、必要であれば、強制アーカイブ送出までのインターバル時間を設定します。"0"、もしくはコメントアウトにすると、ログセグメントがいっぱい(16MB)になってから送出するようになります。なお、ここで scp ではなく rsync を使うのは、rsync はデータがすべてコピーし終えるまでは別名で一時ファイルを作ってくれる(アトミックにコピーを行なってくれる)からです。

  archive_command = 'rsync -az --rsh=ssh %p enterprisedb@node1.example.com:/home/enterprisedb/archive/%f'
  archive_timeout = 60

PostgreSQL-8.3 以降では、加えて "archive_mode=true" の記述が必要です

稼動系サーバのデータベースを再起動させ、設定を反映させます。

  [root@node0]# /etc/init.d/edb_8.3R2 stop
  [root@node0]# /etc/init.d/edb_8.3R2 start

WAL ログセグメントが転送されることを確認します。以下のように、ログセグメントを新しいものに切り替える命令を発行します。

  edb=# select pg_switch_xlog();

すると、以下のようにログセグメントが転送されます。

  [enterprisedb@node1]$ ls -l ~/archive/
  合計 16404
  -rw------- 1 enterprisedb edb 16777216 2009-09-04 16:15 000000010000000000000036

4.1 稼動系サーバ上にも WAL ログセグメントを残す設定(オプション)

ローカルに WAL セグメントを保存するディレクトリを作成します。

  [enterprisedb@node0 ~]$ mkdir -p ~/archive/

ローカルにコピーをとりつつ rsync でリモートに送出するコマンドを /opt/PostgresPlus/8.3R2AS/data/postgresql.conf に指定します。

  archive_command = 'cp %p /home/enterprisedb/archive/%f; rsync -az --rsh=ssh %p enterprisedb@node1.example.com:/home/enterprisedb/archive/%f'
  archive_timeout = 60

このままではローカルのアーカイブは、いつまでも消去されません。古いものから削除するよう、cron に tmpwatch(8) コマンドを設定します。tmpwatch(8) コマンドの引数は、時間数であることに気をつけてください(RHEL5 などに含まれる古い tmpwatch は、日数等の postfix を受け付けません)。

  [enterprisedb@node0 ~]$ crontab -e
  05 4 * * * /usr/sbin/tmpwatch 720 /home/enterprisedb/archive/

5. 稼動系サーバで、バックアップモードを開始

  edb=# select pg_start_backup('intial');

ここで出るのは、バックアップを開始した時点での WAL の番号なので、環境によって異なります。"initial" とあるのはバックアップ・ラベルで、/opt/PostgresPlus/8.3R2AS/data/backup_label ファイルに書き出されます。

6. 稼動系サーバから待機系サーバへのデータのコピー

  [enterprisedb@node0]$ rsync -avvr --rsh=ssh --progress \
   --exclude "postmaster.pid" /opt/PostgresPlus/8.3R2AS/data/ \
   enterprisedb@node1.example.com:/opt/PostgresPlus/8.3R2AS/data/

7. 稼動系サーバで、バックアップモードを終了

  edb=# select pg_stop_backup();

アーカイブディレクトリに、".backup" の suffix を持つヒストリファイルが出力されます。

8. 待機系サーバのデータディレクトリの準備

/opt/PostgresPlus/8.3R2AS/data/postgresql.conf の "archive_command" と "archive_timeout" は稼動系にのみ必要な情報なので、これらをコメントアウトしてください。

  #archive_command = 'cp %p /home/enterprisedb/archive/ ...
  #archive_timeout = 60   

注) PostgreSQL-8.3 以降では、"archive_mode" もコメントアウトしてください。

なお、コピーの際に除外したので以下のファイルは存在しないはずですが、一応確認してください。

  [enterprisedb@node1]$ rm -f /opt/PostgresPlus/8.3R2AS/data/postmaster.pid

9. 待機系サーバでのリカバリモード設定

ウォームスタンバイ用の recovery.conf を作成するため、雛形をコピーします。

  [enterprisedb@node1]$ cp -f /opt/PostgresPlus/8.3R2AS/dbserver/share/recovery.conf \
   /opt/PostgresPlus/8.3R2AS/data/recovery.conf

データディレクトリに recovery.conf が存在すると、PPAS はリカバリモードで起動します。リカバリモードとは、DB インスタンス起動に先立って、アーカイブディレクトリにある WAL ログセグメントを読み込んで、ある時点までのデータベースを再構成するモードです。PITR のために、restore_command に単なるコピーコマンドを設定してあれば、必要なセグメントを読み込んで即座に DB インスタンスを起動するのですが、ウォームスタンバイのために pg_standby コマンドを設定をしていると、次のセグメントの到着かトリガを待って pg_standby コマンドが sleep するため、DB インスタンスが起動しないようになります。pg_standby がトリガを検出してリカバリモードが終了すると recovery.conf は rename され、次回起動ではリカバリモードに入らず、通常モードで起動するようになります。

"restore_command" の行を変更してください。pg_standby コマンドはトリガファイルを検出するまでは正常終了しませんので、指示(トリガファイルの配置)があるまでは PPAS をリカバリモードに保持します。

  restore_command = '/opt/PostgresPlus/8.3R2AS/dbserver/bin/pg_standby -s 5 -t /home/enterprisedb/trigger -k 10 /home/enterprisedb/archive/ %f %p'

注) PostgreSQL-8.3 以降では、オプションが若干異なります。適宜ドキュメントを参照してください。

上記の例では、5 秒間の interval でセグメントをフェッチするスタンバイモードに入ります。"%r" をつけるとセグメントを remove するようになり、なくすとセグメントを残すようになります。消さないと、ディスクがすぐに満杯です。

10. 待機系サーバを、warm standby モードで起動

  [root@node1]# /etc/init.d/edb_8.3R2 start

11. 確認

pg_standby のプロセスが動作していることを確認します。

  [enterprisedb@node1 ~]$ ps ax | grep pg_standby
  19558 ?        S      0:00 sh -c /opt/PostgresPlus/8.3R2AS/dbserver/bin/pg_standby -s 5 -t /h ...
  19559 ?        S      0:00 /opt/PostgresPlus/8.3R2AS/dbserver/bin/pg_standby -s 5 -t /home/en ...
  19706 pts/3    S+     0:00 grep pg_standby
  [enterprisedb@node1 ~]$ 

ログセグメントが、順次適用されていることを確認します。

  [enterprisedb@node1 ~]$ tail -f /opt/PostgresPlus/8.3R2AS/data/dbserver_logs/enterprisedb-2009-09-04_145415.log
  2009-09-04 16:23:21 JST LOG:  ログファイル"000000010000000000000037"をアーカイブからリストアしました
  2009-09-04 16:28:22 JST LOG:  ログファイル"000000010000000000000038"をアーカイブからリストアしました
  2009-09-04 16:33:23 JST LOG:  ログファイル"000000010000000000000039"をアーカイブからリストアしました
  2009-09-04 16:38:23 JST LOG:  ログファイル"00000001000000000000003A"をアーカイブからリストアしました
  2009-09-04 16:43:19 JST LOG:  ログファイル"00000001000000000000003B"をアーカイブからリストアしました
  2009-09-04 16:48:20 JST LOG:  ログファイル"00000001000000000000003C"をアーカイブからリストアしました
  2009-09-04 16:53:20 JST LOG:  ログファイル"00000001000000000000003D"をアーカイブからリストアしました
  2009-09-04 16:58:21 JST LOG:  ログファイル"00000001000000000000003E"をアーカイブからリストアしました
  2009-09-04 17:03:21 JST LOG:  ログファイル"00000001000000000000003F"をアーカイブからリストアしました
  2009-09-04 17:08:22 JST LOG:  ログファイル"000000010000000000000040"をアーカイブからリストアしました

以上で、ウォームスタンバイ構成の構築は終了です。


以下は、障害時に関する記述です。

12. 待機系サーバの昇格

稼動系サーバに何らかの不具合が発生したら、待機系サーバの /home/enterprisedb/trigger というファイルを作成することで、pg_standby コマンドはリカバリモードを終了し、稼動系に昇格し、サービスを始めます。以降、こちらのサーバが実サービスを提供します。

13. 新しい待機系の作成

上記 2~11 の手順で、node0 と node1 を読み替えて、現在の稼働系から待機系を新たに作成してください。それぞれのノードの役割を、当初の稼動系と待機系の関係に戻しても良いのですが、手間も余計にかかりますので、特に問題がなければ、昇格したサーバを実運用に使いつつ、新しい待機サーバを構築することをお勧めします。

プリンタ用画面
友達に伝える
ログイン
ユーザー名:

パスワード:



パスワード要求 | 新規登録

検索
メインメニュー
 


Copyright(C) SIOS Technology, Inc. All Rights Reserved