Skip to main content
© 2020 NTT DATA Corporation 1 © 2020 NTT DATA Corporation
オープンソースカンファレンス2020 Online/Fall
祝!PostgreSQLレプリケーション10周年!徹底紹介!!
2020年10月23日
株式会社NTTデータ 藤井雅雄 @fujii_masao
© 2020 NTT DATA Corporation 22© 2020 NTT DATA Corporation
自己紹介
藤井 雅雄
Database Technical Lead @ NTTデータ
データベース研究開発
PostgreSQL 技術支援
PostgreSQLコミッタ
レプリケーション
WAL圧縮、バックアップ進捗
pg_bigm(全文検索モジュール)コミッタ
@fujii_masao
© 2020 NTT DATA Corporation 3
PostgreSQL13でも利用可能な全文検索モジュールpg_bigm
pg_bigm
https://pgbigm.osdn.jp/
https://github.com/pgbigm/pg_bigm
PostgreSQL上で全文検索機能を提供するOSSモジュール
「OSS」を含むタイトルの書籍情報を検索したい!
SELECT * FROM book WHERE title LIKE ‘%OSS%’
シーケンシャル
スキャン
インデックス
スキャン
pg_bigm導入で高速に! 通常、インデックス使えず低速
宣伝
© 2020 NTT DATA Corporation 4
本講演について
講演資料は、NTTデータのSlideShareアカウント上で公開済です。
https://www.slideshare.net/nttdata-tech
特に断りのないかぎり、講演で取り上げる機能や仕様は PostgreSQL 13 の
ものになります。
© 2020 NTT DATA Corporation 5
アジェンダ
レプリケーションとは
ストリーミングレプリケーションの基本
ストリーミングレプリケーションの非同期・同期
スタンバイでのSQL実行
ストリーミングレプリケーションの監視
PostgreSQL12以降でストリーミングレプリケーションを使うときの注意
最後に
© 2020 NTT DATA Corporation 6
レプリケーションとは
© 2020 NTT DATA Corporation 7
レプリケーションとは?
クライアントクライアント
更新更新
DBサーバ
更新
複製
DBサーバ
更新
中継サーバ
複数のサーバにデータベースを自動的に複製する機能
© 2020 NTT DATA Corporation 8
なぜレプリケーションが必要か?
24時間365日システムを安定運用するのに必要!
高可用性
負荷分散
1台が故障しても、別サーバが処理を引き継げる
システム全体としてDBサービスが停止するのを回避できる
SQL実行の負荷を複数のサーバに分散できる
負荷が一箇所に集中しないので、システム全体として性能向上できる
クライアントクライアント
SQL SQLSQL
高可用 負荷分散
DBサーバ DBサーバ
© 2020 NTT DATA Corporation 9
PostgreSQLで利用可能なレプリケーション
ストリーミングレプリケーション (物理レプリケーション)
2010年リリースのPostgreSQL9.0から利用可能
ロジカルレプリケーション (論理レプリケーション)
2017年リリースのPostgreSQL10から利用可能
PostgreSQL関連製品によるレプリケーション
例えば、pgpool-II、Slonyなど
その他製品によるレプリケーション
例えば、DRBDのディスク同期によるレプリケーションなど
© 2020 NTT DATA Corporation 10
PostgreSQLで利用可能なレプリケーション
ストリーミングレプリケーション (物理レプリケーション)
2010年リリースのPostgreSQL9.0から利用可能
ロジカルレプリケーション (論理レプリケーション)
2017年リリースのPostgreSQL10から利用可能
PostgreSQL関連製品によるレプリケーション
例えば、pgpool-II、Slonyなど
その他製品によるレプリケーション
例えば、DRBDのディスク同期によるレプリケーションなど
今回は、10周年記念の
ストリーミングレプリケーション
について徹底紹介します!
© 2020 NTT DATA Corporation 11
ストリーミングレプリケーションの基本
© 2020 NTT DATA Corporation 12
プライマリ・スタンバイ方式
クライアントクライアント
DBサーバ
複製
プライマリ
中継サーバ
スタンバイ
プライマリでのデータベースの更新結果をスタンバイにレプリケーション(複製)
 プライマリでは、更新SQLと参照SQLを実行可能
 スタンバイでは、参照SQLのみ実行可能
