PostgreSQLはストリーミングレプリケーションと呼ばれるデータコピーの仕組みがあります。3台以上のプライマリ/スレーブ構成を紹介し、ストリーミングレプリケーションに関するパラメタについて説明します。
- PostgreSQL インストール
- PostgreSQL データベースの作成
- PostgreSQL contribモジュールの使い方
- PostgreSQL パラメタの設定方法
- PostgreSQL ベンチマークツールの紹介
- PostgreSQL WAL(Write Ahead Log)の基本説明
- PostgreSQL バックアップとリストア
- PostgreSQL PITR(Point In Time Recovery)基本概念の説明
- PostgreSQL PITR(Point In Time Recovery)操作方法の説明
- PostgreSQL PITR(Point In Time Recovery)タイムライン操作
- PostgreSQL ストリーミングレプリケーションの最小構成
- PostgreSQL ストリーミングレプリケーションのパラメタ説明 (いまここ)
- PostgreSQL ストリーミングレプリケーションの障害復旧
- PostgreSQL ストリーミングレプリケーションの多段構成
- PostgreSQL ストリーミングレプリケーションのDR向け設定
- PostgreSQL ストリーミングレプリケーションのコンフリクト
- PostgreSQL 自動バキューム(AUTO VACUUM)
- PostgreSQL HOT(Heap Only Tuple)
- PostgreSQL インデックスのメンテナンス
- PostgreSQL 統計情報の更新
- PostgreSQL 実行計画
- PostgreSQL スロークエリの調査方法
動作確認構成
以下の環境で動作確認を行います。
+----------+ +----------+ | | | | | centos10 +-----+------+ centos11 | | (primary)| | | (standby)| +----------+ | +----------+ 192.168.56.10/24 | 192.168.56.11/24 | | +----------+ | | | +------+ centos12 | | | (standby)| | +----------+ | 192.168.56.12/24 | | +----------+ | | | +------+ centos13 | | (standby)| +----------+ 192.168.56.13/24
パラメタ解説
synchronous_commit
PostgreSQLはWALログが転送されたかどうかを確認してから処理を完了させるかどうかを指定する事ができます。
例えば、あるアプリケーションがWALをスタンバイに転送する前に決済完了処理を完了させてしまうと、プライマリ障害時に決済処理が失われてしまいます。このような厳密なトランザクションを管理するような処理は、必ずスタンバイへの転送を待ってから処理完了する必要があります。他方、ディザスタリカバリのような要件で東データセンターから西データセンターにレプリケーションするような場合では、WAL転送を待つのは大きな性能劣化となってしまいます。
このようにWALをどこまで処理されるのを待ってからCOMMITするかを指定するパラメタがsynchronous_commitです。synchronous_commitに指定できるパラメタを以下にまとめます。データロスを防ぎたいならば、デフォルト設定のremote_write以上にする必要があります。
指定値 | プライマリのWAL処理 | スタンバイのWAL処理 |
---|---|---|
off | 待たない | 待たない |
local | 待つ | 待たない |
remote_write | 待つ | メモリ書き込みまで待つ |
on | 待つ | ディスク書き込みまで待つ |
remote_apply | 待つ | WALが適用されるまで待つ |
synchronous_standby_names
synchronous_standby_namesには複数台のスタンバイサーバを指定する事ができます。前述のsynchronous_commitは全てのスタンバイサーバのWALが処理されるのを待つのではなく、一部サーバのWALが処理されるのを待つような指定もできます。
FIRSTという指定をすると、先頭に記述したサーバのWALの処理を待つ挙動になります。例えば、以下のような記述の場合は、centos11, centos12の処理が終わるまでを待ちます。
synchronous_standby_names = 'FIRST 2 (centos11,centos12,centos13)'
ANYという指定をすると、一部サーバのWALの処理を待つ起動になります。例えば、以下のような記述の場合は、centos11, centos12,centos13のうち2台の処理が終わるまでを待ちます。
synchronous_standby_names = 'ANY 2 (centos11,centos12,centos13)'
正常系動作確認
マスターサーバの構築
postgresql.confおよびpg_hba.confに以下を加筆します。スタンバイ機は3台構成とし、そのうち2台まではWALが同期している状態とします。
cat << EOF >> /var/lib/pgsql/13/data/postgresql.conf listen_addresses = '0.0.0.0' max_wal_senders = 10 synchronous_commit = 'remote_write' synchronous_standby_names = 'ANY 2 (centos11,centos12,centos13)' EOF cat << EOF >> /var/lib/pgsql/13/data/pg_hba.conf host replication postgres 192.168.56.0/24 trust EOF
再起動し設定を反映させます。
systemctl restart postgresql-13.service
スタンバイサーバの構築
pg_basebackupコマンドを使用して、プライマリサーバのデータを1台目スタンバイサーバへコピーします。
[ -n "${PGDATA}" ] && rm -rf ${PGDATA}/* pg_basebackup -R -D ${PGDATA} -h 192.168.56.10
[ -n "${PGDATA}" ] && rm -rf ${PGDATA}/* rsync -av root@192.168.56.11:/var/lib/pgsql/13/data/ ${PGDATA}
[ -n "${PGDATA}" ] && rm -rf ${PGDATA}/* rsync -av root@192.168.56.11:/var/lib/pgsql/13/data/ ${PGDATA}
postgresql.auto.confのsynchronous_standby_namesにapplication_nameを加筆します。application_nameの値はスタンバイ機によって適宜変更してください。
# vi /var/lib/pgsql/13/data/postgresql.auto.conf primary_conninfo = 'user=postgres <omitted> application_name=centos11'
# vi /var/lib/pgsql/13/data/postgresql.auto.conf primary_conninfo = 'user=postgres <omitted> application_name=centos12'
# vi /var/lib/pgsql/13/data/postgresql.auto.conf primary_conninfo = 'user=postgres <omitted> application_name=centos13'
postgresql.confのプライマリ固有の設定をコメントアウトします。
# vi /var/lib/pgsql/13/data/postgresql.conf #listen_addresses = '0.0.0.0' #max_wal_senders = 10 #synchronous_commit = 'remote_write' #synchronous_standby_names = 'ANY 2 (centos11,centos12,centos13)'
postgresqlを起動し、レプリケーションを開始します。
systemctl start postgresql-13.service
レプリケーションが開始された旨のログを確認します。
[root@centos11 ~]# tail -n 3 /var/lib/pgsql/13/data/log/postgresql-Fri.log 2020-12-25 23:43:33.141 JST [1531] LOG: 0/4000100 でリカバリの一貫性が確保されました 2020-12-25 23:43:33.141 JST [1528] LOG: データベースシステムはリードオンリー接続の受け付け準備ができました 2020-12-25 23:43:33.238 JST [1535] LOG: プライマリのタイムライン1の 0/5000000からでWALストリーミングを始めます
[root@centos12 ~]# tail -n 3 /var/lib/pgsql/13/data/log/postgresql-Fri.log 2020-12-25 23:43:37.835 JST [1017] LOG: 0/4000100 でリカバリの一貫性が確保されました 2020-12-25 23:43:37.836 JST [1014] LOG: データベースシステムはリードオンリー接続の受け付け準備ができました 2020-12-25 23:43:37.978 JST [1021] LOG: プライマリのタイムライン1の 0/5000000からでWALストリーミングを始めます
[root@centos13 ~]# tail -n 3 /var/lib/pgsql/13/data/log/postgresql-Fri.log 2020-12-25 23:43:40.011 JST [1022] LOG: 0/4000100 でリカバリの一貫性が確保されました 2020-12-25 23:43:40.012 JST [1019] LOG: データベースシステムはリードオンリー接続の受け付け準備ができました 2020-12-25 23:43:40.165 JST [1026] LOG: プライマリのタイムライン1の 0/5000000からでWALストリーミングを始めます
動作確認
pgbenchを用いて、動作確認目的の更新処理を発生させます。
createdb test /usr/pgsql-13/bin/pgbench -i test /usr/pgsql-13/bin/pgbench -c 5 -t 100 test
pg_stat_replicationテーブルを参照すると、ストリーミングレプリケーションの対象と進捗を確認する事ができます。
以下出力の場合は、3レコードが現れていますので、3台のスタンバイ機へWALが転送されている事が分かります。
[postgres@centos10 ~]$ psql << EOF > \x > SELECT * FROM pg_stat_replication; > EOF Expanded display is on. -[ RECORD 1 ]----+------------------------------ pid | 5043 usesysid | 10 usename | postgres application_name | centos11 client_addr | 192.168.56.11 client_hostname | client_port | 54554 backend_start | 2020-12-25 22:43:08.465588+09 backend_xmin | state | streaming sent_lsn | 0/5CC3AA0 write_lsn | 0/5CC3AA0 flush_lsn | 0/5CC3AA0 replay_lsn | 0/5CC3AA0 write_lag | flush_lag | replay_lag | sync_priority | 1 sync_state | quorum reply_time | 2020-12-25 23:45:11.354132+09 -[ RECORD 2 ]----+------------------------------ pid | 5044 usesysid | 10 usename | postgres application_name | centos12 client_addr | 192.168.56.12 client_hostname | client_port | 50706 backend_start | 2020-12-25 22:43:13.635872+09 backend_xmin | state | streaming sent_lsn | 0/5CC3AA0 write_lsn | 0/5CC3AA0 flush_lsn | 0/5CC3AA0 replay_lsn | 0/5CC3AA0 write_lag | flush_lag | replay_lag | sync_priority | 1 sync_state | quorum reply_time | 2020-12-25 23:45:11.319904+09 -[ RECORD 3 ]----+------------------------------ pid | 5045 usesysid | 10 usename | postgres application_name | centos13 client_addr | 192.168.56.13 client_hostname | client_port | 54518 backend_start | 2020-12-25 22:43:15.965+09 backend_xmin | state | streaming sent_lsn | 0/5CC3AA0 write_lsn | 0/5CC3AA0 flush_lsn | 0/5CC3AA0 replay_lsn | 0/5CC3AA0 write_lag | flush_lag | replay_lag | sync_priority | 1 sync_state | quorum reply_time | 2020-12-25 23:45:11.301869+09 [postgres@centos10 ~]$
障害系 スタンバイ1台目の障害
スタンバイ機のうち1台目を停止します。
systemctl stop postgresql-13.service
1台の障害では充分障害に書き込み処理が成功する事を確認します。
/usr/pgsql-13/bin/pgbench -c 5 -t 10 test
pg_stat_replicationを見ると、レコードが2つしかなく、2台のみにレプリケーションしている事が分かります。
[postgres@centos10 ~]$ psql << EOF > \x > SELECT * FROM pg_stat_replication; > EOF Expanded display is on. -[ RECORD 1 ]----+------------------------------ pid | 5044 usesysid | 10 usename | postgres application_name | centos12 client_addr | 192.168.56.12 client_hostname | client_port | 50706 backend_start | 2020-12-25 22:43:13.635872+09 backend_xmin | state | streaming sent_lsn | 0/5CD2568 write_lsn | 0/5CD2568 flush_lsn | 0/5CD2568 replay_lsn | 0/5CD2568 write_lag | 00:00:00.000724 flush_lag | 00:00:00.003386 replay_lag | 00:00:00.003392 sync_priority | 1 sync_state | quorum reply_time | 2020-12-25 23:45:54.367778+09 -[ RECORD 2 ]----+------------------------------ pid | 5045 usesysid | 10 usename | postgres application_name | centos13 client_addr | 192.168.56.13 client_hostname | client_port | 54518 backend_start | 2020-12-25 22:43:15.965+09 backend_xmin | state | streaming sent_lsn | 0/5CD2568 write_lsn | 0/5CD2568 flush_lsn | 0/5CD2568 replay_lsn | 0/5CD2568 write_lag | 00:00:00.001292 flush_lag | 00:00:00.003343 replay_lag | 00:00:00.003347 sync_priority | 1 sync_state | quorum reply_time | 2020-12-25 23:45:54.340801+09 [postgres@centos10 ~]$
スタンバイ2台目の障害
スタンバイ機のうち2台目を停止します。
systemctl stop postgresql-13.service
動作確認のため簡単なSQL文を発行してみます。すると、ハングアップしていつまでも処理が完了しません。
Ctrl+Cでキャンセルすると、スタンバイ側にレプリケーションされていない可能性がある旨の警告が現れます。
[postgres@centos10 ~]$ psql -c "CREATE DATABASE test2" ^CCancel request sent WARNING: ユーザからの要求により同期レプリケーションの待ち状態をキャンセルしています DETAIL: トランザクションはローカルではすでにコミット済みですが、スタンバイ側にはレプリケーションされていない可能性があります。 CREATE DATABASE [postgres@centos10 ~]$