どうも、俺です。
pgpool-2でオンラインリカバリを試したのでその方法をメモ。
若干ややこしかった...。
【環境】
・postgresql v9.5.3
・pgpool-2 v3.5.4
・ノード1のあるサーバー 192.168.0.1
・ノード2のあるサーバー 192.168.0.2
・pgpool-2のあるサーバー 192.168.0.1
※PostgreSQLとpgpool-2はすでに稼働中とします。
※pgpool-2の
公式HP参照
手順1) C言語関数インストール
各ノードのPostgreSQLデータベースに関数をインストールします。
すべてのノードのあるサーバーで以下を行います。
# su - postgres
% cd /path/to/pgpool-II-3.5.4/src/sql/pgpool-recovery
% make install
% psql -p ポート番号 -f pgpool-recovery.sql template1
手順2) pgpool.confの設定
オンラインリカバリを行うための設定を追加します。
# vim /path/to/pgpool/etc/pgpool.conf
--- 以下pgpool.conf内容 ---
# PCPの設定
pcp_listen_addresses = '*'
pcp_port = 9898
pcp_socket_dir = '/tmp'
# リカバリを行うPostgreSQLのユーザとパスワード。
recovery_user = 'postgres'
recovery_password = 'postgres'
# オンラインリカバリを実行するスクリプト名。
recovery_1st_stage_command = 'recovery_1st_stage.sh'
recovery_2nd_stage_command = 'recovery_2nd_stage.sh'
# オンラインリカバリのタイムアウト秒数。
recovery_timeout = 120
# リカバリ中にアイドル状態のクライアントを何秒で切断するか。0は無効。-1は即時切断。
client_idle_limit_in_recovery = 1
手順3) postgresql.confの設定
archive_logを取るように設定します。
既に設定済みであれば不要です。
# vim /path/to/pgsql/data/postgresql.conf
--- 以下postgresql.confの内容 ---
archive_mode = on
# /usr/local/pgsql/data/archive というディレクトリ以下にarchive_logがコピーされる
archive_command = 'cp %p /usr/local/pgsql/data/archive/%f'
手順4) リカバリスクリプトの作成
・recovery_1st_stage.sh
・recovery_2st_stage.sh
・pgpool_remove_start
の3ファイルを作成します。
pgpoolレプリケーションモード | PostgreSQL関連情報のスクリプトを使わせて頂きました。ありがとうございます。
recovery_1st_stage.sh
#!/bin/sh
PSQL="/usr/local/pgsql/bin/psql"
PORT=5432
MASTER_BASEDIR=$1
RECOVERY_HOST=$2
RECOVERY_BASEDIR=$3
$PSQL -p $PORT -c "SELECT pg_start_backup('pgpool-recovery')" postgres
echo "restore_command = 'cp /usr/local/pgsql/data/archive/%f %p'" > $MASTER_BASEDIR/recovery.conf
ssh -l postgres -T $RECOVERY_HOST rm -rf $RECOVERY_BASEDIR.bk
ssh -l postgres -T $RECOVERY_HOST mv -f $RECOVERY_BASEDIR{,.bk}
rsync -az -e ssh -l postgres $MASTER_BASEDIR/ $RECOVERY_HOST:$RECOVERY_BASEDIR/
ssh -l postgres -T $RECOVERY_HOST cp -f $RECOVERY_BASEDIR.bk/postgresql.conf $RECOVERY_BASEDIR
ssh -l postgres -T $RECOVERY_HOST rm -f $RECOVERY_BASEDIR/postmaster.pid
rm -f $MASTER_BASEDIR/recovery.conf
$PSQL -p $PORT -c "SELECT pg_stop_backup()" postgres
recovery_2nd_stage.sh
#!/bin/sh
PSQL="/usr/local/pgsql/bin/psql"
PORT=5432
ARCHIVEDIR=/usr/local/pgsql/data/archive/
MASTER_BASEDIR=$1
RECOVERY_HOST=$2
RECOVERY_BASEDIR=$3
$PSQL -p $PORT -c 'SELECT pg_switch_xlog()' postgres
rsync -az -e ssh -l postgres $ARCHIVEDIR $RECOVERY_HOST:$ARCHIVEDIR
pgpool_remove_start
#! /bin/sh
PGCTL=/usr/local/pgsql/bin/pg_ctl
RECOVERY_HOST=$1
RECOVERY_BASEDIR=$2
ssh -l postgres -T $RECOVERY_HOST $PGCTL -w -D $RECOVERY_BASEDIR start 2>/dev/null 1> /dev/null < /dev/null &
これら3ファイルに実行権限を付けて、各ノードサーバーのデータディレクトリ以下に配置します。
以上で、オンラインリカバリの準備は完了です。
では実際にオンラインリカバリを試してみます。
オンラインリカバリを行うには、いずれかのノードサーバーがpgpool側で異常検知されている必要があります。
今回は192.168.0.2のPostgreSQLを止めてからオンラインリカバリをしてみます。
% /usr/local/pgsql/bin/pg_ctl -D /path/to/pgsql/data stop
% /usr/local/pgsql/bin/psql -p 9999 // ←pgpoolへ接続
postgres=# show pool_nodes;
node_id | hostname | port | status | lb_weight | role | select_cnt
---------+--------------+------+--------+-----------+--------+------------
0 | 192.168.0.1 | 5432 | 2 | 0.500000 | master | 1200
1 | 192.168.0.2 | 5432 | 3 | 0.500000 | slave | 884
(2 rows)
192.168.0.2が停止しています。
この状態で、pcp_recovery_nodeコマンドでオンラインリカバリを行います。
% /path/to/pgpool/bin/pcp_recovery_node -h 192.168.0.1 -p 9898 -U postgres -n 1
-h ... PCP(pgpool Communication Manager Connection)の稼働ホスト?
-p ... PCPの稼働ポート
-U ... pgpoo.confに記したrecovery_user名
-n ... 何番のノードを起動させるか。今回はnode_id=1の192.168.0.2
以上で、問題なければオンラインリカバリが成功するはずです。
ただ、オンラインリカバリを行うのは意外と時間かかる場合があるので気長に待つ必要も大切です。
【実際に試してみた】
サービス稼働中を模して、
無限ループでINSERTさせながらオンラインリカバリをやってみました。
...が、ターミナル上はSuccess!と出たのですが、
実際にデータを確認してみると2件レコードのズレがありました...。
やはり、データ誤差が出た場合は一旦サービス止めてdata/ディレクトリ丸ごとコピーの方が安全なのでしょうか。。?
以上でぇぇぇぇす!