更新SQL
参照SQL
参照SQL更新SQL
参照SQL
更新SQL
参照SQL
更新SQL
参照SQL
プライマリ・スタンバイ方式
© 2020 NTT DATA Corporation 13
シングルプライマリ・マルチスタンバイ構成
プライマリは1台のみ、スタンバイは複数台
 更新SQLを実行可能なプライマリは1台のみのため、更新スケールアウトには使えない
 参照SQLを実行可能なスタンバイは複数台構成できるため、参照スケールアウトには使える
複製
参照と更新
プライマリ スタンバイ1 スタンバイ2 スタンバイ3
複製
複製
参照のみ 参照のみ 参照のみ
© 2020 NTT DATA Corporation 14
カスケードレプリケーション
スタンバイからスタンバイへのレプリケーションが可能
 プライマリに直接接続のスタンバイ台数を減らすことで、プライマリの負荷を低減できる
プライマリ
マルチスタンバイ マルチスタンバイ
複製 複製
クライアント
複製
© 2020 NTT DATA Corporation 15
ログシッピング
プライマリは、データベースの変更情報としてトランザクションログ(WAL)をスタンバイに転送
 スタンバイは、転送されたWALをリカバリすることでデータベースを複製
 プライマリとスタンバイのデータベースの内容は物理的に同じ
⑤リカバリ
プライマリ スタンバイ
クライアント①更新SQL
②WAL書込
③WAL転送
④WAL書込
© 2020 NTT DATA Corporation 16
ログシッピングのアーキテクチャ
walsender walreceiver startup
データベース
クライアント
②変更
③書き込み
WAL WAL
⑤読み込み
⑥WAL転送
⑦書き込み ❾読み込み
❿リカバリ
⓬参照
①更新Tx ⓫参照Tx
backendbackendbackend
backendbackendbackend
プライマリ スタンバイ
データベース
ディスク領域メモリ領域プロセス
凡例
⑩応答
⑨応答 ⑧応答
④通知
❽通知
⓭結果
© 2020 NTT DATA Corporation 17
ログシッピングによるストリーミングレプリケーションの制約
プライマリとスタンバイで以下2点が同じでなければならない
① ハードウェアやOSのアーキテクチャ
② PostgreSQLのメジャーバージョン
➡ 異なる環境間のレプリケーションにはロジカルレプリケーションを利用
プライマリ
スタンバイ
64ビットOS
PostgreSQL12.0
PostgreSQL11.0
32ビットOS
64ビットOS
PostgreSQL12.1
NG
NG
OK
© 2020 NTT DATA Corporation 18
データベースクラスタ単位のレプリケーション
すべてのデータベースオブジェクトが基本的にレプリケーション対象
 テーブル単位のレプリケーション指定は不可
 テーブル単位のレプリケーションにはロジカルレプリケーションを利用
データベースクラスタ単位 テーブル単位
プライマリ スタンバイ プライマリ スタンバイ
© 2020 NTT DATA Corporation 19
スタンバイのプライマリへの昇格
 スタンバイはいつでもプライマリに昇格可能
 新しいスタンバイをいつでも構成に組み込むことが可能
プライ
マリ
スタン
バイ
レプリケーション構成
スタンバイ単独
停止 スタン
バイ
停止 プライ
マリ
プライマリ単独
プライマリ故障
プライマリへの昇格
スタンバイ
再組み込み
プライ
マリ
レプリケーション構成
スタン
バイ
© 2020 NTT DATA Corporation 20
スタンバイのプライマリへの昇格
 スタンバイはいつでもプライマリに昇格可能
 新しいスタンバイをいつでも構成に組み込むことが可能
