構成 †
ユーザ †
ディレクトリ †
$HOME (/home/postgres)
|
+-- master (マスタのDBクラスタ)
|
+-- standby (スタンバイのDBクラスタ)
|
+-- pgsql (9.0beta4のインストール先)
※$HOME/pgsql/bin は PATH に登録済
- 同一マシン上にマスタとスタンバイをセットアップする
ネットワーク †
- ポート番号はマスタが 5432、スタンバイが 9999
スクリプト †
- setup_master_and_standby.sh
- monitor_postgres.sh
- postgres プロセスをリアルタイムに表示し続けるスクリプト
- ターミナルを1つプロセス表示用に割り当て、ずっと monitor_postgres.sh を走らせておくと便利
- make_conflict.sh
- スタンバイでリカバリと SQL の競合を発生させるスクリプト
- check_progress.sh
1. セットアップ †
1-1. DBクラスタの作成 †
1-2. マスタのパラメータ設定 †
1-3. マスタの認証設定 †
1-4. マスタの起動 †
- マスタで PostgreSQL を通常と同じように起動
$ pg_ctl -D master start
1-5. バックアップの取得 †
1-6. スタンバイのパラメータ設定 (postgresql.conf 編) †
1-7. スタンバイのパラメータ設定 (recovery.conf 編) †
1-8. フェイルオーバ後を意識した設定 †
- フェイルオーバによってスタンバイがマスタになった後のことまで考えて pg_hba.conf 等を設定すべき
1-9. スタンバイの起動 †
2. レプリケーションの使用 †
2-1. レプリケーションのお試し †
- データベースが複製されることを確認
- マスタの SQL 結果がスタンバイに複製されることの確認
$ psql -p5432
=# CREATE TABLE tbl (id int);
=# INSERT INTO tbl VALUES (1), (2); ※データを2件INSERT
=# SELECT * FROM tbl; ※tblテーブルにデータが2件あることを確認
=# \q
$ psql -p9999
=# \d ※テーブル一覧でtblテーブルがあることを確認
=# SELECT * FROM tbl; ※tblテーブルにデータが2件あることを確認
- 更新SQLがスタンバイで失敗することの確認
=# INSERT INTO tbl VALUES (3);
ERROR: cannot execute INSERT in a read-only transaction
=# \q
- スタンバイで pg_dump のバックアップを取得できることの確認
$ pg_dump -p9999 -t tbl
- テーブル tbl に関係するものだけダンプ
- ダンプ結果に tbl テーブルの作成と、データ2件の COPY があることを確認
2-2. 進捗の確認 †
2-3. スタンバイの停止と再起動 †
- スタンバイをスマート・シャットダウンできることを確認
- 8.4 以前の warm-standby 構成では、スマート・シャットダウンではスタンバイは停止しない
- スタンバイへの接続
###### Terminal 1 ######
$ psql -p9999
- スタンバイの停止
###### Terminal 2 ######
※上記 psql とは別ターミナルから以下を実施
$ pg_ctl -D standby -m s stop
- pg_ctl によるシャットダウンのデフォルトはスマート・シャットダウンなので、-m s の付与は冗長
- スタンバイへの接続の終了
###### Terminal 1 ######
=# \q
- スタンバイの起動
$ pg_ctl -D standby start
- どの位置からレプリケーションを再開すればよいかスタンバイは情報を持っているため、再起動するだけで自動的に前回の続きからレプリケーションが再開される
- レプリケーションの成功の確認
2-4. フェイルオーバ †
- マスタを停止して、フェイルオーバ
$ pg_ctl -D master stop
$ touch trigger
- 作成したトリガファイルは、切替時に PostgreSQL が自動的に削除
- スタンバイがマスタに切り替わったことを、以下のサーバログが出ていることで確認
[standby] LOG: database system is ready to accept connections
- 新しいマスタに接続して、更新SQLが実行できることを確認
$ psql -p9999
=# INSERT INTO tbl VALUES (3);
=# SELECT * FROM tbl; ※tblテーブルにデータが3件あることを確認
=# \q
2-5. 再組み込み †
- 再組み込みのために旧マスタのDBクラスタを削除
$ rm -rf master
- バックアップの取得
$ psql -p 9999 -c "SELECT pg_start_backup('test', true)"
$ cp -r standby master
$ psql -p 9999 -c "SELECT pg_stop_backup()"
- 新スタンバイ(旧マスタ)の postgresql.conf の設定
$ $EDITOR master/postgresql.conf
port = 5432
hot_standby = on
log_line_prefix = '[master] '
- 新スタンバイ(旧マスタ)の recovery.conf の設定
$ $EDITOR master/recovery.conf
standby_mode = 'on'
primary_conninfo = 'host=127.0.0.1 port=9999 user=postgres'
trigger_file = '../trigger'
- 同一マシン上で複数インスタンスを起動するための処置
$ rm -f master/postmaster.pid
- 新スタンバイ(旧マスタ)のPostgreSQLの起動
$ pg_ctl -D master start
- レプリケーションの成功の確認
3. 注意が必要な挙動 †
3-1. リカバリと SQL の競合の確認 †
- スタンバイで、「マスタから転送された WAL のリカバリ処理」と「SQL 処理」が競合することを確認
- 以下の操作が面倒な場合は make_conflict.sh を実行すること
- 初期データを作成する
###### Terminal 1 ######
$ psql -p5432
=# CREATE TABLE tbl (id int);
=# INSERT INTO tbl VALUES (1), (2); ※データを2件INSERT
- 別ターミナルから、スタンバイでデータ2件を参照する処理時間の長い SQL を実行
###### Terminal 2 ######
$ psql -p9999 -c"SELECT pg_sleep(3600) FROM tbl"
- テーブル tbl を参照した上で、3600 秒スリープする SQL
- 初期データを作成したターミナルで、データの削除と VACUUM を実施
###### Terminal 1 ######
=# DELETE FROM tbl;
=# VACUUM tbl;
=# \q
- マスタの VACUUM の WAL がスタンバイに転送されて、スタンバイはリカバリでデータ2件を完全に削除しようとする
- しかし、スタンバイの SELECT 文はまだデータ2件を参照する可能性があるため、データの削除を待たせる
- ps の結果からリカバリが競合で処理を待たされていることを確認
$ pgrep -fl postgres
- startup process に waiting が付与されており、競合の発生を示す
- 30秒程度後に ERROR が発生して、スタンバイで SQL がキャンセルされたことを確認
ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.
3-2. 競合によるリカバリの遅れを確認 †