プライ
マリ
スタン
バイ
レプリケーション構成
スタンバイ単独
停止 スタン
バイ
停止 プライ
マリ
プライマリ単独
プライマリ故障
プライマリへの昇格
スタンバイ
再組み込み
プライ
マリ
レプリケーション構成
スタン
バイ
© 2020 NTT DATA Corporation 21
フェイルオーバ
PostgreSQLは自動的なフェイルオーバ機能を提供しない
• 自動的なフェイルオーバにはクラスタソフトと要連携
クライアントクライアント
プライマリ
pgpool-II
スタンバイプライマリ スタンバイ
Pacemaker pgpool-II
VIP
© 2020 NTT DATA Corporation 22
PG-REX
PostgreSQLの同期レプリケーションにPacemakerを組み合わせた高可用ソリューション
• NTT OSSセンタが、PG-REXの設定・運用のための利用マニュアルや補助ツールなどを公開
https://ja.osdn.net/projects/pg-rex/
クライアント
プライマリ スタンバイ
PG-REX
VIP
同期
© 2020 NTT DATA Corporation 23
簡単セットアップ
手軽にシングルサーバ内でレプリケーション構成をセットアップ可能
プライマリをセットアップ
initdb -D data
pg_ctl -D data start
※プライマリに必要な最低限のパラメータはデフォルトで有効化
スタンバイをセットアップ
pg_basebackup -D sby –R
echo “port = 9999” >> sby/postgresql.conf
pg_ctl -D sby start
※-Rオプションにより、バックアップ取得時に、スタンバイに必要なパラメータも自動的に設定
※同一サーバ内で2インスタンス起動するため、片方のportを変更する必要がある
© 2020 NTT DATA Corporation 24
ストリーミングレプリケーションの
非同期・同期
© 2020 NTT DATA Corporation 25
非同期・同期レプリケーションの概要
プライマリ
プライマリ
スタンバイ
スタンバイ
クライアント
クライアント
非同期はスタンバイへのレプリケーション完了を待たない
同期はスタンバイへのレプリケーション完了を待つ
①更新
②複製
③成功応答
④複製完了
①更新
②複製
③複製完了
④成功応答
© 2020 NTT DATA Corporation 26
同期レプリケーション
COMMIT時にレプリケーションの完了を待つ
 COMMIT成功時にWALがプライマリ・スタンバイ両方に書き込み済と保証
 フェイルオーバ時にCOMMIT済データを失わない!
 レプリケーション完了を待つので比較的低性能
リカバリ
プライマリ スタンバイ
クライアント①COMMIT
②WAL書込
③WAL転送
④WAL書込
⑥OK
⑤応答
© 2020 NTT DATA Corporation 27
非同期レプリケーション
COMMIT時にレプリケーションの完了を待たない
 COMMIT成功時にWALがスタンバイに届いている保証なし
 フェイルオーバ時にCOMMIT済データを失う可能性あり
 レプリケーション完了を待たないので比較的高性能!
⑥リカバリ
プライマリ
スタンバイ
クライアント①COMMIT
②WAL書込
④WAL転送
⑤WAL書込
③OK
③と④の間で
フェイルオーバが発生すると、
COMMIT済データを失う
© 2020 NTT DATA Corporation 28
非同期・同期レプリケーションの使い分け例
同期プライマリ
高可用向けスタンバイ
負荷分散向けスタンバイ
災対向けスタンバイ
非同期 非同期
フェイルオーバ時に
データを失わないように、
高可用向けには
同期レプリケーションを利用
データセンタ(ローカル) データセンタ(遠隔地)
更新SQL
参照SQL
少し古いデータを参照できれば十分であれば、
負荷分散向けには性能オーバーヘッドの小さい
非同期レプリケーションを利用
参照SQL
クライアント
遠隔へのレプリケーションを待つと
性能が大幅劣化するため、
災対向けには非同期レプリケーションを利用
災対向けスタンバイ
非同期
© 2020 NTT DATA Corporation 29
synchronous_standby_names
どのスタンバイを同期レプリケーションの対象とするかは synchronous_standby_names で設定
synchronous_standby_names = '[FIRST | ANY ] NUM (NAME1, NAME2, ...)‘
同期スタンバイの台数 同期スタンバイの名前のリスト同期スタンバイを選ぶ方式
オンラインでいつでも
設定変更可能
© 2020 NTT DATA Corporation 30
synchronous_standby_namesの設定例1
synchronous_standby_names = 'FIRST 2 (S1, S2, S3)'
現在稼働中のスタンバイから、S1、S2、S3の優先順位で2台を同期スタンバイとして選ぶ
プライマリ
S1
S2
S3
スタンバイ
同期
非同期
同期 優先度の高いS1とS2が
同期スタンバイとして
選ばれる
© 2020 NTT DATA Corporation 31
synchronous_standby_namesの設定例2
synchronous_standby_names = 'ANY 2 (S1, S2, S3)'
S1、S2、S3のスタンバイのうち少なくとも2台にレプリケーションが完了するのを待つ
プライマリ
S1
S2
S3
スタンバイ
同期かも
S1~S3のどれか2台に
レプリケーションが
完了するまで待つ
同期かも
同期かも
© 2020 NTT DATA Corporation 32
FIRSTとANYの使い分け
同期
同期 S1
S2
S1
S2
同期かも
同期かも
非同期 S3
スタンバイ
プライ
マリ
S3同期かも
スタンバイ
プライ
マリ
FIRST
 同期レプリケーションのスタンバイを固定したい
 同期スタンバイに全体性能が引きずられる
ANY
 特定スタンバイに全体性能が引きずられるのを避け
たい
 同期スタンバイは固定化できない
© 2020 NTT DATA Corporation 33
synchronous_standby_namesの設定例3
1台のスタンバイ S1 に対して同期レプリケーションを設定
synchronous_standby_names = 'FIRST 1 (S1)' または 'ANY 1 (S1)'
プライマリ スタンバイ
同期
S1
© 2020 NTT DATA Corporation 34
synchronous_commit
synchronous
_commit
プライマリ スタンバイ
WAL書込(write+fsync) WAL書込(write) WAL書込(fsync) リカバリ
off 待たない 待たない 待たない 待たない
local 待つ 待たない 待たない 待たない
remote_write 待つ 待つ 待たない 待たない
on 待つ 待つ 待つ 待たない
remote_apply 待つ 待つ 待つ 待つ
⑥リカバリプライマリ スタンバイクライアント
②WAL書込
(write+fsync)
③WAL転送
④WAL書込(write)
応答
⑤WAL書込(fsync)
高性能
保護レベル高
①COMMIT
OK
synchronous_commitで同期レプリケーションのレベルを細かく設定可能
© 2020 NTT DATA Corporation 35
遅延レプリケーション
recovery_min_apply_delayの指定時間だけ、スタンバイによるWALのリカバリを遅延させられる
 重要なテーブルのTRUNCATEなどオペミスがプライマリで発生したとき、スタンバイでリカバリを遅延され
ている間に何らかの対処が可能
 synchronous_commit=remote_applyの場合は、レプリケーションはリカバリの遅延分まで待
つことになる
プライマリ スタンバイクライアント
WAL書込
WAL転送
WAL書込
応答
COMMIT
OK
recovery_min_apply_delay = '5min'
13:00
WAL生成
13:05以降
リカバリ
WAL生成時刻13:00の5分後の
13:05になるまで、
そのWALのリカバリは待たされる
© 2020 NTT DATA Corporation 36
スタンバイでのSQL実行
© 2020 NTT DATA Corporation 37
プライマリ・スタンバイ方式(再掲)
クライアントクライアント
DBサーバ
複製
プライマリ
中継サーバ
スタンバイ
プライマリでのデータベースの更新結果をスタンバイにレプリケーション(複製)
 プライマリでは、更新SQLと参照SQLを実行可能
 スタンバイでは、参照SQLのみ実行可能
更新SQL
参照SQL
参照SQL更新SQL
参照SQL
更新SQL
参照SQL
更新SQL
参照SQL
プライマリ・スタンバイ方式
© 2020 NTT DATA Corporation 38
スタンバイで実行可能/不可能な操作
操作 実行可能 実行不可能
SQL
クエリ・アクセス
• SELECT, COPY TO
• カーソル操作
データ操作言語(DML)
• INSERT, UPDATE, DELETE
• SELECT FOR UPDATE
データ定義言語(DDL)
• CREATE, DROP, ALTER
一時テーブル
運用
オンライン・バックアップ
• (論理) pg_dump
• (物理) pg_basebackup
メンテナンス・コマンド
• VACUUM, ANALYZE
※ プライマリからメンテナンスの実行結果が
複製されるため、スタンバイでは実行不要
トランザクション
• READ COMMITTED
• REPEATABLE READ
• SERIALIZABLE
• 二相コミット
© 2020 NTT DATA Corporation 39
スタンバイで実行可能/不可能な操作
操作 実行可能 実行不可能
SQL
クエリ・アクセス
• SELECT, COPY TO
• カーソル操作
データ操作言語(DML)
• INSERT, UPDATE, DELETE
• SELECT FOR UPDATE
データ定義言語(DDL)
• CREATE, DROP, ALTER
一時テーブル
運用
オンライン・バックアップ
• (論理) pg_dump
• (物理) pg_basebackup
メンテナンス・コマンド
• VACUUM, ANALYZE
※ プライマリからメンテナンスの実行結果が
複製されるため、スタンバイでは実行不要
トランザクション
• READ COMMITTED
• REPEATABLE READ
• SERIALIZABLE
• 二相コミット
© 2020 NTT DATA Corporation 40
スタンバイで実行可能/不可能な操作
操作 実行可能 実行不可能
SQL
クエリ・アクセス
• SELECT, COPY TO
• カーソル操作
データ操作言語(DML)
• INSERT, UPDATE, DELETE
• SELECT FOR UPDATE
データ定義言語(DDL)
• CREATE, DROP, ALTER
一時テーブル
運用
オンライン・バックアップ
• (論理) pg_dump
• (物理) pg_basebackup
メンテナンス・コマンド
• VACUUM, ANALYZE
※ プライマリからメンテナンスの実行結果が
複製されるため、スタンバイでは実行不要
トランザクション
• READ COMMITTED
• REPEATABLE READ
• SERIALIZABLE
• 二相コミット
© 2020 NTT DATA Corporation 41
スタンバイで参照できるデータ
スタンバイで参照できるデータが古い(COMMIT済の最新データは見えない)可能性がある
 COMMIT済の最新データをすぐにスタンバイで参照するには、
synchronous_commit = remote_apply の同期レプリケーションを利用する
⑦リカバリ
プライマリ スタンバイ
クライアント①COMMIT
③WAL転送
⑤OK
④応答
⑥参照SQL
⑤でCOMMIT完了とクライアントが認識した
データについて、⑦のリカバリが未実施のため、
⑥の参照SQLでは参照できない
© 2020 NTT DATA Corporation 42
ストリーミングレプリケーションの
監視
© 2020 NTT DATA Corporation 43
pg_stat_replication - プライマリからのレプリケーション状況の確認
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 39835
usesysid | 10
usename | postgres
application_name | sby1
client_addr | (null)
client_hostname | (null)
client_port | -1
backend_start | 2019-11-13 18:56:14.796913+09
backend_xmin | 497
state | streaming
sent_lsn | 0/A9FFF40
write_lsn | 0/A9FFF40
flush_lsn | 0/A9FFF40
replay_lsn | 0/A9FA228
write_lag | 00:00:00.000258
flush_lag | 00:00:00.000521
replay_lag | 00:02:01.671144
sync_priority | 1
sync_state | sync
reply_time | 2019-11-13 19:00:09.798971+09
レプリケーションの進捗
プライマリはどこまでWALを送信したか?
スタンバイがどこまでWALを
書き込み(write/fsync)、リカバリしたか?
レプリケーション接続情報
スタンバイのIPアドレス、ポート番号、
レプリケーションに使用するユーザ名、
レプリケーションの開始日時など
レプリケーションの状態
レプリケーションは非同期か?同期か?
優先度は?
レプリケーションの遅延
プライマリでのWAL生成から、スタンバイでのWALの
書き込み(write/fsync)、リカバリまで
どれぐらいタイムラグがあるか?
© 2020 NTT DATA Corporation 44
pg_stat_wal_receiver - スタンバイからのレプリケーション状況の確認
=# SELECT * FROM pg_stat_wal_receiver ;
-[ RECORD 1 ]---------+------------------------
pid | 39834
status | streaming
receive_start_lsn | 0/2000000
receive_start_tli | 1
received_lsn | 0/A9FFF40
received_tli | 1
last_msg_send_time | 2019-11-13 19:00:09.799079+09
last_msg_receipt_time | 2019-11-13 19:00:09.799135+09
latest_end_lsn | 0/A9FFF40
latest_end_time | 2019-11-13 18:58:09.473889+09
slot_name | (null)
sender_host | /tmp
sender_port | 5432
conninfo | user=postgres passfile=/Users/postgres/.pgpass channel_binding=disable
dbname=replication port=5432 application_name=sby1 fallback_application_name=walreceiver sslmode=disable
sslcompression=0 gssencmode=disable target_session_attrs=any
レプリケーションの進捗
スタンバイがどこまでWALを書き込み(write/fsync)
したか?
プライマリとスタンバイの間で送受信された最新メッセー
ジの送信時刻と受信時刻など
レプリケーション接続情報
プライマリ(カスケードレプリケーションの場合はスタンバ
イ)のIPアドレス、ポート番号、接続情報
© 2020 NTT DATA Corporation 45
PostgreSQL12以降で
ストリーミングレプリケーションを
使うときの注意
© 2020 NTT DATA Corporation 46
recovery.confの廃止
PostgreSQL12から、設定ファイルrecovery.confが廃止になり、スタンバイの設定方法が変更に
➡ recovery.conf を意識しているスクリプトやジョブなどあれば、PostgreSQL12以降で動かすために改
修が必要。
PostgreSQL11以前
• スタンバイ関連のパラメータを recovery.conf に設定
PostgreSQL12以降
• スタンバイ関連のパラメータを postgresql.conf に設定
• standby.signal ファイル(空ファイルでよい)を作成
standby.signal ファイルの存在が、サーバをスタンバイとして稼働させることを意味する
© 2020 NTT DATA Corporation 47
最後に
© 2020 NTT DATA Corporation 48
最後に
ストリーミングレプリケーションは10周年記念!!
10年間で、機能がノウハウなど揃いつつある
しかし、まだ機能不足や使いづらい点もあり、、、
次の10年間の開発に向けて、レプリケーションに関する要望などについて
ぜひ会話させてください!
© 2020 NTT DATA Corporation本資料に記載されている会社名、商品名、又はサービス名は、各社の登録商標又は商標です。
© 2020 NTT DATA Corporation 50
(付録)
PostgreSQL13新機能
レプリケーション接続先を手軽に再設定
© 2020 NTT DATA Corporation 51
レプリケーション接続先の設定
スタンバイ側で、primary_conninfoパラメータに
レプリケーション接続先を設定
$ cat $PGDATA/postgresql.conf
primary_conninfo = 'host=x.x.x.x port=5432 user=repuser'
マスタ スタンバイ
WAL転送
接続要求
x.x.x.x:5432
© 2020 NTT DATA Corporation 52
レプリケーション接続先を再設定するときの課題 (v12以前)
マスタ
スタンバイ
新マスタ
フェイル
オーバ
WAL転送
接続要求
レプリケーション接続先を再設定するには、スタンバイの再起動が必要
x.x.x.x:5432
y.y.y.y:9999
primary_conninfo = 'host=y.y.y.y port=9999 user=repuser'
再起動
© 2020 NTT DATA Corporation 53
レプリケーション接続先を手軽に再設定 (v13以降)
マスタ
スタンバイ
新マスタ
フェイル
オーバ
WAL転送
接続要求
v13から、設定ファイルの再読み込みで、レプリケーション接続先を再設定可能に!
x.x.x.x:5432
y.y.y.y:9999
primary_conninfo = 'host=y.y.y.y port=9999 user=repuser'
設定ファイル再読み込み
$ pg_ctl $PGDATA reload
© 2020 NTT DATA Corporation 54
レプリケーション接続先を手軽に再設定 (v13以降)
primary_conninfoを空にして設定ファイルを再読み込みすることで、
スタンバイ側でWAL受信を一時停止(walreceiverを停止)可能に!
マスタ スタンバイ
WAL転送
接続要求
x.x.x.x:5432
primary_conninfo = ''
設定ファイル再読み込み
$ pg_ctl $PGDATA reload
一時停止
© 2020 NTT DATA Corporation 55
(参考) 複数のレプリケーション接続先の設定
マスタ
スタンバイ
新マスタ
フェイル
オーバ
WAL転送
接続要求
v10から、複数のレプリケーション接続先を事前に設定して、
自動的に接続先を切り替えることも可能
x.x.x.x:5432
y.y.y.y:9999
primary_conninfo = 'host=x.x.x.x,y.y.y.y port=5432,9999 user=repuser'
接続に成功するまで、
設定された接続先へ
の接続を順番に試す
© 2020 NTT DATA Corporation 56
(付録)
スタンバイでのSQL実行とリカバリの競合
© 2020 NTT DATA Corporation 57
スタンバイでのSQL実行とリカバリの競合
スタンバイ上でSQL実行とリカバリが競合することがある
• SQLが完了するまでリカバリが待たされる。設定によっては、リカバリを優先するために一定時間経過後にSQLがキャンセル
• リカバリが完了するまでSQL実行が待たされる
例えば、以下の競合が発生しやすい
• VACUUM起因の競合: スタンバイでアクセス中のレコードについて、プライマリで完全削除(DELETE + VACUUM)
• ロック起因の競合: スタンバイでアクセス中のテーブルに対して、プライマリでDDLを実行してロック(ACCESS EXCLUSIVE)を取
得
プライマリ スタンバイ
レコード(id=3)を参照
SELECT * FROM test WHERE id = 3;
①レコード(id=3)を削除
DELETE FROM test WHERE id = 3;
②
ゴミレコード(id=3)をVACUUMで回収
VACUUM test;
③
VACUUMのWAL転送④
ゴミレコード(id=3)をVACUUMする⑤
WALのリカバリを試みる…
id = 3 id = 3
競合⑥
レコード(id=3)を参照するトランザク
ション(①)が完了するまでリカバリは
待ち
© 2020 NTT DATA Corporation 58
スタンバイでのSQL実行とリカバリの競合
競合によりリカバリが進まないと、
• スタンバイで参照できるデータが古いまま
• プライマリ昇格時にリカバリしなければならないWALが増えて、フェイルオーバ時間が増加
• synchronous_commit = remote_applyの同期レプリケーションが停止
競合をできる限り発生させないことが重要
• hot_standby_feedback = on により、VACUUM起因の競合を回避
• スタンバイ上のSQL実行と同じタイミングでDDL実行しないように運用して、ロック起因の競合を回避
プライマリ スタンバイ
レコード(id=3)を参照
SELECT * FROM test WHERE id = 3;
①
レコード(id=3)を削除
DELETE FROM test WHERE id = 3;
②
スタンバイの状況からゴミレコード(id=3)は回収で
きないと判断してVACUUMをスキップ
VACUUM test;
③
id = 3 id = 3
スタンバイの状況をフィードバック
hot_standby_feedback = on
ゴミレコード(id=3)は、①のトランザク
ション終了後にVACUUMが走ると回収。
スタンバイでロングトランザクションがある
と、VACUUMできないゴミレコードがた
まり続けるため注意。
© 2020 NTT DATA Corporation 59
vacuum_truncate
VACUUMやautovacuumが勝手にACCESS EXCLUSIVEロックを取得して、ロック起因の競合を引き起こすことがある
• VACUUMは、通常、強いロックを取得せずにゴミレコードを回収するだけ
• ただし、ゴミレコードの回収によりテーブル末尾に空き領域ができた場合に限り、ACCESS EXCLUSIVEロックを取得して末尾の
空き領域を物理的に削除する
VACUUMに「ロックを取得してテーブル末尾の空き領域を物理削除」させるかどうかをvacuum_truncateで設定可能
• vacuum_truncateはPostgreSQL12から利用可能
• ロック起因の競合を避けたいテーブルに対しては、vacuum_truncate = off と設定する
ALTER TABLE test SET (vacuum_truncate = off);
• VACUUM (TRUNCATE off);
ゴミ
ゴミ
空き
空き
①ゴミレコードの回収
ACCESS EXCLUSIVE
ロックの取得
③空き領域の物理削除
②
© 2020 NTT DATA Corporation 60
(付録)
レプリケーションのアーキテクチャ
© 2020 NTT DATA Corporation 61
アーキテクチャ
walsender walreceiver startup
データベース
クライアント
②変更
③書き込み
WAL WAL
⑤読み込み
⑥WAL転送
⑦書き込み ❾読み込み
❿リカバリ
⓬参照
①更新Tx ⓫参照Tx
backendbackendbackend
backendbackendbackend
プライマリ スタンバイ
データベース
ディスク領域メモリ領域プロセス
凡例
⑩応答
⑨応答 ⑧応答
④通知
❽通知
⓭結果