PostgreSQLエンタープラズ・コンソーシアム 技術部 WG#3
WG3活動報告
ーション調査
2
8
9
10
10
10
10
10
11
12
12
12
12
12
12
12
12
13
13
13
13
13
14
14
14
14
15
15
15
17
18
18
18
23
23
25
26
27
30
30
30
30
31
31
31
32
34
34
36
36
36
36
37
37
38
38
38
目次
1. 改訂履歴
2. イセン
3. はじめに
3.1. PostgreSQLエンタイズシアムとWG3について
3.2. 本資料の概要と目
3.3. 本資料の構成
3.4. 想定読者
3.5. 参考文献
4. PostgreSQLにおけるレリケーション
4.1. リケーョンの
4.1.1. 可用性の向上
4.1.2. 性能向上
4.1.2.1. 参照同期
4.1.2.2. 更新によ一貫性の維持
4.2. 代表的なレリケーションの
4.2.1. ングルマス
4.2.1.1. トレージレリケーション
4.2.1.2. トリガベーリケーション
4.2.1.3. リベースレリケーション
4.2.1.4. トリーミングレリケーション
4.2.1.5. ロジカルレプリケーション
4.2.2. チマ
4.2.2.1. Bi-Directional Replication
4.2.2.2. Bucardo
4.3. 参考文献
5. トリーミングレリケーション
5.1. はじめ
5.1.1. PostgreSQLのストリーミングレリケーションの特徴
5.1.2. 検証を実施したSR構成
5.2. SR環境構築時の設定項目、推奨値
5.2.1. SRにおける目的別の設定
5.2.2. SR本設定手順2ノード)
5.2.3. スレの追加
5.2.4. カイブード運用
5.2.5. リケーションロット
5.2.6. 【参考情報】同期モードにおけるパフォーマンスへの影響
5.2.7. 遅延レリケーション
5.2.8. WAL圧縮
5.3. SR環境の監視
5.3.1. リケーション作ログの監視
5.3.1.1. 調査目的
5.3.1.2. 調査結果
5.3.1.3. 調査結果
5.3.2. 同期状況監視
5.3.2.1. 同期遅延監視
5.3.3. 更新、読み取りの監視
5.3.3.1. 更新・読取監視
5.3.4. スプットブインの監視
5.3.4.1. リットブインの定義と調査の目的
5.3.4.2. 監視方法
5.3.4.3. サーログの監視
5.3.4.4. pg_controldataドによ監視
5.3.4.5. pg_control_recoveryコマンドによ監視
5.3.4.6. pg_is_in_recovery関数によ監視
5.4. SR環境の障害時運用
5.4.1. 本文書にける用語の定義
PostgreSQL Enterprise Consortium
Page 2 of 285
38
38
39
39
40
41
42
46
47
50
51
52
54
59
60
63
65
65
65
66
67
67
72
76
83
83
87
91
91
94
97
104
106
106
109
109
109
109
109
110
110
111
111
111
111
112
112
117
117
117
117
117
119
119
119
119
120
123
123
5.4.1.1. フェイルオーバ
5.4.1.2. フェイルバック
5.4.1.3. イッチオ
5.4.1.4. イッチバック
5.4.2. 障害時運用手順(2ノード構成
5.4.2.1. フェイルオーバ
5.4.2.2. フェイルバック
5.4.2.3. イッチオ
5.4.2.4. イッチバック
5.4.2.5. 障害によ対処
5.4.3. 障害時運用手順(複数ス
5.4.3.1. フェイルオーバ(複数スーブ)
5.4.3.2. フェイルバック(数ス)
5.4.3.3. イッチオ(複数スーブ)
5.4.3.4. イッチバック(複数ス)
5.4.3.5. 障害によ対処(複数ス)
5.4.4. 障害時運用手順(カスケード構成)
5.4.4.1. フェイルオーバ
5.4.4.2. 同期スレーブのフェイルオーバ
5.4.4.3. 非同期スレーブのフェイル
5.4.4.4. フェイルバック
5.4.4.5. 旧マ同期モードスレーブとしてフェイルック
5.4.4.6. 旧マインタンス障害からフェイルバック
5.4.4.7. 旧マ/旧スーブ1フェイルバック
5.4.4.8. イッチオ
5.4.4.9. 同期スレーブのスイッチオ
5.4.4.10. 非同期スへのイッチオ
5.4.4.11. イッチバック
5.4.4.12. 同期ドスからマのスイッチバック
5.4.4.13. 非同期モードスレーブからマへのイッチバック
5.4.4.14. pg_rewind使用したスイッチバック
5.4.4.15. ーブ障害によ対処
5.5. とめ
5.5.1. SR機能拡張の歴史
6. ロジカルレリケーョン
6.1. ロジカルレリケーションの概要
6.1.1. 概要
6.1.2. 特徴
6.1.3. キテクチャ
6.1.4. ースケース
6.1.5. 制限事項
6.2. ロジカルレリケーションの設定
6.2.1. ータベース単位の設定
6.2.1.1. 検証目的
6.2.1.2. 検証内容
6.2.1.3. 検証環境
6.2.1.4. 検証手順
6.2.2. テーブル単位の設定
6.2.2.1. 検証目的
6.2.2.2. 検証内容
6.2.2.3. 検証環境
6.2.2.4. 検証手順
6.2.3. リケーション象とす更新処理の限定
6.2.3.1. 検証目的
6.2.3.2. 検証内容
6.2.3.3. 検証環境
6.2.3.4. 検証手順
6.2.4. 設定するパータ
6.2.4.1. 実行時パラメータ
PostgreSQL Enterprise Consortium
Page 3 of 285
124
129
130
130
130
130
130
131
134
134
135
135
135
141
141
141
141
142
150
150
150
150
151
156
156
156
156
156
169
169
169
170
170
172
174
174
177
178
178
179
185
187
189
191
191
192
194
195
197
198
199
200
201
202
203
204
204
205
206
6.2.4.2. 実行時パラメータと起動プロセスの関係
6.2.4.3. 考察
6.3. ロジカルレリケーションの応用
6.3.1. primary key定義されていルのリケーション設定
6.3.1.1. 検証目的
6.3.1.2. 検証内容
6.3.1.3. 検証環境
6.3.1.4. 検証手順
6.3.2. 同期レリケーション
6.3.2.1. 検証目的
6.3.2.2. 検証内容
6.3.2.3. 検証環境
6.3.2.4. 検証手順
6.3.3. 複数サブスクリプョン
6.3.3.1. 検証目的
6.3.3.2. 検証内容
6.3.3.3. 検証環境
6.3.3.4. 検証手順
6.3.4. カスケード構成
6.3.4.1. 検証目的
6.3.4.2. 検証内容
6.3.4.3. 検証環境
6.3.4.4. 検証手順
6.3.5. ィショニングと組み合わせ
6.3.5.1. 検証構成
6.3.5.2. 組み合わせた場合の利点
6.3.5.3. 検証内容
6.3.5.4. 検証結果
6.4. ロジカルレリケーションの運用
6.4.1. 監視
6.4.1.1. 前提とする
6.4.1.2. ロジカルレプリケーションの設定
6.4.1.2.1. Publisherで確認で情報
6.4.1.2.2. Subscriber確認できる情
6.4.1.3. ロジカルレプリケーションの稼働状態
6.4.1.3.1. Publisherで確認で情報
6.4.1.3.2. Subscriber確認できる情
6.4.2. 障害時の動作確認
6.4.2.1. 前提とする
6.4.2.2. 障害ケー1 ロジカルレプリケーション関連ロセの異常終了
6.4.2.3. 障害ケー2 Publisherのノード停
6.4.2.4. 障害ケー3 Subscriberのノード停止
6.4.2.5. 障害ケー4 Publisher/Subscriberネットワ断絶
6.4.3. リケーション象テの追加/削除
6.4.3.1. 前提とする
6.4.3.2. リケーション対象のテーブ追加す手順(ース単位Publication)
6.4.3.3. リケーション対象のテーブ追加す手順(テーブ単位のPublication)
6.4.3.4. リケーション対象のテーブ変更す手順
6.4.3.5. リケーション対象のテーブにインデック追加する手
6.4.4. リケーション象外となる操作、オブェクト
6.4.4.1. 前提とする
6.4.4.2. TRUNCATE
6.4.4.3. シー
6.4.5. 更新競合時の動作
6.4.5.1. 前提とする
6.4.5.2. 更新時の競合発生と解
6.4.5.2.1. 違反/一意キー
6.4.5.2.2. CHECK制約違反
6.4.5.2.3. 新デ゙存在しない
PostgreSQL Enterprise Consortium
Page 4 of 285
207
207
209
211
212
213
214
214
215
215
215
215
216
217
217
218
218
221
221
222
222
230
231
232
232
232
232
232
232
233
233
234
234
234
235
235
235
235
235
236
241
241
241
241
241
241
241
243
247
247
247
247
247
249
250
250
250
250
250
6.4.5.2.4. 除デ゙存在しない
6.4.5.2.5. ーブ存在しない
6.4.5.2.6. 部の列が存在しない
6.4.5.2.7. デー型変換エ
6.4.5.2.8. ーフロック
6.4.5.2.9. 新対象レードのロッ
6.4.5.3. 初期同期時の競合発生と解消
6.4.5.3.1. 違反/一意キー
6.4.5.3.2. CHECK制約違反
6.4.5.3.3. 新デ゙存在しない
6.4.5.3.4. 除デ゙存在しない
6.4.5.3.5. ーブ存在しない
6.4.5.3.6. 部の列が存在しない
6.4.5.3.7. デー型変換エ
6.4.5.3.8. ーフロック
6.4.5.3.9. 新対象レードのロッ
6.4.5.4. WALのスキップによ競合の解消
6.4.6. ストリーミンリケーションとの併用
6.4.6.1. 前提とする
6.4.6.2. トリーミングレリケーション併用する環境の構築手順
6.4.6.3. トリーミングレリケーション併用する環境で障害が発生した場合の運用手順
6.4.6.4. 考察
6.5. とめ
7. Bi-Directional Replication (BDR)
7.1. はじめ
7.1.1. BDRの特徴
7.1.1.1. BDR
7.1.1.2. ユーケース
7.1.1.3. カニズ
7.1.1.4. 整合
7.1.1.5. シー
7.1.1.6. 比較
7.1.1.7. サポート
7.2. 調査、検証の目的
7.3. 調査、検証の前提
7.4. BDR環境構築時の設定と設定手順
7.4.1. BDR境の設定手順
7.4.1.1. 概要
7.4.1.2. 対象試験サー
7.4.1.3. 事前確認
7.5. BDR動作検証
7.5.1. ノードの追加・切り離し
7.5.1.1. 検証目的
7.5.1.2. 検証内容
7.5.1.3. 検証環境
7.5.1.4. 検証手順
7.5.1.4.1. ノード切り離し
7.5.1.4.2. ノード追加
7.5.1.5. 検証結果
7.5.2. グローバルシーケンス設定
7.5.2.1. 検証目的
7.5.2.2. 検証環境
7.5.2.3. 検証手順
7.5.2.4. 検証結果
7.5.3. 選択的レケーション
7.5.3.1. 検証目的
7.5.3.2. 検証内容
7.5.3.3. 検証環境
7.5.3.4. 検証手順
PostgreSQL Enterprise Consortium
Page 5 of 285
254
254
254
254
255
255
256
264
265
268
269
270
272
272
272
272
272
272
272
275
278
278
278
278
278
278
279
279
281
282
282
282
282
283
284
285
7.5.3.5. 検証結果
7.5.4. 更新処理競合時の動作
7.5.4.1. 検証目的
7.5.4.2. 検証内容
7.5.4.3. 検証環境
7.5.4.4. 検証手順
7.5.4.4.1. PRIMARY KEYたはUNIQUE制約
7.5.4.4.2. 部キー制約
7.5.4.4.3. 他制約
7.5.4.4.4. ローバルなデー
7.5.4.4.5. ロックの競合とデッドロックの中断
7.5.4.4.6. その
7.5.4.5. 検証結果
7.5.5. ノード障害と復
7.5.5.1. 検証目的
7.5.5.2. 検証内容
7.5.5.3. 検証環境
7.5.5.4. 検証手順
7.5.5.4.1. ノード障害
7.5.5.4.2. ノード復旧
7.5.5.5. 検証結果
7.5.5.6. 備考
7.6. BDR性能検証
7.6.1. 更新性能検証結果
7.6.1.1. 検証目的
7.6.1.1.1. 証内容
7.6.1.1.2. 証環境
7.6.1.1.3. 証手順
7.6.1.1.4. 証結果
7.7. とめ
7.7.1. BDR証まとめ
7.8. 参考文献
7.8.1. 関数一覧
7.8.2. テムカタログ一覧
8.
9. 著者
PostgreSQL Enterprise Consortium
Page 6 of 285
PostgreSQL Enterprise Consortium
Page 7 of 285
1.
1.0 2017/06/20 2016年度版として新規作成
- Postg reSQ L 9.6 を対象バージョンとする
2.0 2018/04/11 2017年度版として主に以下の章を加筆修正
- 5  ストリーミングレプリーシ
     Po stgreSQ L 10 対応
     複数スレーブ対応 (1.0版では2ードに限定しいた)
- 6  ロジカルレプリーシンの追加
     Po stgreSQ L 10 新機能として追
PostgreSQL Enterprise Consortium
Page 8 of 285
2.
本作品はCC-BYライセンスよって許諾さいます イセンスの内容を知りたい方は ちら でご確認くださ 文書の内容表記に関する誤り、ご要望、感想等につ
きましては、PGEConsのサイト 通じてお寄いたきますよお願いいたします
Eclip seは、Eclip se Fo u n d atio n Incの米国、およびその他の国における商標もしく登録商標です。
IBM DB 2は、世界の多くの国で登録されたIn tern ation al B u sin ess Mach in es Corp oration の商標で
In telンテおよびXeo n は、米国およびその他の国における In tel Corp ora tion の商標です。
Javaは、O racle Corp o ration 及びその子会社関連会社の米国及びその他の国における登録商標です。 文中の社名商品名等は各社の商標または登
録商標である場合があります
Lin u x Linu s To rvald s の日本およびその他の国における登録商標また商標で
Red H atおよSh ad ow man log o は、米国およびその他の国におけるRed Hat,In c.の商標または登録商標です。
Microso ftW ind o w s ServerSQ L Server、米国 M icro soft Co rp oration の米国及びその他の国における登録商標または商標です。
MySQ Lは、O racle Corp o ration 及びその子会社関連会社の米国及びその他の国における登録商標です。 文中の社名商品名等は各社の商標または
登録商標である場合があります
O racleは、O racle Corp o ration 及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名商品名等は各社の商標または
登録商標である場合があります
Po stg reSQ LPostgreSQ L Commu n ity Association o f Can ad aのカナダにおける登録商標およびその他の国おける商標です。
W in d o w s は米国 Micro soft Co rporation の米国およびその他の国における登録商標です。
TPC, TPC B en ch mark, TPC-B, TPC-C, TPC-E, tp mC, TPC-H, TPC-DS, Q p h H は米国Tran saction Pro cessin g Performan ce Cou n cilの商標です。
その他、本資料に記載さいる社名及び商品名はそぞれ各社が 商標または登録商標として使用している場合があります
PostgreSQL Enterprise Consortium
Page 9 of 285
3.
3.1. PostgreSQLエンープコンーシアムとWG3につ
Po stg reSQ Lエンープライズコンソーシアム(略称 PG ECon s)Po stg reSQ L本体および各種ツールの情報収集と提供、整備などの活動を通じて、ミッションクリティカル
性の高いンタープライズ領域へのPo stgreSQ Lの普及を推進するとを目的として設立さた団体です。
PG ECon s 技術部会ではPostgreSQ Lの普及に資する課題活動テーマとし、3のワーキングループで具体的活動を行っています。
W G1技術検証ワーキンググループ)
W G2行ワーキンググループ)
W G3題検討ワーキングループ)
れら3つのーキンググルーのうち、W G1W G 3ついては 2015 年度まではそれぞ性能ワーキンググルー、「設計運用ワーキンググループ」という名称で活動し
きま2016年度は、来の活動領域広げる意図のもとでそれらを再定義し、上記のような名称に改めました。
れに伴いW G3ではPostgreSQ Lの設計運用を中心としたまざまな題の解決のための調査検証を行い、Postg reSQ Lが広く活用さ事を推進していくととしま
した
3.2. 本資料の概要と目的
本資料はW G32017年度の活動としてPo stgreSQ Lおけレプリケーション機能にいて、調査検討した結果をまとめたものです。
れまでにも、W G3では3度にわたってレプーションにいて取り上げています
2013年ではPostgreSQ Lをエンープライズ領域で活用するあたって、業務要件とトとのバランスをえて能な限り業務を継続できるよう、システムの運用や保
守サービスをPostgreSQ Lで実現する手法につてまとめました [PG ECon s_W G 3_2013] 。報告書では、可用性を向上させるめの手段としてレプリケーションを取り上
げています。今年度の報告書では取り上げなかった、スレージレプリーシ(DRBD)、トリガベーレプーショ(Slon y-I)つい紹介しています。
2014年度では、用性のうち「災害対策」焦点を当てITサービス継続を可能とする Po stgreSQ L の構成につて調査検討しています [PG ECon s_W G3_2014]
ーミングレプーションを含む代表的な Po stgreSQ L のシステム構成を挙げて、データベースのデータ保全性、サービ継続性の観点から各構成の得失を示しまし
2016年度では、ストリーミングレプリーションの2ノードにおける運用ノウハウの整理 Postg reSQ L をベースとして双方向レプリーシンがリリースいます
れらの開発動向と過去の検討結果とを踏ま2017年度は PostgreSQ L 10にて機能拡充が進むストリーミングレプリーシンの3ノードにおける運用ノウハウの整
理と、新機能のロジカルレプリーションの調査実施しした
3.3. 本資料の構成
じめ
Po stg reSQ Lおけるレプリーション
レプーションの目的
代表的なレプリケーションの手法
ーミングレプーショ
じめ
SR環境構築時の設定項目、推奨値
SR環境の監視
SR環境の障害時運
レーブのアーカイブ保存
まとめ
ロジカルレプリーション(仮)
じめ
ロジカルレプリーション環境構築時の設定項目、推奨値
ロジカルレプリーション動作検証
ロジカルレプリーション性能検証
まとめ
B i-Directio n al Replication (B DR )
じめ
B D R 環境構築時の設定項目推奨値
B D R 動作検証
B D R 性能検証
まとめ
おわりに
3.4. 想定読者
PostgreSQL Enterprise Consortium
Page 10 of 285
本資料の読者は以下のような知識を有していることを想定していす。
DB M S操作してデーベースの構築、保守、運用を行うDB A知識
Po stg reSQ Lを利用する上での基礎的知識
3.5. 参考文献
[PG E Co n s_W G 3_2013] Po stg reSQ L E n terprise Con sortium. 2013年度W G 3活動成果報告書. 2014. h ttps://w w w .pg eco n s.org/w p -
con ten t/u plo ads/PG E Co n s/2013/W G3/pg eco n s-w g3-2013-report.p d f
[PG E Co n s_W G 3_2014] Po stg reSQ L E n terprise Con sortium. 2014年度W G 3活動成果報告書 (用性編). 2014. h ttps://w w w .pg eco n s.o rg /w p -
con ten t/u plo ads/PG E Co n s/2014/W G3/PG ECon s_2014_W G3_Availab ility.pdf
[Po stg resB D R ] 2n d Q u ad ran t. Po stg res-B D R. Version Po stg res-B DR94 1.0.2, Novemb er 14, 2016. h ttps://2n d qu adra n t.co m/en -
u s/reso u rces/bd r/
PostgreSQL Enterprise Consortium
Page 11 of 285
4. PostgreSQL
データベースにおいて、レプリーションとは複数のデーベースサーバの間で、 何らかの一貫性保ちながらその内容を複製する手法を指します。Po stg reSQ Lおいて
9.0 以降の各バージョンの基本機能として、レプーションが実現さいます また、PostgreSQ L付加するツールによってもレプリーシンが実現されいます
の章では、各種のプリーション機能を目的に応じて使い分けるめに、機能と特性にいて簡単に紹介します
4.1. レプリケーショ目的
レプーションによって複数のデータベーサーバの複製を作ることによって、シングルサーバでは対応が難しい要件に対応でるよります。それらは、データの冗長
(複製があるこ)と複数サーバによる処理の分散の結果です。
4.1.1.
可用性はITシステムの非機能要件の一つで、システ継続的に利用可能とすることで [IPA] 可用性は継続性耐障害性」災害対策」回復性という4つの
要素から構成されますが、レプリーシンによってデータベースサーバを冗長化ることで、1のサーバで故障や災害が生じたときにもレプリカが格納されている残りのサーバ
でサービスを続するができるるようります。また、運用上の停止が必要な場合であっても、各サーを順次停止して作業ることで、サービス全体としては停止さ
いようできます。
先に挙げた可用性の4の要素をどの程度満足するかはータベースの構成によって変ってきます。詳しくは『2013年度W G3活動成果報告書』
[PG E Co n s_W G 3_2013] を参考にしてい。
4.1.2.
レプーションによって、同じ情報を格納しているデータベースサーバが複数存在することになります。それらのサーバでアプリケーションからの要求にこたることが出来れ
、システム全体としての性能状況が期待できます(スケールウト)アプリケーシンからの要求を複数のサーバに分散させるには、更新(削除・挿入含む)クエリを
1サーバ集約するシングルマスタ」構成と、複数のサーバに分散するスタ」構成があります。ま、参照クエリを数のサーバに分散させるとを参照負荷分散
と呼びます。
レプーションクを性能向上に用いる場合、複数のデータをベースを同時に運用ることから生じる特有の課題がありす。レプリケーション方式を選択する際には、
それらの課題どの程度解決しているのかにいて考慮する必要があります
4.1.2.1.
ある瞬間に同一の参照クエリを異なるサーバに送った時に、まった同じ結果が返ってくるものと、そうでないものとがありす。同じ結果が得られる場合、サーバは期して
る、期レプーションであると言います。
4.1.2.2.
マルチマスタ構成の場合には同期の問題に加え、更新の衝突と一貫性の維持が問題となります。
更新の衝
複数のアプリーシンプログラムから一の更新操作実行しとした場合、単一のDB ーバであればどちかの操作が遅延され、場合によってはエラーと
ます。マルチマス構成では、レプリーションの送信側でれた更新と、そのサー直接要求され更新とが衝突した場合に、どちが優先するのかが問題と
ります。
一貫性の維持
更新が衝突した結果、レプリーションの送信側と受信側でデータベースの内容が異なってしまうと、レプリケーションによって構成されるク全体でデーベース
の一貫性が維持されなくります。この問題を適切に対処する必要がありす。
4.2. 代表的なリケーショ手法
では、本報告書で取り上げるレプリーション手法中心にPostgreSQ L で利用できる表的なレプリーション手法を紹介しす。レプリケーションを利用する立場
からは、ングルマスタとマルチマス二分するができます。その上で、レプリを生成する方法に着目して代表例挙げ、そのメリッデメットを説明します
お、『2013年度W G3活動成果報告書』 [PG ECon s_W G 3_2013] 可用性向上の観点から、レプーションを含めて様々な Po stgreSQ L の構成取り上げて
いますので、併せてご覧くい。
ュニティW ikiページには、Po stg reSQ Lで動作するソフウェいての解説がありその中にレプリケーションも含まれています [PGW iki_replica] 。ここ
紹介する紹介するレプリケーションソフウェアについ紹介さいます
4.2.1.
シングルマス構成の場合レプリカを生成する手法に以下のようなもがあります
レージレプリケーショ
トリガベーレプリーショ
エリベーレプーショ
ーミングレプーショ
PostgreSQL Enterprise Consortium
Page 12 of 285
ロジカルレプリーショ
4.2.1.1.
Po stg reSQ Lやその上で動作するツールを介することなく、データを格納するスレージのレベルでデータを複製します。スレージ装置自体がレプリ生成するものや、
DRB D [DRB D ] のようにLin u xで動作するソフウェアによる実現がありす。
ット
Po stg reSQ Lから単一のサーバに見えるので、単一サーバと同じよう運用できます
デメット
受信側のサーバはータベースとして動作していないので、負荷分散に利用するとがでませ
4.2.1.2.
Po stg reSQ Lのデータベー内に更新によって起動さトリガを設定しておき、更新にる変分を受信側のサーバに送り出すもの。代表的な製品に Slony-I があります
以下では Slo n y-I での主なメリッデメットを紹介します
ット
Po stg reSQ Lのデータベー含まれる表全体だけでなく、任意のテーブルについてけ複製作成することがで
更新さ表にいては参照負荷分散、それ以外の表にいて更新負荷分散が可能です
デメット
比較的オーバヘッドが大きいため、後述のスーミングレプーション方式に比べて、性能が低い傾向があります [pg logical]
4.2.1.3.
アプーションプログムとD B サーバ(Po stgreSQ L)の間に入るミドルウェアによって発行さリを複製して複数DB サー送信することでデータベーを複製し
ます。代表的な製品に Pg p o o l-II [Pg p oo l-II] があります。
ット
複数のD B サーを用いて負荷分散実現する際に、参照クエリ更新クエリとも適切なサーバにクエリが自動的に振り分けらるため、アプーショ
ンから見ると単一のDB サーバを利用しているよ見え
デメット
一部のSQ L文に対する挙動が単一DB サーとは異なる
4.2.1.4.
Po stg reSQ L ータベースでは、更新をコミットした際にその結果をクシュ等で失わないよう更新情報をファイルに書きこむログ先行書込み(W rite Ah ead Logg ing ;
W AL)を用いています。このW ALファルにデータベースに対する更新を全て復元ることができる情報が含まれていますから、これを他のDB サーバに転送するとでデータ
ベースを複製することができる --- がスーミングレプーションの基本的考え方です。
ーミングレプーションは、W ALファルに書かれた内容をほぼそのまま受信側(スレーブサーバ)送り出すことで、送信側(マスサーバ)と物理的に一致するD B を複製
します
ット
受信側サーバに送信側サーバと物理的に一致したデータベースを複製するとができる
送信側サーバでコミット済みのデータを受信側で確実に書き込み済みにするとができるめ、高信頼化に適している
参照負荷分散ができる
デメット
特定のデータベース、だけを複製することできな
ジャーバージョンが異なPo stgreSQ Lの間で利用できない
受信側サーバのデータベースは更新できな
4.2.1.5.
ロジカルレプリーションはPostgreSQ Lバージョ10から標準採用さ機能です。ストリーミングレプリーションが送信側のW ALをそのまま受信側に転送るのに対
、ロジカルレプーションは送信側でW ALファイルデコードし、必要な変更内容のみを受信側に送ります
ット
送信側サーバの一部の表に対する更新だけを受信側に送ることができる
複数の送信側サーバの出力を1の受信側サーバで受け取ることができる
PostgreSQL Enterprise Consortium
Page 13 of 285
ジャーバージョンが異なPo stgreSQ Lの間で利用で
受信側サーバのデータベースを更新するとができる
デメット
レプーションできなSQ Lやオブジェクトがあり、送信側と受信側で不整合が発生しないよう注意して運用する必要がある
受信側サーバのデータベースを更新した場合送信側サーバでの更新内容と競合する可能性がある
4.2.2.
マルチマスタ構成の場合、レプリを生成する法に以下のようものがあります
B i-Directio n al Replication
B u card o
4.2.2.1. Bi-Directional Replication
2n d Q u adran tが公開している B i-D irection al Replication は、先に紹介した論理レプリケーションを用いてデー複製しつつ、複数のサーでデーの更新を可
能としたものです。主な用途としては地理的に離れ場所にある複数のサーバ間で、データを共有する利用形態を想定しています [Po stg resB D R ]
ット
論理レプリーションを利用しているため他の方式によるマルチマス比べてオーバヘッドが小さ
デメット
レプーション自体は非同期に行われるため、複数サーバに同時に発行した参照クエリの結果が異なるとがあります。
4.2.2.2. Bucardo
B u card o は、ガベースレプリケーションを使ってデータを複製します [B u card o ] 。そのため、メット、デメリッはシングルマスタのトベースレプリケーションと同じです。
4.3. 参考文献
[IPA] 独立行政法人情報処理推進機構. 機能要求グレード 利用ガイド[活用編]. 2010. h ttp://w w w .ip a.go.jp/files/000026853.p df
[PG W ik i_rep lica] Smith , G .; Grittn er, K.; Pin o , Con rad T.; R ing er, C.; Simon , R . et al. R ep licatio n , Clusterin g , a n d Co n n ectio n Pooling . 2017.
h ttps://w iki.postgresql.org /w iki/R eplication ,_Clu sterin g ,_an d _Con n ectio n _Po oling
[DRB D] LINB IT, In c. h ttp://w w w .d rbd.org /en/
[p g lo g ical] 2n d Q u adra n t. pg logical. h ttps://2n d qu adran t.co m/en/resou rces/pg logical/
[Pg p oo l-II] Pg Po o l G lobal Develop men t G rou p . h ttp://w w w .p g po ol.n et/med iaw ik i/in d ex.ph p /M ain _Page
[B u cardo ] Jensen, G .; Sabin o, G . M . et al. h ttps://b u cardo .o rg/w iki/Main _Page
PostgreSQL Enterprise Consortium
Page 14 of 285
5.
5.1. じめに
5.1.1. PostgreSQL
Po stg reSQ Lのストリーミングレプリケーショ(以下SR構成)は以下を目的とした構成です。
可用性の向上
性能向上
以下の特徴があります
変更履歴が格納されたW ALを操作単位でマスタ側からスレーブ側へ転送ることでデータを同期
SR基本構成図(スレーブ1台)
Po stg reSQ L 10 おける主な機能を示します。
より、スレーブ活用度の向上が期待できる
同期式はW ALの転送までの保証であり、データ保護が目的。
完全同期式はW ALの適用までの保証であり、データ同期が保証れるためリアイムのデータ照に期待。
syn ch ro n o u s_co mmit以下の設定が可能であり、要件に応じて選択。
remote_apply :全同期。W AL適用まで保証。昇格時の時間短縮と参照負荷分散の拡充が目的。
on      :同期。W AL転送ディス書き込みまで保証。データ保護が目的。
remote_w rite :同期。W AL転送リ書き込みまで保証。データ保護とパフォーマンスンスが目的。
lo ca l    :非同期。ローカルのW AL込みまで保証。パフォーマンス優先が目的。
off     :完全非同期。ローカルW AL書き込みすら保証しない。最もパフォーマンスが非現実的。
以下の図syn ch ro n o u s_co mmitの設定による保証時点を示す
より、スレーブに必要なW ALをマスタが確保し続ける
レーブの障害時(ネットワーク不調含む等にマスW ALを保持し切れず、W ALファイルの再利用によりロストする懸念がある。
レプーションスロットの登場前はw al_keep _segmen tsパラメーによる調整、まはアーカイブモード運用が必要であった - w al_keep_seg men ts
W AL数を指定するものであるため、見積もりが困難である。 - アーカイブモードも複数スレーブ構成における不要W ALファルの判断はやはり困難。
レプーションスロットによりW ALファイルの要・不要の判断をシスムに任せる事ができる。
SR構成のW ALァイル管理のためにアーカイブモード運用は必要はな、過去の時点に復旧する(PITR )要件がある場合に設定する
PostgreSQL Enterprise Consortium
Page 15 of 285
複数スレーブの場合は、スレーブ毎に専用のレプリケーシンスロットを作成する
が可能
従来も複数スレ構成は可能であっが、同期スレーブはその内の1台までという制限があったがそれが取り払われた
同期スレーブを任意(ANY)に選択するQ uo rum-based 同期レプリーシンが実装さ
により、オペレーションミを反映さない事が可能に
レーブでの適用を一定時間待機る機能である。マスでのオペミスが即座にレーブに伝搬さるのを防ぐのが主な目的。
W ALァイルの転送は遅延な処理さるため、データ保全(RPO )の観点では問題ない。同期モードで設定する事もできる
recovery.con f reco very_min _apply_delayパラータ遅延時間を設定。
従来からの手法としてPITR使用してオペミ直前時点を指定してカバリするで障害回復を図る方法もある
(p g_rew ind )より、効率の良いSR 再構成が可能に
旧マスを分岐時点へ巻き戻す事で、新マスタに追い付事が可能な状態とする能である。
巻き戻し後、旧マス新マスW ALを適用(追い付する事で旧マスタを新スレとして構成。
従来はpg_baseb acku p 等による作成が必要であっ
大規模データベースでは、大幅な時間短縮が期待できる
下図に巻き戻し機能のイメージを示す
PostgreSQL Enterprise Consortium
Page 16 of 285
WAL より、W AL転送の効率を改善
W AL圧縮でサイズを縮小するにより、W AL転送の効率改善が目的。
レーブを遠隔地に配置る場合に特に有効。
注意点として、圧縮(マスや解凍(スレーブ)の負荷が発生る。
SR構成の運用上の注意点
死活監視と障害発生時のフイルオーバはPo stgreSQ Lの機能ではできないためソフを利用する要があります 商用クラスタフトが使用さ
合もありますが、オープンソースソフトウェアのPgpo o l-II と呼ばれるクラスタフトを使用した例も多く報告されています。 特に参照負荷分散を行う場合
Pgp oo l-IIを使用します。
5.1.2. SR
以下のSR構成に検証を実施しています。
対象バージョンは Po stgreSQ L 10
201711 時点の最新版
3ノード構
1. 複数スレーブ方式( - 1 , 2 スレーブ2はマスと繋がっている
2. カスケード方式( - - 孫) レーブ2スレーブ1と繋がってい
Po stg reSQ Lの機能に限定
Pgp oo l-II等のラスタフトに関するーマは対象外
PostgreSQL Enterprise Consortium
Page 17 of 285
5.2. SR環境構築時の設定項目、推奨値
5.2.1. SR
Po stg reSQ LSR構成に様々な機能があり、 処する障害応じて適切に設定する必要があります また各機能組み合わせとが可能で
"ストリーミングレプリーシ""SR"表記します。
"レプリーションスロッ""ロット"と表記します。
5.1 SRの機能
アーカイブW AL
必要なW ALファイルの保持。以下の2種類
物理バッアッ(PITR )必要フルバックアップ以降
の)W AL 障害発生直前まで復旧や操作ミス時に過
戻す機能がある
SR構成において未転送のW ALを保持する
アーカイブW ALがディス領域圧迫しいように、不要とった
アーカイブW ALの明示的な削除が必要。
SR用途の場合、W ALイルの要不要の判断が困難であるた
め、現在では後述のレプーションスロットの使用が一般的。
SR構成に物理バッアップという面もあるため過去に戻す
要件がなければ物理バッアップを取得する必要性は低い。
れらを考慮し、一般的には非アーカイブモード運用でも十分と
考えれる。
レプーションスロッ
レーブに必要W ALァイルを保持する事によるSR構成の維持。
対応する各スレーブの未転送のW ALを保持する。
レーブへW ALファイルの転送ができな状態が続くと、W AL
イルが溜まり領域を圧迫する。
複数スレーブ構成では、スレーブ毎にロットの使用/未使用を
選択できる。
レーブ毎にスロットを作成する必要がある
遅延レプリーショ レーブ側のW AL適用を意図して遅らせるとで、スレーブを
の過去の状態に維持する 操作ミス対策に任意の時点まで巻き
戻せるようにする
レーブはに過去の状態であめ、参照活用には一定の制
限がある。
イルオーバ時には遅延分の適用が必要にるため、RTO
点で難がある。そのため複数スレーブ構成の場合に1スレーブで
構成するのが一般的
W AL圧縮 Fu ll Page W rite(ポイント後の最初の更新時)W AL
ァイルに書き出すルページイメージを圧縮する。 縮された
W AL適用時に解凍される。 W ALサイズを大幅に圧縮できる
能性があり、転送負荷の低減が期待さる。ディザスタ・リカバ
構成で有効と考え
マスの圧縮時とスレーブの解凍時に通常り余分にCPU 負荷
と時間がかる。
5.2.2. SR 2
基本的なSR 境の設定手順を紹介します 尚、マスとスレーブの両サーPo stg reSQ Lインストール済みであり マス側でデータベースクラスタを構築している
とを前提としてす。
1. 関連パラータ
SR構成に最低限必要な設定は以下の通りで スレーブはマスベースバックアップから作成さめ、マスタに設定しパラメータは全てレーブ
同様の値に設定されます。
"ストリーミングレプリーシ""SR"表記します。
"レプリーションスロッ""ロット"と表記します。
  説明の便宜上、以下の設定とします
5.2 構成デー
マスIPアドレス およびサーバ名 192.168.100.101/24 server1
レーブのIPアドレスおよびサーバ名 192.168.100.102/24 server2
ポート番号 5432
レプーション用ユーザ/パスワード repu ser/passw ord
PostgreSQL Enterprise Consortium
Page 18 of 285
5.3 SR構成の設定(マスタのp g_h b a.co n f)
h ost replication repu ser 192.168.100.101/32 tru st
h ost replication repu ser 192.168.100.102/32 tru st
またはCIDR指定にて
h ost replication repu ser 192.168.102.0/24 trust
SR用ユーザの接続を許可する
pg _h b a.con f両ノード共通の設定となる事から
 どちがマスっても使用できる定とする
IPアドレスはW AL転送を行うネットワークLAN指定。
 パブリッLAN以外にハートビートLAN力。
認証方式任意だが、passw ord md 5ではパスワードファイルり入力
めらいようにする。
5.4 SRの設定(マスpo stg resq l.con f)
listen _add resses '0.0.0.0' 接続を受け入れIPを指定。
再起動で反映。
w al_level replica W AL書かれ情報量を指定。
SR構成の場合は rep lica 設定。
デフォルトrep licaであめ変更不要
再起動で反映。
w al_keep_segmen ts 64 暫定値としてma x_w al_size/16MBの値設定。
ロットを使用する場合は設定不要。
ロードで反映。
syn ch ro n o u s_co mmit on 目的に応じて設定る。
remote_apply : 完全同期。W AL適用でを保証。
on : 同期。W AL転送後のディスへの書き込みまで保証。
remote_w rite : 準同期W AL転送後のメリ書き込みまで保証。
lo ca l : 非同期ローカルへの書込みまで保証(リモトは保証しない)
off : 完全非同期。ローカルへの書き込みも保証しない。
同期式におけレーブ障害時および復旧時の同期/非同期の切り替え
syn ch ro n o u s_stan d b y_n ames行う。本パラータ固定。
ロードで反映。
syn ch ro n o u s_stan d b y_n ames ''同期) SRの非同期と同期切り替えに使用。
非同期の場合 : ''
同期の場 : '*' あるいは特定スレーブのapp licatio n _n ame
ロードで反映。
max_w al_send ers 10 起動するw al sen ders数を指定。
pg _b aseb acku pW ALストリーミングを指定する場合はその分も考慮
通常はデフォルトの10で問題ない。
再起動で反映。
max_replication _slot 10 レプーションスロットを作成可能最大数
通常はデフォルトの10で問題ない。
再起動で反映。
restart_after_crash off on の場合インスタンス障害(po stg resプロセスは残存)の場合に、自動的に再起動
シングル構成で便利な機能であるが、SR構成では管理が複雑化するめ、off設定
するが一般的。
ロードで反映。
PostgreSQL Enterprise Consortium
Page 19 of 285
5.5 SRの設定(スレーブのpo stg resql.con f)
h ot_stan db y on ホットスタンバイとして参照可能状態で起動する
レーブに対しても監視SQ Lを実行できるよう通常は有効化する
デフォルトon であるため、変更は不要。
h ot_stan db y_feedback on o n 場合、スレーブが現在処理している問い合わせについて、マスタへフィー
ドバッを送る
通常は有効化する。特にスロットを作成する合に有効化が必須
デフォルトoffであるめ、変更が必要。
5.6 SRの設定(スレーブのrecovery.co n f)
stand b y_mode on レーブとして起動か、PITRのリカバリ処理か区別をする定。
on の場合、スレーブとして起動する。W ALファルの最後に達してもリカバリ
を終了せず、マス接続してW ALセグメント取得を継続。
primary_co n n info 'h o st=server1 po rt= 5432
u ser= repu ser
passw ord = p assw ord
applicatio n _n ame=server2'
マスへの接続文字列を指定。
h ostW AL転送行うLANを指定。2サーバ間の転送のみである事から
ハートビートLANでも良い。
po rtPo stg reSQ Lがリスニングしているポート番号(p o rtパラメータ)
u serreplication 仮想データベースへ接続できるユーザを指定(ユーザの
replica tion 属性おpg _h b a.con fの設定)
passw ord はパスワードが必要場合に設定。パスワードの記載を避けた
場合は、~ /.pgpassを使用。
applicatio n _n ame視認性を高めるのが目的であり必須ではな
スレーブ名を指定。
デフォルト'w al_receiver'
recovery_targ et_timelin e latest カバリが作成する個別のイムラインを指定。
SR構成ではlatestを指定して最新タイムラインを追従。
primary_slot_n ame <スロッ> 当該スレーブ用のスロットを作成してい場合は、スロット名設定。
最新バージョンではロットを作成するのが一般的
restore_co mman d アーカイブW ALイルの
ピー)方法を指定
ロットを使用している場合は設定不要
2. 構築手順
では基本的2ノード構成における手順を記載します
5.7 SR構成条件
同期方式 非同期(syn ch ro n o u s_stan d b y_n ames = '')
レプーションスロッ 使用しない
(1)プリーシンユーザ作成
マスサーでレプリーション用のユーザを作成します
postgres=# CREATE ROLE repuser LOGIN REPLICATION PASSWORD 'password';
(2)設定フイルの変更
マス$PGDATA配下のp g_h b a.co n fpo stg resql.con fを変更します
pg _h b a.con f
PostgreSQL Enterprise Consortium
Page 20 of 285
レプーションユーザがデータベー接続できるよpg _h ba.co n fを次のよ設定します。 こで便宜上、trust認証を
指定しています。 md5認証を指定する場合はパスワドファイル(~ /.p g p ass)を使用して、パスワードの入力が不要となる
設定します。
$ vi $PGDATA/pg_hba.conf
[pg_hba.conf]
# デフォルトで以下の設定が登録さていす。
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust
# 以下の様に変更します。
host replication repuser 192.168.100.100/32 trust
host replication repuser 192.168.100.101/32 trust
host replication repuser 192.168.100.102/32 trust
po stg resq l.con f
マスして稼働させるめ、po stgresq l.con fを次のよ設定します。 レーブ側の設定も含めておきます。スレーブ側の
設定は、マス側では無視されます。
$ vi $PGDATA/postgresql.conf
[postgresql.conf]
port = 5432 (デフォルト)
listen_addresses = '*'
wal_level = replica (デフォルト)
synchronous_commit = on (デフォルト)
synchronous_standby_names = '' (デフォルト)
max_wal_senders = 10 (デフォルト)
max_replication_slots = 10 (デフォルト)
restart_after_crash = off
hot_standby = on (デフォルト)
hot_standby_feedback = on
パラメーの記述後、設定ファルの変更を反映するめにPostg reSQ Lを再起動します
$ pg_ctl restart
(3)pg_basebacku p よる物理ファイルのコピー (スレーブ)
レーブ側でpg_baseb acku p を実行し、スレーブデータベーを構築します
$ pg_basebackup -h <マスIP> -p 5432 -U repuser -D $PGDATA --progress --
verbose
おパスワードファイルはpg_baseb acku p ピーされないため、必要に応じてピーします
$ scp <IP>:~/.pgpass ~/
(4)reco very.con fの設定(スレーブ)
pg _b aseb acku pで取得したデータベースクラスタの設定を変更し、スレーブとして稼働するようします 取得($PGDATA)配下
recovery.con fを作成します なおスレーブに必要なパータ設定は(po stg resql.con f)は、マスタ側で設定済みのファイルがコ
ピーされているため、変更不要です。
PostgreSQL Enterprise Consortium
Page 21 of 285
recovery.con f
PG D ATA配下にreco very.con f作成し以下を記述します。
$ vi $PGDATA/recovery.conf
[recovery.conf]
standby_mode = 'on'
primary_conninfo = 'host=server1 port=5432 user=repuser
password=repuser'
recovery_target_timeline = latest
(5)Po stgreSQ Lの起動(スレ
レーブのPostgreSQ Lを起動します。
$ pg_ctl start
(6)状況確認(マス
SR構築さいること確認しす。
[マス側で確認]
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 40724
usesysid | 16385
usename | repuser
application_name | walreceiver
client_addr | <レーブのIP>
client_hostname |
client_port | 48077
backend_start | 2018-01-04 01:30:54.01041+09
backend_xmin |
state | streaming
sent_lsn | 0/3000060
write_lsn | 0/3000060
flush_lsn | 0/3000060
replay_lsn | 0/3000060
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
(7)状況確認(スレーブ)
PostgreSQL Enterprise Consortium
Page 22 of 285
[スレーブ側で確認]
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_stat_wal_receiver;
-[ RECORD 1 ]---------+--------------------------------------------------
pid | 52484
status | streaming
receive_start_lsn | 0/3000000
receive_start_tli | 1
received_lsn | 0/3000140
received_tli | 1
last_msg_send_time | 2018-01-04 01:35:50.514256+09
last_msg_receipt_time | 2018-01-04 01:18:46.923761+09
latest_end_lsn | 0/3000140
latest_end_time | 2018-01-04 01:33:20.23195+09
slot_name |
conninfo | user=repuser password=******** dbname=replication
host=<マスタのIP> port=<マスのポート番号>
fallback_application_name=walreceiver
sslmode=disable sslcompression=1
target_session_attrs=any
con n in fo 実際に1行で表示されますが、便宜上改行してす。
5.2.3.
2ノード構成からレーブ(server3)を追加する方法は、基本的には前述の手順と同様です。 複数スレーブ方式とカスケード方式の違いはserver3側でpg_baseb ack u p
を実行するのは同様で、マスの指定の違いだけで ード方式で、マ負荷をかけないというットがあります。
1. pg _b aseb acku pの実行server3)
複数スレーブ構成:sever1
$ pg_basebackup -h server1 -p 5432 -U repuser -D $PGDATA --progress --
verbose
カスケード構成 :マスserver2
$ pg_basebackup -h server2 -p 5432 -U repuser -D $PGDATA --progress --
verbose
2. recovery.con fの設定(server3)
recovery.con f
PG D ATA配下にreco very.con f作成しす。 カスケード方式の場合にserver2からピーさイルが存在
ので、それを修正します。 server2設定とほぼ同様で、異なるマスの指定です。
$ vi $PGDATA/recovery.conf
[recovery.conf]
複数スレーブ構成:sever1
primary_conninfo = 'host=server1 port=5432 user=repuser
password=repuser'
カスケード構成 :マスserver2
primary_conninfo = 'host=server1 port=5432 user=repuser
password=repuser'
5.2.4.
SR構成においてアーカイブモード運用は有力です。 レーブが物理バックアップとも言えますのでアーカイブモード運用は必須でありませんが、以下を目的として構成する
事もあります
PostgreSQL Enterprise Consortium
Page 23 of 285
PITR (Po in t In Time Recovery)一定の過去に戻す
 アーカイブモド運用の最大のメットと言えます。
 類似機能として「延レプーション」もありますが、PITRの方がより汎用的で
アーカイブW ALの保持
 フルバックアップ11回取得する場合、アーカイブW AL1日分(あるいはそ以上)保持することになります
 SRの伝搬の遅れが保持時間以内にっていれば、SRを継続できます。
 W ALを保持する機能として、レプリーシンスロットがあります
 SRを意識してW ALを確保する必要なW ALが欠落するリスはありません。
 ただし伝搬遅延が大きくりすぎた場合、W AL領域がディスルになるスクがあります。
 アーカイブモド運用の場合は定期的に削除るためそのリスクは低いと言えます。
1. 関連パラータ
既存のレプリーシンスロットの設定に加え、次のパラメータを指定します。
ァイ
マス po stg resq l.con f arch ive_mode o n アーカイブを有効化する
マス po stg resq l.con f arch ive_co mman d cp %p <アーカイブの保存先>/% f アーカイブの実行コマンドを指定する。
プトを指定する可能であめ、複雑な
処理を組み込む事が可能。
レー
recovery.con f restore_co mman d 'scp <マスのユーザ名> @ <マスのホ
> :< マスのアーカイディレクト> % f
%p'
マスのアーカイブを取得するマンドを指定
する W AL期を保証する場合に必要とな
る。しレプリーシンスロットを使用する
場合は不要である。
注釈
restore_co mman d scpマンドを使用する場合、スレーブはマスタのPo stgreSQ LO Sユーザに ssh パスワードなしで接続できるよう
る必要があります またアーカイブ・ディレNFSマウント等、マスタ/レーブ間で共有可能なパスする事で、 アーカイブの扱いが容
易になります。
障害時スレーブをマスタにする場合に備え、マスタに設定したパラータ スレーブ側でも事前に有効化するとを推奨します。
2. 設定手順
(1)側のp ostg resql.con fのパラメータを以下の設定する
$ vi $PGDATA/postgresql.conf
[postgresql.conf]
archive_mode = on
archive_command = 'cp %p <アーカイブの保存先>/%f'
(2)必要なばスレーブ側のrecovery.con fのパラメータ以下追加する。
$ vi $PGDATA/recovery.conf
[recovery.conf]
restore_command = 'scp <スタのユーザ名>@<マスのホスト名>:<マスのアーカイブ・ディレクト>%f %p'
(3)側を再起動し、その後スレーブ側を再起動する
[マス/スレブの両方で実施]
$ pg_ctl restart
(4)側で強制的にW ALイルを切り替え、アーカイブW ALァイルが出力されることを確認する
PostgreSQL Enterprise Consortium
Page 24 of 285
postgres=# SELECT pg_switch_xlog();
pg_switch_xlog
----------------
0/7017008
(1 row)
$ <アーカイブ・ディレクトリ>
000000010000000000000007
5.2.5.
レーブに未転送のW ALを保持するとでSRの維持を保証します。 アーカイ運用で同期の保証は可能ですが、アーカイブログ管理などが問題となり、 ノーアーカイ
ブ運用をしてい環境も多くあります。 そのよう環境において、レプリケーションの維持を保証するめに、レプリーシンストの設定が必要です。 またアーカイブ運用
おいても、アーカイブW ALファルの削除にSRの考慮が不要になるめ、有用な設定で
1. 関連パラータ
既存のレプリーシンスロットの設定に加え、次のパラメータを指定します。
基本的なSR 構築手順に設定済みのパラータも、改めて記載しています
5.8 レプーションスロットの設定
ファ
マス po stg resq l.con f max_replication _slots レーブ数以上(設定済み 作成可能なレプリーションスロッ数を指
定する
レー
po stg resq l.con f h o t_stan d b y_feedback o n 定済み レーブの状態をマスタにフィードバッ
る。
レー
recovery.con f primary_slot_n ame レプーションスロット名 使用するレプリケーションスロッ名を指定
する
注釈
障害時スレーブをマスタにする場合に備え、マスタに設定したパラータ スレーブ側でも事前に有効化するとを推奨します。
2. レプーションスロットの作成方法
レプーションスロットに関連る関数は以下の通りです。
5.9 レプーションスロットの関数
pg _create_p h ysical_replicatio n _slot(スロット名[,
tru e/false])
レプーションスロットを作成する
ロット名:成するレプリーシンスト名指定する。
tru e/falsetru eの場合、レプリーシンスロットは即座にW ALを保持する
falseの場合従来通り、スレーブがレプリケーションスロッに繋いだ時点から
W ALを保持する
pg _d rop_replication _slot(ロット名)
レプーションスロットを削除する
ロット名:除するレプリーシンスト名指定する。
3. 検証
(1)po stg resql.con fmax_replication _slots加え、設定反映のため再起動。
$ vi $PGDATA/postgresql.conf
[postgresql.conf]
max_replication_slots = 10 <--- デフォ
$ pg_ctl restart
PostgreSQL Enterprise Consortium
Page 25 of 285
(2)レプリケーションスロットを作成。
postgres=# SELECT pg_create_physical_replication_slot('slot1', true);
pg_create_physical_replication_slot
-------------------------------------
(slot1,0/B000220)
(1 row)
(3)レプリケーションスロットの作成確認。
postgres=# SELECT slot_name, restart_lsn, active FROM pg_replication_slots;
slot_name | restart_lsn | active
-----------+-------------+--------
slot1 | 0/B000220 | f
(1 row)
active列が'f'あるとから、まだ使用されいない。
restart_lsn列に値があることから、使用されていなくてもW ALの保持は開始している。
(4)レーブにてreco very.co n fp rimary_slot_n ame加え、設定反映のため再起動。
$ vi $PGDATA/postgresql.conf
[recovery.conf]
primary_slot_name = 'slot1'
$ pg_ctl restart
(5)側でレプリーシンスロットが使用されいることを確認。
postgres=# SELECT slot_name, restart_lsn, active FROM pg_replication_slots;
slot_name | restart_lsn | active
-----------+-------------+--------
slot1 | 0/B0002C8 | t
(1 row)
active列が't'であることから、使用されている。
5.2.6.
同期モードの懸念としてW AL送の待機によるパフォーマンスへの影響があります。 下の図はsyn ch ro n o u s_co mmitの各設定によるパフォーマンス比較です。(on
値を1.00とした相対値)
サーバススペッ
CPU  : In tel(R ) Xeon (R ) CPU E5-2640 v2 @ 2.00GHz 16Core
モリ : 64GB
O S  : Red Hat En terp rise Lin u x Server release 6.5 (Santiago)
Po stg reSQ Lのバージョン : Po stg reSQ L 9.6.1
パラメー設定
キャッシュヒット率の影響を受けないよほぼ100%るよ調整
shared_bu ffers : 8G B
処理中に自動VACUUM が発生しないよう無効化
au tova cu u m off
処理中にックポイントが発生しないように調整
ch eck p o int_timeou t 1h
max_w al_size :10G B
処理前に毎回手動でチックポイント実行
トランザクションツールはpgben ch を使用。
初期化スケール 100
100セッション、25ワーカスレッドのトンザクションを実施(p g ben ch -c 100 -j 25)
PostgreSQL Enterprise Consortium
Page 26 of 285
通常のO LTPアプリーシンではほど激しいトランザクションではないため、低下は限定的と考えらます
同期モードの実装あたって、実際のアプリケーションで検証して確認くい。
5.2.7.
レーブの適用を一時的に遅延させます。 マスの操作が即座に伝搬さのを防ぐのが目的です。 W AL転送までは遅延な処理さるため、データ保全には影響
ありません。 同期転送(syn ch rono u s_co mmit=o n )との組み合わせができます。
注意点
マスの切り替わり時に遅延分の適用が発生するため切り替わりに時間がかかります。
 高可用性用途には向いていません。
 複数スレーブ構成にて1台目位は同期、で2台目を遅延とするする構成が考えられます
以下の操作を行うと、遅延レプリーションの設定(reco very_min _app ly_delay)は無視さ最新の状態まで適用されます。注意下い。
 - 再起 (pg_ctl restart)
 - 昇格 (p g _ctl p romote)
完全同期(syn ch ro n ou s_co mmit= remo te_apply)ではDML(自動コットがオフの場合はCO M M IT待機するため、遅延レプリーションは使用できま
ん。
以下の検証を行います。
検証1: 遅延レプリケーションの設定および動作確認
     スレーブへの適用が指定した時間分、遅延する事。およびマスタでの遅延確認。
検証2: 問題発生前の状態まで適用
     オペレーションミ発生を想定し、発生前の状態まで適用し、昇格。
1. 関連パラータ
既存のレプリーシンスロットの設定に加え、次のパラメータを指定します。
5.10 遅延レプリーションの設定
レーブ po stg resq l.con f h ot_stan db y_feedback o n フィードバッを有効化)
レーブ recovery.con f reco very_min _app ly_delay 遅延させる時間を指定
2. 検証1遅延レプーションの設定および動作確
(1)ストに使用するーブルを作成。
マス
postgres=# CREATE TABLE delay_test(id integer, time1 timestamp);
postgres=# \d delay_test
Table "public.delay_test"
Column | Type | Modifiers
--------+-----------------------------+-----------
id | integer |
time1 | timestamp without time zone |
(2)レーブで遅延レプリーションの設定行い、再起動。
PostgreSQL Enterprise Consortium
Page 27 of 285
スレ
$ vi $PGDATA/postgresql.conf
[postgresql.conf]
hot_standby_feedback = on
$ vi $PGDATA/recovery.conf
[recovery.conf]
recovery_min_apply_delay = '60min'
$ pg_ctl restart
(3)ストテーブルにデータを追加。
マス
postgres=# INSERT INTO delay_test VALUES (1, localtimestamp);
postgres=# SELECT * FROM delay_test;
id | time1
----+----------------------------
1 | 2018-03-10 18:05:46.29221
(1 rows)
(4)レーブにて座に反映されない事を確認。
スレ
postgres=# SELECT * FROM delay_test;
id | time1
----+-------
(0 rows) <--- INSERTが反映されていない
(5)適用の遅延確認。
pg _stat_replication ビューのrep lay_lag列で確認
マス
postgres=# SELECT write_lag,flush_lag,replay_lag FROM pg_stat_replication ;
-[ RECORD 1 ]---------------
write_lag | 00:00:00.000323
flush_lag | 00:00:00.00048
replay_lag | 00:00:38.354572 <--- recovery_min_apply_delay達するまで適用を待機
(6)1時間経過後、スレーブにて適用さ事を確認。
スレ
postgres=# SELECT *,localtimestamp FROM delay_test;
id | time1 | localtimestamp
----+----------------------------+----------------------------
1 | 2018-03-10 18:05:46.29221 | 2018-03-10 19:06:10.521195
(q rows)
(7)適用の遅延がクリアた事確認。
PostgreSQL Enterprise Consortium
Page 28 of 285
マス
postgres=# SELECT write_lag,flush_lag,replay_lag FROM pg_stat_replication ;
-[ RECORD 1 ]---------------
write_lag |
flush_lag |
replay_lag |
3. 検証2問題発生前の状態まで適用
(1)ストテーブルにデータを追加。
マス
postgres=# INSERT INTO delay_test VALUES (2, localtimestamp);
postgres=# SELECT * FROM delay_test;
id | time1
----+----------------------------
1 | 2018-03-10 18:05:46.29221
2 | 2018-03-10 19:30:11.23870
(1 rows)
id = 2の更新(INSERT)オペレーションミスとみなし、スレーブを更新前の時点まで適用
(2)を停止。
$ pg_ctl stop
(3)レーブにて1件も反映さない事を確認。
スレ
postgres=# SELECT * FROM delay_test;
id | time1
----+-------
(0 rows) <--- INSERTが反映されていない
(4)レーブを停止。
$ pg_ctl stop
(5)レーブにてreco very.co n f修正。
$ vi $PGDATA/recovery.conf
[recovery.conf]
restore_command = 'cp <$PGDATAパス>/pg_wal/%f %p' <--- WALのパスを指定
recovery_target_time = '2018-03-10 19:30:00' <--- id=2COMMIT直前の時
recovery_target_timeline = latest <--- 最新のタイムライン
recovery_target_action = 'promote' <--- 適用中断後、昇格
(6)レーブにて定時間までのリカバリおよび昇格(スレーブ新マス
PostgreSQL Enterprise Consortium
Page 29 of 285
$ pg_ctl start
$ pg_controldata | grep state <--- マス/レーブの確認
Database cluster state: in production <--- マス
5.11 遅延レプリーションのPITRログ
LO G : startin g po int-in -time recovery to 2018-03-10 19:30:00+09 recovery_targ et_time
LO G : reco very stopp in g b efore co mmit of tra n sactio n 578, time 2018-03-10 19:30:11.423701 id = 2CO MMIT時間
LO G : last co mp leted transaction w as at lo g time 2018-03-10 18:05:46.314276 id = 1CO MMIT時間
(8)新マスタにid = 1のみ適用されいること確認。
postgres=# SELECT * FROM delay_test ;
id | time1
----+---------------------------
1 | 2018-03-10 18:05:46.29221
(1 row)
5.2.8. WAL
Fu ll Page W rite(ポイント後の最初の更新時)W AL書き出すフページイメージを圧縮します 圧縮れたW ALは適用時に解凍されます。 W ALイル
のサイズが小さくなるため、書 が期待さす。 注意点とし圧縮処理および解凍処理が発生するめ、通常より余分にCPUを使用しま
す。 用にいてそれらを総合的に判断しす。 一般的な適用場面としSR構成において効果的と考えれます。 特に以下の構成で有力です。
同期モード(転送で)また完全同期モード(適用まで)
W AL転送の遅延を懸念して同期モード設定を躊躇する場面でW AL縮を検討します
非同期モードでもW AL圧縮は有力ですが、一定のW AL転送の遅延は許容されるため、
マスCPU 負荷を優先してW AL圧縮を適用しいという断も考えす。
レーブの遠隔地配置(ィザスタ・リカバリ
レーブを遠隔地に配置る構成において、非同期モードでもW AL転送の遅延が
許容範囲超える場合にW AL縮の適用を検討します。
1. 関連パラータ
既存のレプリーシンスロットの設定に加え、次のパラメータを指定します。
5.12 W AL圧縮の設定
マス po stg resq l.con f w al_co mp ressio n 'o n '
5.3. SR環境の監視
5.3.1.
5.3.1.1. 調調
SR構成のサーバログ監視にいて有益な情報を提示する事を目的としています。
以下の挙動時にサーバログ出力さッセージを確認しした
マスの起/停止
レーブの起動/停止
カスケードスレーブの起動/停止
マス側のW AL利用による(ロット不使用
カスケードスレーブ構成時のスレーブ側のW AL再利用によるロスト(スロッ不使用)
以下のパターンで検証しました。
レプーション操作ロ力無効時(ォルト
PostgreSQL Enterprise Consortium
Page 30 of 285
lo g _replication _co mmand = off
レプーション操作ロ力有効時
lo g _replication _co mmand = on
5.3.1.2. 調調
マス側またスレーブ側のサーバログに出力さるレプリーシン情報についてまとめます。
ホスト名、IPアドレス、ポート番号、ユーザ名、データベース名は例です。
レプーション操作ロ力無効時(ォルト
5.13 デフォルトで出力さる情報
レーブ停止時 マス レーブが複数台存在し、Q u o rum-based 同期レプリーションを設定していない場合に
片系スレーブの起動また停止を行うとで同期優先順位が変化し場合のみれます。
STAR T_REPLICATIO N 0/57000000 TIM ELINE 1
マス停止 レーブ エラーメッセージが繰り返し出力されます。
LO G : in valid record len gth at 132/EF 8AD7F0: w an ted 24, go t 0
FATAL: could not connect to th e primary server: cou ld n o t co n n ect to server: Con n ectio n refu sed
    Is th e server run n in g o n h o st "master" (192.168.100.100) and acceptin g
    TCP/IP co n n ectio n s o n po rt 5432?
W AL再利用による
ロスト
マス エラーセージが繰り返し出力さす。
ERRO R : req u ested W AL seg men t 0000001100000132000000EF h as already been removed
W AL再利用による
ロスト
レーブ エラーメッセージが繰り返し出力されます。
LO G : started streamin g W AL fro m p rimary at 132/EF000000 o n timelin e 17
FATAL: could not receive data from W A L stream: ERRO R : requ ested W AL seg men t
0000001100000132000000EF has already been removed
レプーション操作ロ力有効時
  デフォルトで出力さ情報に加え、以下が出力さす。
5.14 監視強化時に出力さ情報
レーブ起動ま
停止時
マス スレーブが複数台存在し、Q u o ru m-based 同期レプリーシンを定していない場合に
片系スレーブの起動また停止を行うとで同期優先順位が変化し場合のみ出力さす。
LO G : received rep licatio n comman d: IDENTIFY_SYSTEM
LO G : received rep licatio n comman d:
STAR T_REPLICATIO N 0/57000000 TIM ELINE 1
W AL再利用に
よる
マス、スレーブ(
レーブ出力はカス
ード・レプリ
ション時のみ)
エラーメッセージが繰り返し出力されます。
LO G : received rep licatio n comman d: IDENTIFY_SYSTEM
LO G : received rep licatio n comman d: START_REPLICATIO N 134/4A000000 TIM ELINE 17
5.3.1.3. 調調
SR関連のエラーが発生した場合は、デフォルトの設定(log_min _messages= 'w arn ing ')でサーバログに出力さます
表の太字の文字が監視キーード候補です。
マスが停止するとスレーブ出力がありすが、レーブが単一の構成時にはスレーブが停止してもマ出力はありませんでした
lo g _replication _co mmand よる出力はそれほど多くなく監視に対する影響は限定的で
ードで反映できると合わせ、気軽に有効化できるとも言えます
lo g _min _message = D EB U G [1-5] ()DEBU G1DEB U G 2 ることでもレプリーション関連のメッセージが出力さます
し影響が大きいため、通常はlo g_replication _comman d を使用しす。
lo g _replication _co mmand よる出力は、スレーブのw al receiverロセスからィードバッれた情報で
lo g _lin e_prefixap p lication _name(%a)を設定する事で確認できます
SQ LSTATEの値をキーワードに監視を行うために、lo g_lin e_prefixパラメータSQ LSTATE (%e)を設定しす。
5.3.2.
非同期レプリーシンを構成した場合ハードやNW 構成、利用状況によって
マスレーブの同期状況が変化します。
の状態を監視し、同期の遅延が許容範囲内であるかを確認します。
PostgreSQL Enterprise Consortium
Page 31 of 285
構成:
マス下に1台または2台のスレーブ構成
マス、スレーブに加えードスレーブをスレーブ下に構成する3台構
カスケード・レプーション)
バージョン:Po stgreSQ L 10
同期モード:問わない
5.3.2.1.
(1)W ALの書込み位置による同期遅延量を用いて監視する可能か
2014年度W G3活動報告書- 可用性 -での検証結果をベース実施します。
マスW ALとスタンバが適応したW AL2つの差分は
マスの最W ALの書き込み位(LSNLog Seq u en ce Numb er)
ンバイが適用したW ALの位置(LSN)との差分より算出します。
マスLSNは、pg _cu rren t_w al_in sert_lsn ()数が返す現在のW ALの挿入位置とみします
ンバイのLSNは、統計情pg _stat_replicatio n ューのreplay_lsn を使用しす。
2LSNの差分をバト単位で表示するめにpg_w al_lsn _diff数の引数にそれぞれを格納し
その結果が許容値を超過するかどうかで監視を行います。
検証には、以下シェルスクプトで実施しました。
監視通知部については、テストの為、標準出力のみとしています
PostgreSQL Enterprise Consortium
Page 32 of 285
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/bin/sh
HOST=localhost
LIMIT=1
SLEEPTIME=2
ALERT="echo"
SLAVENUM=2
function send_alert(){
${ALERT} $1
}
IFS_DEFAULT=$IFS
while :
do
val1=$(psql -h $HOST -p 5432 -U postgres -q -t -c "select current_time;")
case $(psql -p 5432 -U postgres -q -t -c "SELECT pg_is_in_recovery();"
|awk '{print $NF}') in
t)
val2=$(psql --no-align -h $HOST -p 5432 -U postgres -q -t -c
"select client_addr,pg_wal_lsn_diff(master,replay_lsn)
as replaydiff from (select pg_last_wal_replay_lsn() master)
as m,pg_stat_replication;")
;;
f)
val2=$(psql --no-align -h $HOST -p 5432 -U postgres -q -t -c
"select client_addr,pg_wal_lsn_diff(master,replay_lsn)
as replaydiff from (select pg_current_wal_insert_lsn() master)
as m,pg_stat_replication;")
;;
esac
rownum=$(psql --no-align -h $HOST -p 5432 -U postgres -q -t -c
"select client_addr,pg_wal_lsn_diff(master,replay_lsn)
as replaydiff from (select pg_current_wal_insert_lsn() master)
as m,pg_stat_replication;" |wc -l)
for slave_lsn in ${val2};
do
if [ ${rownum} -ne ${SLAVENUM} ]; then
send_alert "Slave Down |${val1}"
fi
IFS=$'|'
byte=`echo ${slave_lsn} | awk '{print $NF}'`
if [ ${byte} -gt ${LIMIT} ]; then
send_alert "Replication Delay ${val1},${slave_lsn}"
fi
IFS=${IFS_DEFAULT}
sleep ${SLEEPTIME}
done
done
今回の検証でスレーブが複数存在する場合も、それぞのスレーブの遅延状況を検知するとが可能であとがわかりました。
監視シェルを実行中insert文を実行した結果を記載します。
以下の通り、遅延状況を検知でき、ールサーバ等に連携することで監視するとが可能です。
また間接的に更新待ち監視も行うことがでます。詳細は、新・読取監視の項に記載します。
PostgreSQL Enterprise Consortium
Page 33 of 285
$ ./delay_test.sh
Replication Delay 20:58:18.451839+09,192.168.100.101 11880
Replication Delay 20:58:18.451839+09,192.168.100.102 11880
Replication Delay 20:58:22.484532+09,192.168.100.101 11880
Replication Delay 20:58:22.484532+09,192.168.100.102 11880
Replication Delay 20:58:26.512656+09,192.168.100.101 12048
Replication Delay 20:58:26.512656+09,192.168.100.102 12048
Replication Delay 20:58:30.538009+09,192.168.100.102 12048
尚、カスケードスレーブ構成の場合にスレブ上で同シェルスクリプトを実行することで
カスケードスレーブとの同期の遅延状況を検知するが可能です。
5.3.3.
非同期レプリーシンを構成した場合ハードやNW 構成、利用状況によってスタとスレーブの同期状況が変化します。
の状態を監視し、同期の遅延が許容範囲内であるかを確認します。
3ノード構
1. 複数スレーブ方式( - 1 , 2 スレーブ2はマスと繋がっている
2. カスケード方式( - - 孫) レーブ2スレーブ1と繋がってい
同期モード:同期は完全同期 (syn ch ro n ou s_co mmit = on / remote_apply)
5.3.3.1.
(1)Po stgreSQ Lの機能により監視する可能か
- 検証方法
 Po stgreSQ Lの内部パラメー(statemen t_timeou t)より、マスタへの更新処理に対し
 スレーブ停止によって一定時間応答がな場合に接続を切断し、アラート通知するとは可能かを検証を行いました
 statemen t_timeou tpo stgresql.co n f内での設定は推奨さていい為、SQ L行時に設定しました
 まpg_stat_rep licatio n ューにより間接的に、検知できなかについ検証を行いました。
- 検証結果
statement_timeout設定しSQ Lを発行しましたが、有効に機能
Ctrl+ Cをキーインするまで停止しいとい結果となりました。
複数台のレーブのうち1つで稼働している場合には設定時間を待た
PostgreSQL Enterprise Consortium
Page 34 of 285
一方のスレーブの応答をもって処理が完了してしまうめ、他のスレーブの同期遅延の検知がでないという結果とりました
$ psql -U postgres -d testdb -q -t << EOF
> \timing on
> SET statement_timeout TO 5000;
> insert into test(id) values(1);
> delete from test where id=1;
> EOF
時間: 0.192 ms
^CCancel request sent
WARNING: canceling wait for synchronous replication due to user request
DETAIL: The transaction has already committed locally, but might not have been
replicated to the standby.
時間: 13626.496 ms
$ psql -U postgres -d testdb -q -t << EOF
> \timing on
> SET statement_timeout TO 5000;
> insert into test(id) values(1);
> delete from test where id=1;
> EOF
Time: 0.147 ms
Time: 1.899 ms
Time: 1.277 ms
 pg_stat_rep licatio n ューについては、スレーブサーバ停止時にレコードが取得できなる為
 この点利用することで間接的に、同期待ちを検知するとが可能であるとがわかります
testdb=# select * from pg_stat_replication;
pid | usesysid | usename | application_name | client_addr | client_hostnam
e | client_port | backend_start | backend_xmin | state | sen
t_lsn | write_lsn | flush_lsn | replay_lsn | write_lag | flush_lag | flush_lag |
sync_priority | sync_state
-------+----------+---------+------------------+----------------+---------------
--+-------------+-------------------------------+--------------+-----------+----
-----------+----------------+----------------+-----------------+---------------+
------------
(0 )
(2)O Sマンドなどの外部機能により、更新処理に対して一定時間応答がない場合を監視する
 スレーブが単一であれtimeou tコマンドにより、指定秒数で強制切断に成功し、
 スンバイと同期が取れいないメッセージが出力さます
 ま終了値とし124が返却さいる為、全てのスレーブが応答できない場合に限り
 メッセージ内容また、終了値を制御するでスレーブサーバ障害による同期待を検知するが可能です。
PostgreSQL Enterprise Consortium
Page 35 of 285
$ timeout -sINT 5 psql -U postgres -d testdb -q -t << EOF
> \timing on
> insert into test(id) values(1);
> delete from test where id=1;
> EOF
Cancel request sent
WARNING: canceling wait for synchronous replication due to user request
DETAIL: The transaction has already committed locally, but might not have been
replicated to the standby.
Time: 4994.166 ms (00:04.994)
[postgres@test_pg01 data]$ echo $?
124
 しかし statemen t_timeou t設定による検証のケースと同様に、複数台のスレのうち1でも稼働してい場合に
 設定時間を待た一方のスレーブの応答をもって処理が完了してしまうめ、
 他のスレーブの同期遅延の検知ができないという結果とりました
$ timeout -sINT 5 psql -U postgres -d testdb -q -t << EOF
> \timing on
> insert into test(id) values(1);
> delete from test where id=1;
> EOF
Time: 2.382 ms
Time: 1.246 ms
[postgres@test_pg01 data]$ echo $?
0
5.3.4.
5.3.4.1. 調 調
SR構成において、通常はマスの障害を検知した場合にスレーブを昇格させます。まりマス常に1台のみです。 しオペレーションミスにより、マスタが正常な状態
かかわらずスレーブを昇格させてしまうという事も有り得ます 稼働中のマスシングル)2台とい危険な状態になります。その状態をスプリットブレインと定義します
その場合でも全てのアプーションが元のマスのみ接続していれ問題ありませんが、 2台目のマスも接続が発生するとデータの整合性が損なわれてしまいます。
それを避けるためスプリッレイン状態にっていないかの監視の方法を検討します。
5.3.4.2.
以下の監視についてまとめます。
サーバログの監視
pg _co n trold ataマンドによる監視
pg _co n trol_recovery関数による監視
pg _is_in _recovery関数による監視
5.3.4.3.
pg _ctl p romo te マンドにより昇格した場合、昇格したノードのサーバログに以下のメセージが出力さます timelin e ID した事が分かります。
received promote request
selected new timeline ID: XX
マス稼働中にレーブ側にのようッセージが出力されいないかを監視します
注意点
recovery.con f削除(また改名)後に再起動する事でマスシングル)して起動する方法もあります
timelin e ID の変化がな、特徴的なメセージは出力されません。状態変更の捕捉が困難で
5.3.4.4. pg_controldata
PostgreSQL Enterprise Consortium
Page 36 of 285
5.3.4.4. pg_controldata
pg _co n trold ataマンドは制御ファイル($PG DATA/g lobal/p g _co n trol)状態を表示します
以下に実行例示します。では環境変数LANGの設定により英語で表示しています
(実行例)
$ export LANG=C
$ pg_controldata
pg_control version number: 1002
Catalog version number: 201707211
Database system identifier: 6514575400714084610
Database cluster state: in archive recovery
~以下略
多数の項目がありますが、ここでは"Datab ase clu ster state"着目します。 必要な項目のみ抽出する例です
(スレーブでの実行例)
$ pg_controldata | grep "Database cluster state"
Database cluster state: in archive recovery
4類の状態がありす。
マス/レーブ
稼働中/停止中
5.15 Datab ase clu ster stateで表示さる値
( (
in pro du ction 運用中 マスして稼働中
in arch ive recovery アーカイブリカバリ レーブとして稼働中
shu t d o w n シャッダウン マスして停止中
shu t d o w n in recovery リカバリしながらシャッダウン中 レーブとして停止中
"in arch ive reco very"PITRとしてのリカバリ中の場合も含みますが、ここではスレーブ状態の意味です。
カスケード・レプーション構成の場合は、スレーブもリバリ中との取り扱いになる
カスケードスレーブと同様にレーブ状態に準じた状態が表示さます
両ノードとも"in pro d u ction "態でない事を確認します
ssh マンドでリモートの状態容易に取得できます。
注意点として、リモート側の環境変数を認識しないため、明示的に指定る必要があります
以下はローカルとモートで同一設定の前提です。
(スプットブレインの状態下での実行例)
$ ssh <remote> $PGHOME/bin/pg_controldata $PGDATA | \
> grep "Database cluster state"
Database cluster state: in production
5.3.4.5. pg_control_recovery
pg _co n trol_recoveryは制御ファイルの情報をpg _co n trold ataマンドに代わり取得する方法です。
取得できる項目は限らていすが、SELECT文で取得でるという特徴があります。
状態監視の選択肢の一つとして認識下さ
(スレーブでの実行例)
PostgreSQL Enterprise Consortium
Page 37 of 285
=# SELECT pg_control_recovery();
pg_control_recovery
-----------------------------
(0/5E0001B0,1,0/0,0/0,f)
(1 )
カンマ区切りにより5項目から構成さていす。何れpg_co n troldataマンドでも取得でます
5.16 p g _con trol_reco very関数の表示内容例
min _recovery_end _lsn 0/0 0/15000178
min _recovery_end _timelin e 0 1
backu p _start_lsn 0/0 0/0
backu p _end _lsn 0/0 0/0
end _o f_backu p _reco rd _required f f
min _recovery_end _lo catio n および min_recovery_en d _timelineにマスタとスレーブの違いが表れます。
pg _co n trold a taマンドによる監視と同様、カスケードレプーション構成の場合は
レーブもリカバリとの取り扱いにるため、例外的にードスレーブとの違いが表れません。
5.3.4.6. pg_is_in_recovery
カバリ中かどうかを示します。 スタであれば f (false) スレーブであれば t (tru e) を表示します
(スレーブでの実行例)
=# SELECT pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 )
両ノードとも f (false) 状態でない事を確認します
5.4. SR環境の障害時運用
5.4.1.
5.4.1.1.
マスへの障害発生時やアクセ不能時に、スレーブをマスタへ昇格さる処理を指します
新マスシングル構成であり、レプリケーションされいない片系運用の状態です。
レプーション構成への復旧に後述のイルバッを実行しますが
マスの障害がインスンス害など、データイルの障害でない場合は、イッチーバ」が可能な場合もあります。
5.4.1.2.
イルオーバにより片系運用にった後、再度レプリケーション構成に復帰さる処理を指します
シングル構成とった新マス、新スレーブを追加します
新マスと新スレーブを交代させてイルオーバ前に戻とまでは含まない事とします
複数スレーブ構成では、不要な処理となります
PostgreSQL Enterprise Consortium
Page 38 of 285
5.4.1.3.
マスレーブを入れ替える処理を指します
マスを停止し、スレーブを新マスへ昇格させ旧マスを新スレーブとして再追加しす。
マスのメンテナンスのための一時的な入れ替えどが目的です。
イルオーバーとの違いは、マス停止が障害による停止か計画停止かであり、スレーブ対する処理は同様です。
5.4.1.4.
イッチーバ後に、マス/レーブを入れ替えとを指します
マス/レーブとの関係性を除き処理内容は、スイッーバ」と同様です。
PostgreSQL Enterprise Consortium
Page 39 of 285
5.4.2. 2
前提 以降の手順では次の前提とします
Po stg reSQ L 10.1
マス、スレーブの2台構成(ホス名をそれぞ server1,server2表記する
同期モードは同期(syn ch ro n o u s_co mmit = on または remo te_apply)
レーブはトスタンバイ機能により参照可 (ho t_stand b y = on )
レプーション用のユーザは rep _user
マス/レーブともport5432を使用
レプーションスロット使
マス/レーブとも、環境変数PG D ATA,PG PO R Tは設定済み
死活監視実際の運用ではスタソフトを使用するのが一般的ですが、では便宜上手動で実施
サーバのNICパブリックのみ
仮想IPいて考慮し
対処一 大別する3種類の対処方法が考えます
PostgreSQL Enterprise Consortium
Page 40 of 285
5.17 障害別の対処
ID
pg_basebackup pg_rew ind使 使
1 マス マスレーブの関係が崩れており再構成が必要
物理障害
pro mo teを伴わないスレーブのマス(reco very.con f削除)
pg _b aseb acku pマンドを使用してフェイルバッ
2 マス マスレーブの関係巻き戻しで復旧可
非同期レプリーシンのインスンス障害(差異がある状態で昇格)
プリブレン状態での旧マスへの更新
pg _rew in dマンドを使用してスイッチバッ
3 マス マスレーブの切り替え可能
計画停止
同期レプリーションのインスンス障害(物理障害なし)
pg _rew in dマンドを使用しいでスイッバッ
4 スレ マスレーブの連携再開可能
レーブの障害
同期式の場合は非同期式に切り替え
5.4.2.1.
イルオーバについて記載します
マス、障害が発生した場合のレーブを新マスへ昇格したシングル構成図
(1) マスの疑似障害発生
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
マス実行しす。
$ pg_ctl -w -m immediate stop
$ kill -9 `head -1 $PGDATA/postmaster.pid`
(2) マスの死活監視にて異常を検知
死活監視の方法には多数ありますが、ここではpg_isread yンドを使用します
pg _isreadyマンドはイアンツールですので、任意のノードから実行でます
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - no response
(3) スレーブを新マスへ昇格
旧スレーブで実行します。
$ pg_ctl promote
※サーバログに下記内容が記載さ
"d a tab ase system is ready to accept co n n ection s"
しこの時点ではsyn ch ro n ou s_stan d b y_namesパラータ値が設定さいるめ、新マスで更新処理ができない状態で
PostgreSQL Enterprise Consortium
Page 41 of 285
(4) 新マスを非同期に切り替え
syn ch ro n o u s_stan d b y_n amesパラータの設定を''設定し、リロードで反映しす。
新マスで実行します。
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_standby_names = '*'
[編集後]
synchronous_standby_names = ''
$ pg_ctl reload
れで更新処理ができる状態になりました
(5) 新マスの死活監視にて正常を確認
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - accepting connections
以上でファイルオーバーは完了です。
5.4.2.2.
pg _b aseb acku pを使用したフェイルバッいて記載します。 初期構築手順とほぼ同じです。
マス障害発生によるフェイルオーバ後、旧マスを新スレとしたレプリーシン構成図
パラータ
pg _b aseb acku p必要な設定を記載します
5.18 p g _baseb acku p 必要設定
マス po stg resq l.con f listen _add ress 0.0.0.0 全てIPアドレス(v4)からの接続を受け付ける
マス po stg resq l.con f max_w al_send ers 2 W ALストリームオプションを付与する場合は、2以上を設定
p g _baseb acku p マンド
pg _b aseb acku pマンドの主なオプションは次の通りです。
PostgreSQL Enterprise Consortium
Page 42 of 285
5.19 p g _baseb acku p プショ
-D < d irecto ry> 出力を書き出すディレクトを指定。
-X < meth o d>
--w al-metho d = < meth o d>
必要なW ALファイルをバッアップに含める。metho d (収集方)は以下から選択。
fetch W ALファルは最後に収集
streamックアップ作成中に同時W ALをスームで収
運用中にp g _baseb acku p を実行する場合には stream を指定する
fetch 最後に収集)では、要なW ALファイルが削除される可能性があるため。
-S < slot_n ame>
--slo t=< slo t_n ame>
W ALーミングの収集に指定しプリーションスロットを使用。
-X stream とセットで指定
必要なW ALファイルが削除さるのを防ぐ事目的とする
運用中にp g _baseb acku p を実行する場合に使用を検討する
以下に注意する。
事前にレプリケーションスロッ作成する必要がある
マスW AL領域の空きが十分である事を確認する
-R
--w rite-reco very-co n f
最低限のreco very.con f作成。必要に応じてreco very.co n f加筆修正。
-r < rate>
--max-rate=< rate>
サーバから転送さデータの最大転送速度を指定。
運用中にp g _baseb acku p を実行する場合に使用を検討する
転送速度抑える事で、マ対する響を制限する事を目的とる。
-P 進行状況報告を有効化。
pg _b aseb acku p処理中におおよその進行状況を報告する
運用中に実行した場合、データベースクラスタのサイズが増加して進行状況が100%を超え場合があ
る。
-v 冗長モードを有効化。
進行状況報告も有効な場合、現在処理中のファイル名を出力。
pg _b aseb acku pでレプリーションスロッが使用できます。 W AL収集方式に stream を指定する事でW ALをほぼ確保できますが、スロットを指定するでより確実に
ります スロットを使用する運用であれ、この段階で作成るのが有力です。
フェイルバッ手順
pg _b aseb acku pスロットを指定する場合を記載しす。
(1) 旧マスのデータースを削除
旧マスて実行します
$ rm -rf $PGDATA/*
$PG DATA以外に表領域を作成している場合、そのファルも削除します
$PG DATAディレクトリを除する合はpostgresユーザで$PGDATAィレトリを作成できるよ
 親ディレトリのオーナーまたはパーミションを設定します
(2) レプリケーシンスロットの作成
新マスて実行します
PostgreSQL Enterprise Consortium
Page 43 of 285
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server1',true);  -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,144/EEFC8940)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots ;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
plugin |
slot_type | physical
datoid |
database |
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 144/EEFC8940 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(3) p g _basebacku p マンドにて、新マスからデータベースクをコピー
旧マスて実行します
$ pg_basebackup -h server2 -U rep_user -D $PGDATA -X stream -S slot_server1 -P -v -R
transaction log start point: 144/F3000028 on timeline 17
pg_basebackup: starting background WAL receiver
10503022/10503022 kB (100%), 1/1 tablespace
transaction log end point: 144/F3000130
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed
(4) recovery.con fの修正
旧マスて実行します
pg _b aseb acku p-Rオプションを指定した事で、reco very.con fが作成されます。
ロットを指定している事からprimary_slot_n ameの指定があります。以下を追記します
recovery_targ et_timelin eパラータ
primary_co n n infパラメータapp licatio n _nameを追加(任意/デフォルトはw alreceiver
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=rep_user host=server2 port=5432 sslmode=prefer sslcompression=1'
primary_slot_name = 'slot_server1'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=rep_user host=server2 port=5432 application_name=slave_server1
asslmode=prefer sslcompression=1'
primary_slot_name = 'slot_server1'
recovery_target_timeline = latest
(5) 旧マスp o stgresql.co n fの修正
旧マスて、パラータの調整を行います
syn ch ro n o u s_stan d b y_n amesパラータの無効化
pg _statsin foの無効化(有効化さてい場合)
同期レプリーションの設定無効化します
PostgreSQL Enterprise Consortium
Page 44 of 285
新スレーブのsh ared _prelo ad_lib rariesパラータ p g _statsinfoが設定さいる場合は、書き込みができずエラーが発生します
pg _statsin foの指定を削除します。
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_standby_names = '*'
shared_preload_libraries = 'pg_stat_statements,pg_statsinfo'
[編集後]
synchronous_standby_names = ''
shared_preload_libraries = ''
(6) 新スレーブの起動
新スレーブを起動しす。
$ pg_ctl start
(7) 新マスでのレプリーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 11262
usesysid | 16384
usename | rep_user
application_name | slave_server1
client_addr | <新スレーブIP>
client_hostname |
client_port | 44548
backend_start | 2017-03-22 06:36:06.362576+09
backend_xmin | 1781
state | streaming --- ストリーミング
sent_location | 0/10000060
write_location | 0/10000060
flush_location | 0/10000060
replay_location | 0/10000000
sync_priority | 2
sync_state | async --- 非同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
active | t --- ィブ
(8) レプリケーシン方式を同期式に変
新マスて、syn ch ro n ou s_stan d b y_n amesパラメータを設定し、リロードで反映します。
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_standby_names = ''
[編集後]
synchronous_standby_names = '*'
$ pg_ctl reload
PostgreSQL Enterprise Consortium
Page 45 of 285
$ psql -h server2 -U postgres postgres -c "SELECT * FROM pg_stat_replication" -x
-[ RECORD 1 ]----+------------------------------
pid | 11262
usesysid | 16384
usename | rep_user
application_name | s1
client_addr | <新スレIP>
client_hostname |
client_port | 44548
backend_start | 2017-03-22 06:36:06.362576+09
backend_xmin | 1781
state | streaming --- ーミング
sent_location | 0/10000060
write_location | 0/10000060
flush_location | 0/10000060
replay_location | 0/10000000
sync_priority | 2
sync_state | sync --- 同期
れに、以下の構成に復旧しました。
レプーションスロット使
同期式レプリーシン構成
5.4.2.3.
イッチーバについて記載します
スイッーバ手順
計画停止におけるマス/スレーブの切り替え手順です。 p g _baseb acku p pg_rew ind が不要であるためシンプルな手順です。
計画停止にてマスとスレーブの役割を切り替えレプリケーシン構成図
(1) マスの正常停止
マス実行しす。
$ pg_ctl stop -m fast
(2) スレーブの昇格
レーブにて実行しす。
以下の場合にpg _rew in d 不要で
計画停止
同期レプリーションのインスンス障害(物理障害なし)
$ pg_ctl promote
以降の手順はフェイルーバの場合と同様であるため省略します
3. レプーションスロットの作成
4. recovery.con fの作成
PostgreSQL Enterprise Consortium
Page 46 of 285
5. 旧マスpo stg resq l.con fの修正
6. 新スレーブの起動
7. 新マスでのレプリケーシン確認
8. レプーション方式を同期式に変更
(9) レプリケーシンスロットの削除(スレーブ)
イルオーバとの違いとしては、新スレーブに旧マス時代のスロットが残る事があります
restart_lsn列に値が残って状態では、マスタVACUU M 処理を阻害するなど
悪影響の可能性があるため、削除しす。
ロットの削除は関数で行うめ、スレーブでも実行可能です。
$ psql
=# SELECT pg_drop_replication_slot('slot_server2');
pg_create_physical_replication_slot
-------------------------------------
(1 row)
=# SELECT slot_name FROM pg_replication_slots ;
(0 rows)
以上でスイッチオーバが完了しました
5.4.2.4.
pg _rew in dを使用したスイッバッいて記載します。
pg _rew in dはタイムラインのずれたレプリケーションを再同期させる機能です。 実行後、ターゲットクソースと置き換えれた状態になります そのた
pg _rew in d後の操作は、通常のフェイルーバ時と同じで イムラインの分岐点からソースW ALを適用するめ、更新量が少なければpg_basebackよる
複製より高速で りフェイルオーバ時、旧マスを容易に新スレーブとして起動させるとができます
イッチーバー後に役割を元に戻したレプーション構成図
関連パラータ
pg _rew in d必要な設定を記載します
5.20 p g _rew ind 必要な設定
マス postgresq l.con f full_p age_w rites on ポイント後の更新時、ディスページの全内容をW AL書き込
む。
マス postgresq l.con f w al_log_h ints on ヒントビット更新時もfu ll_p age_w ritesを実行する
p g _rew indマンド
PostgreSQL Enterprise Consortium
Page 47 of 285
pg _rew in dマンドのの主なオプションは次の通りです。
5.21 p g _rew ind のオプション
D <ーゲットクスタ> pg _rew in dを実行し、ソーススタの内容に置き換えるクを指定する。
sou rce-server= "<ソース> "
同期対象であるソースクラスタを指定します。主に次の接続文字列を使用します。
h ostソースのホスト名またIPアドレス
po rtソースのポート番号
db n ameソースの接続先データベース名
u serソースクラスタの接続先ユーザ
P 進行状況レポートとして表示する
スイッバッ手順
※事前にマス/スレーブで(1) 関連パラメータの設定がされていることを前提とします
(1) 旧マスの正常停
pg _rew in dを使用する正常停止る必要があります
停止した旧マスタを一旦起動した後正常停止さます
障害により正常に起動や停止ができない状態ではp g _rew indは使用できません。
その場合は、pg _b aseb acku pを使用します。
$ pg_ctl start -w
$ pg_ctl stop -m fast -w
(2) p g _rew indの実
 旧マスタでp g_rew in d を実行する
$ pg_rewind -D $PGDATA --source-server="host=server2 port=5432"
servers diverged at WAL position 0/5015B70 on timeline 1
rewinding from last common checkpoint at 0/5015B00 on timeline 1
Done!
(3) スレーブのrecovery.con f編集
旧マスの$PG DATA配下にreco very.con f作成し以下を設定します。
$ vi $PGDATA/recovery.conf
[編集後]
standby_mode = 'on'
primary_conninfo = 'host=server2 port=5432 user=rep_user'
recovery_target_timeline = 'latest'
(4) 新スレーブを起動し、新マスタとタムラインID が揃っていることを確認する。
イムラインIDの取得には、p g _con tro ld ataマンドを使用する
厳密には最新チェックポイント実行時のタイムラIDであめ、
イムラインIDが揃っていないときは、マチェックポイント実行後、再確認します
ssh 経由で実行するで任意のノードから全データベースクラスタの情報が取得できる。
PostgreSQL Enterprise Consortium
Page 48 of 285
[新マス]
$ export LANG=C
$ pg_controldata | grep " TimeLineID"
Latest checkpoint's TimeLineID: 2
$ ssh server1 $PGHOME/bin/pg_controldata $PGDATA | grep " TimeLineID"
Latest checkpoint's TimeLineID: 2
p g _rew ind使用時の注意点
正常停止が必要
pg _rew in dを実行するデータベースクラスタ正常終了しなければいけません。
物理障害等にり正常停止できない場合p g _rew in d は使用できません。p g _basebacku p を使用します。
同一タイムランの場合は実施不
pg _p romoteを実行せず旧スレーブを新マスした場合、新マスのタイムインID は変わらないため、
新マスと旧マスのタイムラインIDは同じ状態です。
の場合は、p g _rew in d は実行できません。
実行時期と所要時間の関係
pg _rew in dよるイルバックの所要時間は2つの要素から構成さます
Step 1. pg_rew ind よる巻き戻し 旧マスW ALを使用)
Step 2. W AL用にる追い付き 新マスタのW ALを使用)
新マスで大量更新がある場合は、Step1は短時間で終了してStep2で時間がかかります
結果としp g _basebacku pの方が効率が良い場合もあり得ます。
また新マスタ昇格時W ALが削除さてい場合は、後述するよStep2ーとなる可能性あります。その場合はpg_basebacku p
が必要となります
pg _rew in dはフルオーバー後、あまり時間を置かず実行する事がポイントです。
旧マスW AL削除
旧マスの巻き戻しに必要な旧マスW ALが削除さいるいる場合、pg_rew in d は失敗します
例えば旧マが障害により大量更新の途中で異常終了した場合などに発生します
pg _rew in d実行時に次のようなエーが発生しす。
could not open file "/home/pg96/pg96_data/pg_xlog/0000000D00000002000000CF": No
such file or directory
could not find previous WAL record at 2/CF000140
Failure, exiting
pg _rew in dが成功するかどうかは検証(d ry-ru n オプション)事前に確認する事ができます
$ pg_rewind -D $PGDATA --source-server="host=server2 port=5432" --dry-run
servers diverged at WAL position 0/5015B70 on timeline 1
rewinding from last common checkpoint at 0/5015B00 on timeline 1
Done!
| メッセージはdry-runオプションが無い場合と同じです。
| pg_rewindでエラーが発生する場合(レーブのWAL削除)は、の検証にて確認できますが、
| pg_rewindでエラーが発生しないで、後から発生する場合(マスWAL削除)は検知できません。
| 検証の仕様にいて認識下さ
新マスW AL削除
pg _rew in d後、新スレは新マスタのW ALを適用するとで、新マス同期します。
新マス昇格時のW ALファルが残っていない場合、新スレーブは追い付きができず、次のエラーがサーバログ出力さ続けます
PostgreSQL Enterprise Consortium
Page 49 of 285
対策としプリションストの有効化が有力でが、新マスタのW AL領域の枯渇にご注意下さい。
ERROR: requested WAL segment 0000000D00000000000000F3 has already been removed
イムラインの巻き戻し
pg _rew in dPostgreSQ L9.6からイムラインの巻き戻しができるよになっています
れによりスプットブレインが発生しても、新マスをスレーブに戻すことが可能です。
pg _rew in dが不要な場合
pg _rew in dはターゲとソーススタのイムラインIDが分岐した場合に実行が必要です。
そのためタイムラインが枝分かれしなかった場合、pg_rew ind を実行する必要はありません。
例えpg_rew in d 実行時にのようなメッセージが出た場合、pg _rew in d は実行せずに、以降の操作を継続します
servers diverged at WAL position 0/503A428 on timeline 2
no rewind required
5.4.2.5.
レーブ障害時の緊急対応の必要性は、非同期モードが同期モードかによって異なります。
非同期モードの場合は、スレーブ障害がマスの更新処理を阻害しないため、緊急対応必要ありませ
とはいえ、シングル状態であるため早期プリーシン構成に復旧します。
同期モードの場合、ス
$ psql -h server1 -U postgres postgres -c "INSERT INTO test1_t VALUES ( 1 )"
Cancel request sent
WARNING: canceling wait for synchronous replication due to user request
DETAIL: ** The transaction has already committed locally, but might not have been replicated to
the standby. **
INSERT 0 1
Ctrl+Cキーインする等、意図的にキャンセルしない限り、応答が返ってきません。
そのため、直ち非同期に設定する必要があります
非同期への切り替え処理以降に示す様に再起動不要であるため、即時対応が可能です。
非同期への切り替えではな、スレーブの再起動を試み方法も考えれます。その方が効率的のよう考えます
即座に起動でその通りですが、起動に時間がかかる、あるいは物理的な障害で起動できな状態である事も考えます
そのような試行錯誤より、まずは確実にマスのハング状態解消を優先します
マスの復旧後は、スレーブの復旧試みます
物理障害により起動できない場合は、フイルバッ処理と同様の作業を行います。
(1) スレーブの疑似障害発
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
レーブにて実行しす。
$ pg_ctl -w -m immediate stop
(2) スレーブの死活監視に異常を検知
死活監視の方法には多数ありますが、ここではpg_isread yンドを使用します
PostgreSQL Enterprise Consortium
Page 50 of 285
pg _isreadyマンドはイアンツールですので、任意のノードから実行でます
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - no response
(3) 非同期ードに切り替え
syn ch ro n o u s_stan d b y_n amesパラータ''に設定する事で非同期の設定となります
$ vi $PGDATA/postgresql.conf
[変更前]
synchronous_standby_names = '*'
[変更後]
synchronous_standby_names = ''
$ pg_ctl reload
(4) 非同期ードの確認
レプーションモードが非同期(asyn c)変更れた事を確認します。
$ psql -At -c "SELECT sync_state FROM pg_stat_replication;"
async
れでスタが更新処理が可能な状態に復旧しました だしシングル状態であめ、フルオーバと同様の作業を行います
5.4.3.
同期モードにいて
レーブが複数ある場合、障害時にどのスレーブを新マスタに昇格するかが重要にります 基本的に同期運用しているスレーブを昇格すべきですが、同期対象も複数
選べるためどの同期スレーブを優先するが問題です。
れに対しPostgreSQ Lは、通常の同期運用では、同期優先度を明確にするで、昇格すべきスレーブを絞っています。 かし同期優先度が明確な場合、同期対象ス
レーブの性能に、マス大きく影響を受けます そのため複数同期において、最も処理が進んでいるスレーブを同期対象とするとでスレーブの影響を抑えォーラ
という機能が用意さいます
しクォーラムコットの場合、最も同期が進んでいるスレーブがその時によって異なるめ、運用に工夫が必要です。 性能面と運用面のトードオフを考慮した上で、同
期モードを選択する要があります
通常の同
synchronous_standby_names = 'FIRST X (standby_name1, standby_name2, ...)'
通常の同期モードで運用する場合、上記のようsyn ch ro n ou s_stan d b y_namesを設定します。 FIRSTは通常の同期モードの選択であり省略可能です。 数字X
同期対象のスレーブ数であり、カッコ内の左から順に優先して同期対象にります。 ッコ内のレーブ名は、期候補のスレーブです。
以下のよう設定の場合、slave13が同期運用、slave45潜在的な同期運用がさます 潜在的な同期運用は、普段は非同期として運用さ必要な場合
同期へ昇格さす。 例えslave2の環境がマスタから断された場合、残ったスレーブで優先度が高いslave1,slave3,sla ve4が同期運用れます。 (まり非同期
運用であったslave4が同期運用へ昇格さます)
synchronous_standby_names = 'FIRST 3 (slave1, slave2, slave3, slave4, slave5)'
障害発生時は、同期の優先度が高いスレーブをマスへ昇格させます 通常の同期モードではカッコ内の左側が優先度が高く、右に行くほど優先度が低くります。
ォーラムコミット
synchronous_standby_names = 'ANY X (standby_name1, standby_name2, ...)'
ォーラムコミットで運用する合、上記のようにsyn ch ro n o u s_stan d by_names定します ANYはクォーラムコットの選択であり、こ省略でません。 X
同期対象のスレーブ数であり、カッコ内のうX台のスレブの同期を待ちます カッコ内のスレーブ名は、同期候補のスレーブです。
以下のよう設定の場合、slave15の全てがクォーラムコットで運用されます マス側で更新があった場合、slave15のういずれか3台でスタから更新反映
PostgreSQL Enterprise Consortium
Page 51 of 285
が完了すれば、同期したとみなします
synchronous_standby_names = 'ANY 3 (slave1, slave2, slave3, slave4, slave5)'
障害発生時、新マへ昇格させるスレーブを選択するのには注意が必要です。 確認方法はSELECT p g_con trol_reco very();マンドにより現在のW AL置を比
較するとです。 同期が進んでいる側はW ALも進んでいす。により判断が可能です。
前提
以降の手順では次の前提とします。
Po stg reSQ L 10
マス2台スレーブの計3台構成(ホスト名をそれぞ server1,server2,slave3表記する
同期モードは同期(syn ch ro n o u s_co mmit = on または remo te_apply)
同期にはクォーラムコットを使用(syn ch ro n o u s_stan d b y_n ames = 'ANY 1 (slave_server2, slave_server3)'
レーブはトスタンバイ機能により参照可 (ho t_stand b y = on )
レプーション用のユーザは rep _user
マス/レーブともport5432を使用
レプーションスロット使
マス/レーブとも、環境変数PG D ATA,PG PO R Tは設定済み
死活監視実際の運用ではスタソフトを使用するのが一般的だが、では便宜上手動で実施
サーバのNICパブリックのみ
仮想IPいて考慮し
対処一 大別する4種類の対処方法が考えます
5.22 状況別の対処
ID
1 マス マスレーブの関係が崩れており再構成が必要
物理障害
pro mo teを伴わないスレーブのマス(reco very.con f削除)
pg _b aseb acku pマンドを使用してフェイルバッ
2 マス マスレーブの関係巻き戻しで復旧可
非同期レプリーシンのインスンス障害(差異がある状態で昇格)
プリブレン状態での旧マスへの更新
pg _rew in dマンドを使用してスイッチバッ
3 マス マスレーブの切り替え可能
計画停止
同期レプリーションのインスンス障害(物理障害なし)
pg _rew in dマンドを使用しいでスイッバッ
4 スレ マスレーブの連携再開可能
レーブの障害
同期式の場合、残ったレーブを同期式に切り替
5.4.3.1. ( )
イルオーバについて記載します
次のよう状況を想定しています。
server1:マス  障害により停止
server2:レーブ 新マスへ昇格
server3:レーブ マスからW AL転送が途絶えめ、更新が停止
マス、障害が発生した場合のレーブを新マスへ昇格したシングル構成図
PostgreSQL Enterprise Consortium
Page 52 of 285
(1) マスの疑似障害発生
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
マス(server1)にて実行します
$ pg_ctl -w -m immediate stop
$ kill -9 `head -1 $PGDATA/postmaster.pid`
(2) マスの死活監視にて異常を検知
死活監視の方法には多数ありますが、ここではpg_isread yンドを使用します
pg _isreadyマンドはイアンツールですので、任意のノードから実行でます
$ pg_isready -h server1 -U postgres -d postgres
server1:5432 - no response
(3) 昇格対象のスレ決定
ォーラムコミットの場合、現在のW AL位置を確認し、新マスへ昇格すべきスレーブを特定します
両方のスレーブ(server1,slave2)実行し結果を比較します。
※通常の同期モードでは、優先度の高いスレーブが昇格対象なため、本操作は必要ありません。
[server2]
=# SELECT pg_control_recovery();
pg_control_recovery
--------------------------
(0/1301F348,1,0/0,0/0,f)
(1 row)
[server3]
=# SELECT pg_control_recovery();
pg_control_recovery
--------------------------
(0/1301F170,1,0/0,0/0,f)
(1 row)
WALserver2進んでいるため、server2を昇格させる
server1:1301F348
server2:1301F170
(4) スレーブを新マスへ昇格
旧スレーブ(server2)実行します
$ pg_ctl promote
※サーバログに下記内容が記載さ
"d a tab ase system is ready to accept co n n ection s"
しこの時点ではsyn ch ro n ou s_stan d b y_namesパラータ値が設定さいる場合、新マスで更新処理ができない状態です。
(5) 新マスを非同期に切り替え
syn ch ro n o u s_stan d b y_n amesパラータの設定を''設定し、リロードで反映しす。
新マス(server2)で実行します。
PostgreSQL Enterprise Consortium
Page 53 of 285
$ vi $PGDATA/postgresql.conf
[編集後]
synchronous_standby_names = ''
$ pg_ctl reload
れで更新処理ができる状態になりました
(6) 新マスの死活監視にて正常を確認
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - accepting connections
以上でファイルオーバーは完了です。
5.4.3.2. ( )
pg _b aseb acku pを使用したフェイルバッいて記載します。 昇格されなかったスレーブは、新マスタのスレーブとして運用るために再設定が必要です。 旧マスから
新スレーブへの構築は初期構築手順とほぼ同じです。
マス障害発生によるフェイルオーバ後、旧マスを新スレとしたレプリーシン構成図
パラータ
pg _b aseb acku p必要な設定を記載します
5.23 p g _baseb acku p 必要設定
マス po stg resq l.con f listen _add ress 0.0.0.0 全てIPアドレス(v4)からの接続を受け付ける
マス po stg resq l.con f max_w al_send ers 2 W ALストリームオプションを付与する場合は、2以上を設定
p g _baseb acku p マンド
pg _b aseb acku pマンドの主なオプションは次の通りです。
PostgreSQL Enterprise Consortium
Page 54 of 285
5.24 p g _baseb acku p プショ
-D < d irecto ry> 出力を書き出すディレクトを指定。
-X < meth o d>
--xlog-meth o d = < metho d >
必要なW ALファイルをバッアップに含める。metho d (収集方)は以下から選択。
fetch W ALファルは最後に収集
streamックアップ作成中に同時W ALをスームで収
運用中にp g _baseb acku p を実行する場合には stream を指定する
fetch 最後に収集)では、要なW ALファイルが削除される可能性があるため。
-S < slot_n ame>
--slo t=< slo t_n ame>
W ALーミングの収集に指定しプリーションスロットを使用。
-X stream とセットで指定
必要なW ALファイルが削除さるのを防ぐ事目的とする
運用中にp g _baseb acku p を実行する場合に使用を検討する
以下に注意する。
事前にレプリケーションスロッ作成する必要がある
マスW AL領域の空きが十分である事を確認する
-R
--w rite-reco very-co n f
最低限のreco very.con f作成。必要に応じてreco very.co n f加筆修正。
-r < rate>
--max-rate=< rate>
サーバから転送さデータの最大転送速度を指定。
運用中にp g _baseb acku p を実行する場合に使用を検討する
転送速度抑える事で、マ対する響を制限する事を目的とる。
-P 進行状況報告を有効化。
pg _b aseb acku p処理中におおよその進行状況を報告する
運用中に実行した場合、データベースクラスタのサイズが増加して進行状況が100%を超え場合があ
る。
-v 冗長モードを有効化。
進行状況報告も有効な場合、現在処理中のファイル名を出力。
pg _b aseb acku pでレプリーションスロッが使用できます。 W AL収集方式に stream を指定する事でW ALをほぼ確保できますが、スロットを指定するでより確実に
ります スロットを使用する運用であれ、この段階で作成るのが有力です。
フェイルバッ手順
次のよう状況を想定しています。
server1:旧マス  新スレーブ
server2:旧スレーブ 新マス
server3:旧スレーブ 新スレーブ
pg _b aseb acku pスロットを指定する場合を記載しす。
(1) レプリケーシンスロットの作成
新マス(server2)にて実行します
$ psql
[server1:旧マス新スレーブ用のレプリーシンス]
=# SELECT pg_create_physical_replication_slot('slot_server1',true);  -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,144/EEFC8940)
(1 )
[server3:旧スレーブ新スレーブ用のレプリーションスロッ]
=# SELECT pg_create_physical_replication_slot('slot_server3',true);  -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server3,144/EEFC8940)
(1 )
PostgreSQL Enterprise Consortium
Page 55 of 285
(2) recovery.con fの修正
旧スレーブ(server3)実行しす。p rimary_co n n in fo記載する接続先マスの情報を新マスタ(server2)に書き換えます
またレプリーションスロッ名が変更されている場合、変更後の名前に合わせます。
$ vi $PGDATA/recovery.conf
[編集前]
primary_conninfo = 'user=rep_user host=server1 port=5432 application_name=slave_server3
asslmode=prefer sslcompression=1'
[編集前]
primary_conninfo = 'user=rep_user host=server2 port=5432 application_name=slave_server3
asslmode=prefer sslcompression=1'
(3) 新スレーブの起動
旧スレーブ(server3)実行しす。recovery.con f修正反映し新スレーブとして再起動します
$ pg_ctl restart
(4) 旧マスのデータースを削除
旧マス(server1)にて実行します
$ rm -rf $PGDATA/*
$PG DATA以外に表領域を作成している場合、そのファルも削除します
$PG DATAディレクトリを除する合はpostgresユーザで$PGDATAィレトリを作成できるよ
 親ディレトリのオーナーまたはパーミションを設定します
(5) p g _basebacku p マンドにて、新マスからデータベースクをコピー
旧マス(server1)にて実行します
$ pg_basebackup -h server2 -U rep_user -D $PGDATA -X stream -S slot_server1 -P -v -R
transaction log start point: 144/F3000028 on timeline 17
pg_basebackup: starting background WAL receiver
10503022/10503022 kB (100%), 1/1 tablespace
transaction log end point: 144/F3000130
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed
(6) recovery.con fの修正
旧マス(server1)にて実行します
pg _b aseb acku p-Rオプションを指定した事で、reco very.con fが作成されます。
ロットを指定している事からprimary_slot_n ameの指定があります。以下を追記します
recovery_targ et_timelin eパラータ
primary_co n n infパラメータapp licatio n _nameを追加(任意/デフォルトはw alreceiver
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=rep_user host=server2 port=5432 sslmode=prefer sslcompression=1'
primary_slot_name = 'slot_server1'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=rep_user host=server2 port=5432 application_name=slave_server1
asslmode=prefer sslcompression=1'
primary_slot_name = 'slot_server1'
recovery_target_timeline = latest
(7) 旧マスp o stgresql.co n fの修正
PostgreSQL Enterprise Consortium
Page 56 of 285
旧マス(server1)にて、パラメタの調整を行います
syn ch ro n o u s_stan d b y_n amesパラータの無効化
pg _statsin foの無効化(有効化さてい場合)
同期レプリーションの設定無効化します
新スレーブのsh ared _prelo ad_lib rariesパラータ p g _statsinfoが設定さいる場合は、書き込みができずエラーが発生します
pg _statsin foの指定を削除します。
$ vi $PGDATA/postgresql.conf
[編集後]
synchronous_standby_names = ''
shared_preload_libraries = ''
(6) 新スレーブの起動
新スレーブを起動しす。
$ pg_ctl start
(7) 新マスでのレプリーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 57 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 1866
usesysid | 16384
usename | rep_user
application_name | slave_server3
client_addr | ::1
client_hostname |
client_port | 46840
backend_start | 2018-02-13 14:06:04.475996+09
backend_xmin |
state | streaming --- ーミング
sent_lsn | 0/B067570
write_lsn | 0/B067570
flush_lsn | 0/B067570
replay_lsn | 0/B067570
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
-[ RECORD 2 ]----+------------------------------
pid | 1776
usesysid | 16384
usename | rep_user
application_name | slave_server1
client_addr | ::1
client_hostname |
client_port | 46838
backend_start | 2018-02-13 14:05:53.580727+09
backend_xmin |
state | streaming --- ーミング
sent_lsn | 0/B067570
write_lsn | 0/B067570
flush_lsn | 0/B067570
replay_lsn | 0/B067570
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]----
slot_name | slot1
active | t --- ィブ
-[ RECORD 2 ]----
slot_name | slot2
active | t --- ィブ
(8) レプリケーシン方式を同期式に変
新マスて、syn ch ro n ou s_stan d b y_n amesパラメータを設定し、リロードで反映します。
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_standby_names = ''
[編集後]
synchronous_standby_names = 'ANY 1 (slave_server1, slave_server3)'
$ pg_ctl reload
PostgreSQL Enterprise Consortium
Page 58 of 285
$ psql -h server2 -U postgres postgres -c "SELECT * FROM pg_stat_replication" -x
-[ RECORD 1 ]----+------------------------------
pid | 1866
usesysid | 16384
usename | rep_user
application_name | slave2
client_addr | ::1
client_hostname |
client_port | 46840
backend_start | 2018-02-13 14:06:04.475996+09
backend_xmin |
state | streaming --- ーミング
sent_lsn | 0/B067570
write_lsn | 0/B067570
flush_lsn | 0/B067570
replay_lsn | 0/B067570
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | quorum --- クォーラムコット
-[ RECORD 2 ]----+------------------------------
pid | 1776
usesysid | 16384
usename | rep_user
application_name | slave1
client_addr | ::1
client_hostname |
client_port | 46838
backend_start | 2018-02-13 14:05:53.580727+09
backend_xmin |
state | streaming --- ーミング
sent_lsn | 0/B067570
write_lsn | 0/B067570
flush_lsn | 0/B067570
replay_lsn | 0/B067570
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | quorum --- クォーラムコット
れに、以下の構成に復旧しました。
レプーションスロット使
同期式レプリーシン構成
5.4.3.3. ( )
イッチーバについて記載します
スイッーバ手順
計画停止におけるマス/スレーブの切り替え手順です。 p g _baseb acku p pg_rew ind が不要であるためシンプルな手順です。
次のよう状況を想定しています。
server1:マス  新スレーブ
server2:レーブ 新マス
server3:レーブ 新スレーブ
計画停止にてマスとスレーブの役割を切り替えレプリケーシン構成図
PostgreSQL Enterprise Consortium
Page 59 of 285
(1) マスの正常停止
マス(server1)にて実行します
$ pg_ctl stop -m fast
(2) スレーブの昇格
レーブ(server2)実行します。
以下の場合にpg _rew in d 不要で
計画停止
同期レプリーションのインスンス障害(物理障害なし)
$ pg_ctl promote
以降の手順はフェイルーバの場合と同様であるため省略します
3. レプーションスロットの作成
4. recovery.con fの作成
5. 旧マスpo stg resq l.con fの修正
6. 新スレーブの起動
7. 新マスでのレプリケーシン確認
8. レプーション方式を同期式に変更
(9) レプリケーシンスロットの削除(スレーブ)
イルオーバとの違いとしては、新スレーブ(server1)に旧スタ時代のスロットが残る事があります
restart_lsn列に値が残って状態では、マスタVACUU M 処理を阻害するなど
悪影響の可能性があるため、削除しす。
ロットの削除は関数で行うめ、スレーブでも実行可能です。
$ psql
=# SELECT pg_drop_replication_slot('slot_server2');
pg_create_physical_replication_slot
-------------------------------------
(1 row)
=# SELECT pg_drop_replication_slot('slot_server3');
pg_create_physical_replication_slot
-------------------------------------
(1 row)
=# SELECT slot_name FROM pg_replication_slots ;
(0 rows)
以上でスイッチオーバが完了しました
5.4.3.4. ( )
PostgreSQL Enterprise Consortium
Page 60 of 285
pg _rew in dを使用したスイッバッいて記載します。
pg _rew in dはタイムラインのずれたレプリケーションを再同期させる機能です。 実行後、ターゲットクソースと置き換えれた状態になります そのた
pg _rew in d後の操作は、通常のフェイルーバ時と同じで イムラインの分岐点からソースW ALを適用するめ、更新量が少なければpg_basebacku p
よる製より高速です。 れによりフェイルーバ時、旧マスを容易に新スレーブとして起動させるとができます。
イッチーバー後に役割を元に戻したレプーション構成図
関連パラータ
pg _rew in d必要な設定を記載します
5.25 p g _rew ind 必要な設定
マス postgresq l.con f full_p age_w rites on ポイント後の更新時、ディスページの全内容をW AL書き込
む。
マス postgresq l.con f w al_log_h ints on ヒントビット更新時もfu ll_p age_w ritesを実行する
p g _rew indマンド
pg _rew in dマンドのの主なオプションは次の通りです。
5.26 p g _rew ind のオプション
D <ーゲットクスタ> pg _rew in dを実行し、ソーススタの内容に置き換えるクを指定する。
sou rce-server= "<ソース> "
同期対象であるソースクラスタを指定します。主に次の接続文字列を使用します。
h ostソースのホスト名またIPアドレス
po rtソースのポート番号
db n ameソースの接続先データベース名
u serソースクラスタの接続先ユーザ
P 進行状況レポートとして表示する
スイッバッ手順
※事前にマス/スレーブで(1) 関連パラメータの設定がされていることを前提とします
(1) 旧マスの正常停
pg _rew in dを使用する正常停止る必要があります
停止した旧マスタを一旦起動した後正常停止さます
障害により正常に起動や停止ができない状態ではp g _rew indは使用できません。
その場合は、pg _b aseb acku pを使用します。
PostgreSQL Enterprise Consortium
Page 61 of 285
$ pg_ctl start -w
$ pg_ctl stop -m fast -w
(2) p g _rew indの実
 旧マスタでp g_rew in d を実行する
$ pg_rewind -D $PGDATA --source-server="host=server2 port=5432"
servers diverged at WAL position 0/5015B70 on timeline 1
rewinding from last common checkpoint at 0/5015B00 on timeline 1
Done!
(3) スレーブのrecovery.con f編集
旧マスの$PG DATA配下にreco very.con f作成し以下を設定します。
$ vi $PGDATA/recovery.conf
[編集後]
standby_mode = 'on'
primary_conninfo = 'host=server2 port=5432 user=rep_user'
recovery_target_timeline = 'latest'
(4) 新スレーブを起動し、新マスタとタムラインID が揃っていることを確認する。
イムラインIDの取得には、p g _con tro ld ataマンドを使用する
厳密には最新チェックポイント実行時のタイムラIDであめ、
イムラインIDが揃っていないときは、マチェックポイント実行後、再確認します
ssh 経由で実行するで任意のノードから全データベースクラスタの情報が取得できる。
[新マス]
$ export LANG=C
$ pg_controldata | grep " TimeLineID"
Latest checkpoint's TimeLineID: 2
$ ssh server1 $PGHOME/bin/pg_controldata $PGDATA | grep " TimeLineID"
Latest checkpoint's TimeLineID: 2
p g _rew ind使用時の注意点
正常停止が必要
pg _rew in dを実行するデータベースクラスタ正常終了しなければいけません。
物理障害等にり正常停止できない場合p g _rew in d は使用できません。p g _basebacku p を使用します。
同一タイムランの場合は実施不
pg _p romoteを実行せず旧スレーブを新マスした場合、新マスのタイムインID は変わらないため、
新マスと旧マスのタイムラインIDは同じ状態です。
の場合は、p g _rew in d は実行できません。
実行時期と所要時間の関係
pg _rew in dよるイルバックの所要時間は2つの要素から構成さます
Step 1. pg_rew ind よる巻き戻し 旧マスW ALを使用)
Step 2. W AL用にる追い付き 新マスタのW ALを使用)
PostgreSQL Enterprise Consortium
Page 62 of 285
新マスで大量更新がある場合は、Step1は短時間で終了してStep2で時間がかかります
結果としp g _basebacku pの方が効率が良い場合もあり得ます。
また新マスタ昇格時W ALが削除さてい場合は、後述するよStep2ーとなる可能性あります。その場合はpg_basebacku p
が必要となります
pg _rew in dはフルオーバー後、あまり時間を置かず実行する事がポイントです。
旧マスW AL削除
旧マスの巻き戻しに必要な旧マスW ALが削除さいるいる場合、pg_rew in d は失敗します
例えば旧マが障害により大量更新の途中で異常終了した場合などに発生します
pg _rew in d実行時に次のようなエーが発生しす。
could not open file "/home/pg96/pg96_data/pg_xlog/0000000D00000002000000CF": No
such file or directory
could not find previous WAL record at 2/CF000140
Failure, exiting
pg _rew in dが成功するかどうかは検証(d ry-ru n オプション)事前に確認する事ができます
$ pg_rewind -D $PGDATA --source-server="host=server2 port=5432" --dry-run
servers diverged at WAL position 0/5015B70 on timeline 1
rewinding from last common checkpoint at 0/5015B00 on timeline 1
Done!
| メッセージはdry-runオプションが無い場合と同じです。
| pg_rewindでエラーが発生する場合(レーブのWAL削除)は、の検証にて確認できますが、
| pg_rewindでエラーが発生しないで、後から発生する場合(マスWAL削除)は検知できません。
| 検証の仕様にいて認識下さ
新マスW AL削除
pg _rew in d後、新スレは新マスタのW ALを適用するとで、新マス同期します。
新マス昇格時のW ALファルが残っていない場合、新スレーブは追い付きができず、次のエラーがサーバログ出力さ続けます
対策としプリションストの有効化が有力でが、新マスタのW AL領域の枯渇にご注意下さい。
ERROR: requested WAL segment 0000000D00000000000000F3 has already been removed
イムラインの巻き戻し
pg _rew in dPostgreSQ L9.6からイムラインの巻き戻しができるよになっています
れによりスプットブレインが発生しても、新マスをスレーブに戻すことが可能です。
pg _rew in dが不要な場合
pg _rew in dはターゲとソーススタのイムラインIDが分岐した場合に実行が必要です。
そのためタイムラインが枝分かれしなかった場合、pg_rew ind を実行する必要はありません。
例えpg_rew in d 実行時にのようなメッセージが出た場合、pg _rew in d は実行せずに、以降の操作を継続します
servers diverged at WAL position 0/503A428 on timeline 2
no rewind required
5.4.3.5. ( )
レーブ障害時の緊急対応の必要性は、非同期モードが同期モードかによって異なります。
非同期モードの場合は、スレーブ障害がマスの更新処理を阻害しないため、緊急対応必要ありませ
とはいえ、シングル状態であるため早期プリーシン構成に復旧します。
同期モードの場合稼働しいるスレーブ数が、同期対象のスレーブ数より下回った場合、ス
PostgreSQL Enterprise Consortium
Page 63 of 285
$ psql -h server1 -U postgres postgres -c "INSERT INTO test1_t VALUES ( 1 )"
Cancel request sent
WARNING: canceling wait for synchronous replication due to user request
DETAIL: ** The transaction has already committed locally, but might not have been replicated to
the standby. **
INSERT 0 1
Ctrl+Cキーインする等、意図的にキャンセルしない限り、応答が返ってきません。
そのため、直ち非同期に設定する、また同期対象のスレブ数設定を減らす必要があります。
非同期への切り替え処理以降に示す様に再起動不要であるため、即時対応が可能です。
非同期への切り替えではな、スレーブの再起動を試み方法も考えれます。その方が効率的のよう考えます
即座に起動でその通りですが、起動に時間がかかる、あるいは物理的な障害で起動できな状態である事も考えます
そのような試行錯誤より、まずは確実にマスのハング状態解消を優先します
マスの復旧後は、スレーブの復旧試みます
物理障害により起動できない場合は、フイルバッ処理と同様の作業を行います。
(1) スレーブの疑似障害発
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
レーブにて実行しす。
$ pg_ctl -w -m immediate stop
(2) スレーブの死活監視に異常を検知
死活監視の方法には多数ありますが、ここではpg_isread yンドを使用します
pg _isreadyマンドはイアンツールですので、任意のノードから実行でます
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - no response
(3) 非同期ードに切り替え
syn ch ro n o u s_stan d b y_n amesパラータ''に設定する事で非同期の設定となります
$ vi $PGDATA/postgresql.conf
[変更前]
synchronous_standby_names = 'FIRST X (standby_name1, standby_name2, ...)'
[変更後]
synchronous_standby_names = ''
$ pg_ctl reload
(4) 非同期ードの確認
レプーションモードが非同期(asyn c)変更れた事を確認します。
$ psql -At -c "SELECT sync_state FROM pg_stat_replication;"
async
れでスタが更新処理が可能な状態に復旧しました だしシングル状態であめ、フルオーバと同様の作業を行います
PostgreSQL Enterprise Consortium
Page 64 of 285
5.4.4.
前提 以降の手順では次の前提とします
Po stg reSQ L 10.1
マス、スレーブ1、スレーブ23台のカスケード構成(ホスト名をそれぞ server1,server2,server3表記する
レーブ1が同期モード(syn ch ro n o u s_co mmit= o n , syn ch ro n o u s_stan d by_names= 'server2')
レーブ2が非同期モード(syn ch ron o u s_co mmit= o ff, syn ch ro n o u s_stan d b y_n ames= ''
レーブはトスタンバイ機能により参照可 (ho t_stand b y = on )
レプーション用のユーザは rep u ser
マス/レーブともport5432を使用
レプーションスロット使
マス/レーブとも、環境変数PG D ATA,PG PO R Tは設定済み
死活監視実際の運用ではスタソフトを使用するのが一般的ですが、では便宜上手動で実施
サーバのNICパブリックのみ
仮想IPいて考慮し
対処一 大別する3種類の対処方法が考えます
5.27 障害別の対処
ID
pg_basebackup pg_rew ind使 使
1 マス マスレーブの関係が崩れており再構成が必要
物理障害
pro mo teを伴わないスレーブのマス(reco very.con f削除)
pg _b aseb acku pマンドを使用してフェイルバッ
2 マス マスレーブの関係巻き戻しで復旧可
非同期レプリーシンのインスンス障害(差異がある状態で昇格)
プリブレン状態での旧マスへの更新
pg _rew in dマンドを使用してスイッチバッ
3 マス マスレーブの切り替え可能
計画停止
同期レプリーションのインスンス障害(物理障害なし)
pg _rew in dマンドを使用しいでスイッバッ
4 スレ1 マスとスレーブの連携再開可能
レーブの障害
同期式の場合は非同期式に切り替え
5 スレ1 マスとスレーブの連携再開不可能
レーブの障害
pg _b aseb acku pマンドを使用してフェイルバッ
6 スレ2 マスとスレーブの連携再開可能
レーブの障害
pg _rew in dマンドを使用しいでフェイルバッ
7 スレ2 マスとスレーブの連携再開不可能
レーブの障害
pg _b aseb acku pマンドを使用してフェイルバッ
8 マス、ス
レーブ1
マスレーブ2連携再開可
マス、スレーブ1の障害
pg _rew in dマンドを使用しいでフェイルバッ
9 マス、ス
レーブ1
マスレーブ2連携再開不可能
レーブの障害
pg _b aseb acku pマンドを使用してフェイルバッ
5.4.4.1.
イルオーバについて記載します
5.4.4.2.
PostgreSQL Enterprise Consortium
Page 65 of 285
マス(server1)にて、障害が発生した場合にレーブ1(server2)を新マスへ昇格した構成図
(1) マス(server1)の疑似障害発
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
マス(server1)にて実行します
$ pg_ctl -w -m immediate stop
$ kill -9 `head -1 $PGDATA/postmaster.pid`
(2) マス(server1)の死活監視に異常を検知
死活監視の方法には多数ありますが、ここではpg_isread yンドを使用します
pg _isreadyマンドはイアンツールですので、任意のノードから実行でます
$ pg_isready -h server1 -U postgres -d postgres
server1:5432 - no response
(3) スレーブ1(server2)新マスへ昇格
レーブ1(server2)実行します。
$ pg_ctl promote
※サーバログに下記内容が記載さ
"d a tab ase system is ready to accept co n n ection s"
(4) 新マス(server2)死活監視に正常を確認
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - accepting connections
(5) スレーブ2(server3)の死活監視を確認
$ pg_isready -h server3 -U postgres -d postgres
server3:5432 - accepting connections
(6) 新マス(server2)データ更新が行えとを確認
(7) スレーブ2(server3)にてデータが伝播されいること確認
以上でファイルオーバーは完了です。
5.4.4.3.
マス(server1)/スレーブ1(server2)サイトに障害が発生した場合のレーブ2(server3)新マスへ昇格し構成図
PostgreSQL Enterprise Consortium
Page 66 of 285
(1) マス(server1)の疑似障害発
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
マス(server1)にて実行します
$ pg_ctl -w -m immediate stop
$ kill -9 `head -1 $PGDATA/postmaster.pid`
(2) スレーブ1(server2)の疑似障害発生
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
レーブ1(server2)実行します
$ pg_ctl -w -m immediate stop
$ kill -9 `head -1 $PGDATA/postmaster.pid`
(3) マス(server1)スレーブ1(server2)の死活監視にて異常検知
死活監視の方法には多数ありますが、ここではpg_isread yンドを使用します
pg _isreadyマンドはイアンツールですので、任意のノードから実行でます
$ pg_isready -h server1 -U postgres -d postgres
server1:5432 - no response
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - no response
(4) スレーブ2(server3)新マスへ昇格
レーブ2(server3)実行します。
$ pg_ctl promote
※サーバログに下記内容が記載さ
"d a tab ase system is ready to accept co n n ection s"
(5) 新マス(server3)死活監視に正常を確認
$ pg_isready -h server3 -U postgres -d postgres
server3:5432 - accepting connections
(6) 新マス(server3)データ更新が行えとを確認
以上でファイルオーバーは完了です。
5.4.4.4.
イルバックにいて記載します。
5.4.4.5.
pg _b aseb acku pを使用したフェイルバッいて記載します。 初期構築手順とほぼ同じです。
PostgreSQL Enterprise Consortium
Page 67 of 285
マス障害発生によるフェイルオーバ後、旧マスを同期モード新スレーブとしたレプリケーシン構成図
関連パラータ
pg _b aseb acku p必要な設定を記載します
5.28 p g _baseb acku p 必要設定
マス po stg resq l.con f listen _add ress 0.0.0.0 全てIPアドレス(v4)からの接続を受け付ける
マス po stg resq l.con f max_w al_send ers 2 W ALストリームオプションを付与する場合は、2以上を設定
p g _baseb acku p マンド
pg _b aseb acku pマンドの主なオプションは次の通りです。
5.29 p g _baseb acku p プショ
-D < d irecto ry> 出力を書き出すディレクトを指定。
-X < meth o d>
--w al-metho d = < meth o d>
必要なW ALファイルをバッアップに含める。metho d (収集方)は以下から選択。
fetch W ALファルは最後に収集
streamックアップ作成中に同時W ALをスームで収
運用中にp g _baseb acku p を実行する場合には stream を指定する
fetch 最後に収集)では、要なW ALファイルが削除される可能性があるため。
-S < slot_n ame>
--slo t=< slo t_n ame>
W ALーミングの収集に指定しプリーションスロットを使用。
-X stream とセットで指定
必要なW ALファイルが削除さるのを防ぐ事目的とする
運用中にp g _baseb acku p を実行する場合に使用を検討する
以下に注意する。
事前にレプリケーションスロッ作成する必要がある
マスW AL領域の空きが十分である事を確認する
-R
--w rite-reco very-co n f
最低限のreco very.con f作成。必要に応じてreco very.co n f加筆修正。
-r < rate>
--max-rate=< rate>
サーバから転送さデータの最大転送速度を指定。
運用中にp g _baseb acku p を実行する場合に使用を検討する
転送速度抑える事で、マ対する響を制限する事を目的とる。
-P 進行状況報告を有効化。
pg _b aseb acku p処理中におおよその進行状況を報告する
運用中に実行した場合、データベースクラスタのサイズが増加して進行状況が100%を超え場合があ
る。
-v 冗長モードを有効化。
進行状況報告も有効な場合、現在処理中のファイル名を出力。
pg _b aseb acku pでレプリーションスロッが使用できます。 W AL収集方式に stream を指定する事でW ALをほぼ確保できますが、スロットを指定するでより確実に
ります スロットを使用する運用であれ、この段階で作成るのが有力です。
フェイルバッ手順
pg _b aseb acku pスロットを指定する場合を記載しす。
(1) 旧マス(server1)データベースクラスタ削除
PostgreSQL Enterprise Consortium
Page 68 of 285
旧マス(server1)にて実行します
$ rm -rf $PGDATA/*
$PG DATA以外に表領域を作成している場合、そのファルも削除します
$PG DATAディレクトリを除する合はpostgresユーザで$PGDATAィレトリを作成できるよ
親ディレクトのオーナーまたパーミッションを定します
(2) レプリケーシンスロットの作成
新マス(server2)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server2',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server2,0/96000090)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/96000090 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(3) p g _basebacku p マンドにて、新マス(server2)からデータベースクラスタピー
旧マス(server1)にて実行します
$ pg_basebackup -h server2 -U repuser -D $PGDATA -X stream -S slot_server2 -P -v -R
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/99000028 on timeline 32
pg_basebackup: starting background WAL receiver
138336/138336 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/99000130
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed
(4) recovery.con fの修正
旧マス(server1)にて実行します
pg _b aseb acku p-Rオプションを指定した事で、reco very.con fが作成されます。
ロットを指定している事からprimary_slot_n ameの指定があります。以下を追記します
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
recovery_targ et_timelin eパラータ追加
PostgreSQL Enterprise Consortium
Page 69 of 285
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
application_name=server1 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
recovery_target_timeline = 'latest'
起動
$ pg_ctl start
(5) 新マス(server2)postg resql.con fの修正
新マス(server2)にて実行します
syn ch ro n o u s_co mmitパラータの有効化
syn ch ro n o u s_stan d b y_n amesパラータの有効化
同期レプリーションの設定有効化します
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = off
synchronous_standby_names = ''
[編集後]
synchronous_commit = on
synchronous_standby_names = 'server1'
設定を反映
$ pg_ctl reload
(6) レプリケーシンスロットの作成
新スレーブ1(server1)にて実行します
PostgreSQL Enterprise Consortium
Page 70 of 285
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server1',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,0/9A000060)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/9A000060 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(7) スレーブ2(server3)にてrecovery.con f修正
レーブ2(server3)実行します
primary_co n n infoパラメーの「h o st= 」部分を修正
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
recovery_target_timeline = 'latest'
再起動
$ pg_ctl restart
(8) 新マス(server2)のレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 71 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 46558
usesysid | 16384
usename | repuser
application_name | server1
client_addr | <server1IP>
client_hostname |
client_port | 64897
backend_start | 2018-02-09 11:22:23.535181+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/9A000140
write_lsn | 0/9A000140
flush_lsn | 0/9A000140
replay_lsn | 0/9A000140
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync --- 同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
active | t --- ィブ
(9) 新スレーブ(server1)でのレプリケーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 97277
usesysid | 16384
usename | repuser
application_name | server3
client_addr | <server3IP>
client_hostname |
client_port | 52882
backend_start | 2018-02-09 11:55:20.971553+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/9A000140
write_lsn | 0/9A000140
flush_lsn | 0/9A000140
replay_lsn | 0/9A000140
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
れに、以下の構成に復旧しました。
レプーションスロット使
server2(スタ) = => server1(スレーブ1) = 非同期= > server3(レーブ2) のカードレプリーション構成
5.4.4.6.
PostgreSQL Enterprise Consortium
Page 72 of 285
pg _b aseb acku pを使用したフェイルバッいて記載します。 初期構築手順とほぼ同じです。
マスインスタンス障害発生によるイルオーバ後、旧マスを同期モード新スレーブとしたレプリケーション構成図
フェイルバッ手順
(1) スレーブ2(server3)一旦停止
レーブ2(server3)実行します
$ pg_ctl stop
(2) レプリケーシンスロットの作成
新マス(server2)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server2',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server2,0/96000090)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/96000090 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(3) recovery.con fの作成
旧マス(server1)にて実行します
以下を設定します。
$ vi $PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
application_name=server1 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
recovery_target_timeline = 'latest'
(4) 旧マス(server1)postg resql.con fの修正
PostgreSQL Enterprise Consortium
Page 73 of 285
旧マス(server1)にて、パラメタの調整を行います
syn ch ro n o u s_co mmitパラータの無効化
syn ch ro n o u s_stan d b y_n amesパラータの無効化
pg _statsin foの無効化(有効化さてい場合)
同期レプリーションの設定無効化します
新スレーブのsh ared _prelo ad_lib rariesパラータ p g _statsinfoが設定さいる場合は、書き込みができずエラーが発生します
pg _statsin foの指定を削除します。
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = on
synchronous_standby_names = '*'
shared_preload_libraries = 'pg_stat_statements,pg_statsinfo'
[編集後]
synchronous_commit = off
synchronous_standby_names = ''
shared_preload_libraries = ''
(5) 新スレーブ(server1)の起動
新スレーブ(server1)を起動します。
$ pg_ctl start
(6) 新マス(server2)postg resql.con fの修正
新マス(server2)にて実行します
syn ch ro n o u s_co mmitパラータの有効化
syn ch ro n o u s_stan d b y_n amesパラータの有効化
同期レプリーションの設定有効化します
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = off
synchronous_standby_names = ''
[編集後]
synchronous_commit = on
synchronous_standby_names = 'server1'
設定を反映
$ pg_ctl reload
(7) レプリケーシンスロットの作成
新スレーブ1(server1)にて実行します
PostgreSQL Enterprise Consortium
Page 74 of 285
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server1',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,0/9A000060)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/9A000060 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(8) スレーブ2(server3)にてrecovery.con f修正
レーブ2(server3)実行します
primary_co n n infoパラメーの「h o st= 」部分を修正
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
recovery_target_timeline = 'latest'
再起動
$ pg_ctl restart
(9) 新マス(server2)のレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 75 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 12505
usesysid | 16384
usename | repuser
application_name | server1
client_addr | <server1IP>
client_hostname |
client_port | 58195
backend_start | 2018-02-07 21:55:00.722782+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync --- 同期
(10) 新スレーブ(server1)でのレプリション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 86651
usesysid | 16384
usename | repuser
application_name | server3
client_addr | <server3IP>
client_hostname |
client_port | 18206
backend_start | 2018-02-07 22:13:40.199786+09
backend_xmin | 606
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
れに、以下の構成に復旧しました。
レプーションスロット使
server2(スタ) = => server1(スレーブ1) -同期-> server3(スレーブ2) のカードレプリーション構成
5.4.4.7. / 1
pg _b aseb acku pを使用したフェイルバッいて記載します。 初期構築手順とほぼ同じです。
マス(server1)/スレーブ1(server2)サイトに障害が発生し、フイルオーバ後、 マスタ(server1)/スレ1(server2)元の状態に復旧したレプリケーション構成
PostgreSQL Enterprise Consortium
Page 76 of 285
pg _b aseb acku p必要な設定にいて、以下と同様であるめ省略します
「旧マスタを同期モードスレブとしてイルバッ
pg _b aseb acku pでレプリーションスロッが使用できます。 W AL収集方式に stream を指定する事でW ALをほぼ確保できますが、スロットを指定するでより確実に
ります スロットを使用する運用であれ、この段階で作成るのが有力です。
フェイルバッ手順
pg _b aseb acku pスロットを指定する場合を記載しす。
(1) 旧マス(server1)データベースクラスタ削除
旧マス(server1)にて実行します
$ rm -rf $PGDATA/*
$PG DATA以外に表領域を作成している場合、そのファルも削除します
$PG DATAディレクトリを除する合はpostgresユーザで$PGDATAィレトリを作成できるよ
親ディレクトのオーナーまたパーミッションを定します
(2) 旧スレーブ1(server2)のデータベースクラスタ削除
旧スレーブ1(server2)にて実行します
$ rm -rf $PGDATA/*
$PG DATA以外に表領域を作成している場合、そのファルも削除します
$PG DATAディレクトリを除する合はpostgresユーザで$PGDATAィレトリを作成できるよ
親ディレクトのオーナーまたパーミッションを定します
(3) レプリケーシンスロットの作成
新マス(server3)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server3',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server3,0/AD000090)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server3
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/AD000090 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
PostgreSQL Enterprise Consortium
Page 77 of 285
(4) p g _basebacku p マンドにて、新マス(server3)からデータベースクラスタピー
旧マス(server1)にて実行します
$ pg_basebackup -h server3 -U repuser -D $PGDATA -X stream -S slot_server3 -P -v -R
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/3B000028 on timeline 2
pg_basebackup: starting background WAL receiver
203852/203852 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/3B000130
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed
(5) recovery.con fの修正
旧マス(server1)にて実行します
pg _b aseb acku p-Rオプションを指定した事で、reco very.con fが作成されます。
ロットを指定している事からprimary_slot_n ameの指定があります。以下を追記します
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server3 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server3'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server3 port=5432
application_name=server1 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server3'
recovery_target_timeline = 'latest'
(6) 新スレーブ1(server1)の起動
新スレーブ1(server1)起動します
$ pg_ctl start
(7) レプリケーシンスロットの作成
新スレーブ1(server1)にて実行します
PostgreSQL Enterprise Consortium
Page 78 of 285
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server1',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,0/AE000028)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/AE000028 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(8) p g _basebacku p マンドにて、新スレーブ1(server1)からデータベースクラスタをコピー
レーブ2(server2)実行します
$ pg_basebackup -h server1 -U repuser -D $PGDATA -X stream -S slot_server1 -P -v -R
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/3B000028 on timeline 2
pg_basebackup: starting background WAL receiver
203852/203852 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/3B000130
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed
(9) recovery.con fの修正
レーブ2(server2)実行します
pg _b aseb acku p-Rオプションを指定した事で、reco very.con fが作成されます。
ロットを指定している事からprimary_slot_n ameの指定があります。以下を追記します
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
application_name=server2 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
recovery_target_timeline = 'latest'
(10) 新スレーブ2(server2)の起動
PostgreSQL Enterprise Consortium
Page 79 of 285
新スレーブ2(server2)起動します
$ pg_ctl start
(11) スタ(server3)の停止
マス(server3)停止しす。
$ pg_ctl stop
(12) レーブ1(server1)を新マスへ昇
レーブ1(server1)実行します。
$ pg_ctl promote
※サーバログに下記内容が記載さ
"d a tab ase system is ready to accept co n n ection s"
(13) プリーションスロットの作成
新スレーブ1(server2)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server2',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server2,0/AE000028)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/AE000028 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(14) 新スレーブ2(server3)にてreco very.co n f作成
新スレーブ2(server3)にてreco very.co n f作成しす。
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータの追
recovery_targ et_timelin eパラータの追加
PostgreSQL Enterprise Consortium
Page 80 of 285
$ mv $PGDATA/recovery.done $PGDATA/recovery.conf
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
recovery_target_timeline = 'latest'
起動
$ pg_ctl start
(15) 新マス(server1)postg resql.con fの修正
新マス(server1)にて実行します
syn ch ro n o u s_co mmitパラータの有効化
syn ch ro n o u s_stan d b y_n amesパラータの有効化
同期レプリーションの設定有効化します
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = off
synchronous_standby_names = ''
[編集後]
synchronous_commit = on
synchronous_standby_names = 'server2'
設定を反映
$ pg_ctl reload
(16) 新マス(server1)でのレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 81 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 12505
usesysid | 16384
usename | repuser
application_name | server2
client_addr | <server2IP>
client_hostname |
client_port | 58195
backend_start | 2018-02-07 21:55:00.722782+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync --- 同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
active | t --- ィブ
(17) 新スレーブ1(server2)でのレプリケーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 86651
usesysid | 16384
usename | repuser
application_name | server3
client_addr | <server3IP>
client_hostname |
client_port | 18206
backend_start | 2018-02-07 22:13:40.199786+09
backend_xmin | 606
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
=# SELECT slot_name,active FROM pg_replication_slots;
slot_name | active
--------------+--------
slot_server2 | t
(1 row)
(18) プリーションスロットの削除(レーブ)
PostgreSQL Enterprise Consortium
Page 82 of 285
新スレーブに旧スタ時代のスロットが残る事があります
restart_lsn列に値が残って状態では、マスタVACUU M 処理を阻害するなど
悪影響の可能性があるため、削除しす。
ロットの削除は関数で行うめ、スレーブでも実行可能です。
レーブ2(server3)実行します
$ psql
=# SELECT slot_name,active FROM pg_replication_slots;
slot_name | active
--------------+--------
slot_server3 | f
(1 row)
=# SELECT pg_drop_replication_slot('slot_server3');
pg_create_physical_replication_slot
-------------------------------------
(1 row)
=# SELECT slot_name FROM pg_replication_slots;
(0 rows)
れに、以下の構成に復旧しました。
レプーションスロット使
server1(スタ) = => server2(スレーブ1) = 非同期= > server3(レーブ2) のカードレプリーション構成
5.4.4.8.
イッチーバについて記載します
5.4.4.9.
スイッーバ手順
計画停止におけるマス/スレーブの切り替え手順です。 p g _baseb acku p pg_rew ind が不要であるためシンプルな手順です。
計画停止にてマスとスレーブ1の役割を切り替えプリーション構成図
(1) マス(server1)の正常停止
マス(server1)にて実行します
$ pg_ctl stop -m fast
(2) スレーブ(server2)昇格
レーブ(server2)実行します。
以下の場合にpg _rew in d 不要で
計画停止
同期レプリーションのインスンス障害(物理障害なし)
PostgreSQL Enterprise Consortium
Page 83 of 285
$ pg_ctl promote
(3) レプリケーシンスロットの作成
新マス(server2)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server2',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server2,0/B40000C8)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/B40000C8 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(4) 旧マス(server1)reco very.con fの作成
以下を記載します。
$ vi $PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
application_name=server1 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
recovery_target_timeline = 'latest'
(5) 旧マス(server1)postg resql.con fの修正
旧マス(server1)にて、パラメタの調整を行います
syn ch ro n o u s_co mmitパラータの無効化
syn ch ro n o u s_stan d b y_n amesパラータの無効化
pg _statsin foの無効化(有効化さてい場合)
同期レプリーションの設定無効化します
新スレーブのsh ared _prelo ad_lib rariesパラータ p g _statsinfoが設定さいる場合は、書き込みができずエラーが発生します
pg _statsin foの指定を削除します。
PostgreSQL Enterprise Consortium
Page 84 of 285
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = on
synchronous_standby_names = '*'
shared_preload_libraries = 'pg_stat_statements,pg_statsinfo'
[編集後]
synchronous_commit = off
synchronous_standby_names = ''
shared_preload_libraries = ''
再起動
$ pg_ctl restart
(6) レプリケーシンスロットの作成
新スレーブ(server1)実行しす。
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server1',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,0/B4000028)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/B4000028 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(7) 新マス(server2)postg resql.con fの修正
新マス(server2)にて実行します
syn ch ro n o u s_co mmitパラータの有効化
syn ch ro n o u s_stan d b y_n amesパラータの有効化
同期レプリーションの設定有効化します
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = off
synchronous_standby_names = ''
[編集後]
synchronous_commit = on
synchronous_standby_names = 'server1'
設定を反映
$ pg_ctl reload
PostgreSQL Enterprise Consortium
Page 85 of 285
(8) スレーブ2(server3)にてrecovery.con f修正
レーブ2(server3)実行します
primary_co n n infoパラメーの「h o st= 」部分を修正
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ vi $PGDATA/recovery.conf
[編集前]
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=12079
sslmode=disable sslcompression=1 target_session_attrs=any'
[編集後]
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=12079
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
recovery_target_timeline = 'latest'
再起動
$ pg_ctl restart
(9) 新マス(server2)のレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 12505
usesysid | 16384
usename | repuser
application_name | server1
client_addr | <server1IP>
client_hostname |
client_port | 58195
backend_start | 2018-02-07 21:55:00.722782+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync --- 同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
active | t --- ィブ
(10) 新スレーブ(server1)でのレプリション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 86 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 86651
usesysid | 16384
usename | repuser
application_name | server3
client_addr | <server3IP>
client_hostname |
client_port | 18206
backend_start | 2018-02-07 22:13:40.199786+09
backend_xmin | 606
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-----------
slot_name | slot_server1
active | f
以上でスイッチオーバが完了しました
5.4.4.10.
スイッーバ手順
計画停止におけるマス/スレーブの切り替え手順です。 p g _baseb acku p pg_rew ind が不要であるためシンプルな手順です。
計画停止にてマスとスレーブ2の役割を切り替えプリーション構成図
(1) マス(server1)の正常停止
マス(server1)にて実行します
$ pg_ctl stop -m fast
(2) スレーブ(server3)昇格
レーブ(server3)実行します。
以下の場合にpg _rew in d 不要で
計画停止
レプーションのインスタンス障害(物理障害なし)
PostgreSQL Enterprise Consortium
Page 87 of 285
$ pg_ctl promote
(3) レプリケーシンスロットの作成
新マス(server3)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server3',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server3,0/BA0000C8)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server3
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/BA0000C8 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(4) 旧マス(server1)reco very.con fの作成
以下を記載します。
$ vi $PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server3 port=5432
application_name=server1 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server3'
recovery_target_timeline = 'latest'
(5) 旧マス(server1)postg resql.con fの修正
旧マス(server1)にて、パラメタの調整を行います
syn ch ro n o u s_co mmitパラータの無効化
syn ch ro n o u s_stan d b y_n amesパラータの無効化
pg _statsin foの無効化(有効化さてい場合)
同期レプリーションの設定無効化します
新スレーブのsh ared _prelo ad_lib rariesパラータ p g _statsinfoが設定さいる場合は、書き込みができずエラーが発生します
pg _statsin foの指定を削除します。
PostgreSQL Enterprise Consortium
Page 88 of 285
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = on
synchronous_standby_names = '*'
shared_preload_libraries = 'pg_stat_statements,pg_statsinfo'
[編集後]
synchronous_commit = off
synchronous_standby_names = ''
shared_preload_libraries = ''
(6) 新スレーブ1(server1)の起動
新スレーブ1(server1)起動します
$ pg_ctl start
(7) レプリケーシンスロットの作成
新スレーブ1(server1)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server1',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,0/BA000028)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/BA000028 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(8) スレーブ2(server2)にてrecovery.con f修正
レーブ2(server2)実行します
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ
PostgreSQL Enterprise Consortium
Page 89 of 285
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
application_name=server1 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
recovery_target_timeline = 'latest'
再起動
$ pg_ctl restart
(9) 新マス(server3)のレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 12505
usesysid | 16384
usename | repuser
application_name | server1
client_addr | <server1IP>
client_hostname |
client_port | 58195
backend_start | 2018-02-07 21:55:00.722782+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | async --- 非同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server3
active | t --- ィブ
(10) 新スレーブ1(server1)でのレプリケーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 90 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 86651
usesysid | 16384
usename | repuser
application_name | server2
client_addr | <server2IP>
client_hostname |
client_port | 18206
backend_start | 2018-02-07 22:13:40.199786+09
backend_xmin | 606
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
active | t --- ィブ
以上でスイッチオーバが完了しました
5.4.4.11.
イッチックにいて記載しす。
5.4.4.12.
同期モードスレーブにっていた旧マスをマ復帰させるイッチックついて記載します
同期モードスレーブにっていた旧マスをマとして復帰させたレプーション構成図
スイッバッ手順
(1) マス(server2)の停止
$ pg_ctl stop
(2) スレーブ1(server1)の昇格
レーブ1(server1)実行します
PostgreSQL Enterprise Consortium
Page 91 of 285
$ pg_ctl promote
(3) 旧マス(server2)reco very.con fの作成
以下を記載します。
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ cp $PGDATA/recovery.done $PGDATA/recovery.conf
$ vi $PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
application_name=server2 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
recovery_target_timeline = 'latest'
(4) 新マス(server1)postg resql.con fの修正
新マス(server1)にて実行します
syn ch ro n o u s_co mmitパラータの有効化
syn ch ro n o u s_stan d b y_n amesパラータの有効化
同期レプリーションの設定有効化します
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = off
synchronous_standby_names = ''
[編集後]
synchronous_commit = on
synchronous_standby_names = 'server2'
設定を反映
$ pg_ctl reload
(5) 新スレーブ1(server2)の起動
$ pg_ctl start
(6) スレーブ2(server3)reco very.con fの作成
以下を記載します。
primary_co n n infoパラメーの「h o st= 」部分を修正
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ修正
recovery_targ et_timelin eパラータ追加
PostgreSQL Enterprise Consortium
Page 92 of 285
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
recovery_target_timeline = 'latest'
(7) スレーブ2(server3)の再起動
$ pg_ctl restart
(8) 新マス(server1)のレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 12505
usesysid | 16384
usename | repuser
application_name | server2
client_addr | <server2IP>
client_hostname |
client_port | 58195
backend_start | 2018-02-07 21:55:00.722782+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync --- 同期
(9) スレーブ1(server2)でのレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 93 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 86651
usesysid | 16384
usename | repuser
application_name | server3
client_addr | <serrver3IP>
client_hostname |
client_port | 18206
backend_start | 2018-02-07 22:13:40.199786+09
backend_xmin | 606
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
以上でスイッチバッが完了しました
5.4.4.13.
非同期モードスレーブからマスへスイッチバッいて記載します。
非同期モードスレーブにっていた旧マスをマスタとして復帰させたレプリケーシン構成図
スイッバッ手順
(1) マス(server3)の停止
$ pg_ctl stop
(2) スレーブ1(server1)の昇格
レーブ1(server1)実行します
$ pg_ctl promote
(3) レプリケーシンスロットの作成
新スレーブ1(server2)にて実行します
PostgreSQL Enterprise Consortium
Page 94 of 285
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server2',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server2,0/BB0000C8)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/BB0000C8 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(4) 旧マス(server3)reco very.con fの作成
以下を記載します。
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ cp $PGDATA/recovery.done $PGDATA/recovery.conf
$ vi $PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
recovery_target_timeline = 'latest'
再起動
$ pg_ctl restart
(5) 新マス(server1)postg resql.con fの修正
新マス(server1)にて実行します
syn ch ro n o u s_co mmitパラータの有効化
syn ch ro n o u s_stan d b y_n amesパラータの有効化
同期レプリーションの設定有効化します
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = off
synchronous_standby_names = ''
[編集後]
synchronous_commit = on
synchronous_standby_names = 'server2'
$ pg_ctl reload
PostgreSQL Enterprise Consortium
Page 95 of 285
(6) 新マス(server1)のレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 12505
usesysid | 16384
usename | repuser
application_name | server2
client_addr | <server2IP>
client_hostname |
client_port | 58195
backend_start | 2018-02-07 21:55:00.722782+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync --- 同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
active | t --- アクティブ
(7) スレーブ1(server2)でのレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 96 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 86651
usesysid | 16384
usename | repuser
application_name | server3
client_addr | <server3IP>
client_hostname |
client_port | 18206
backend_start | 2018-02-07 22:13:40.199786+09
backend_xmin | 606
state | streaming --- ストリーミング
sent_lsn | 0/6A000818
write_lsn | 0/6A000818
flush_lsn | 0/6A000818
replay_lsn | 0/6A000818
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
=# SELECT slot_name,active FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
active | t --- アクティブ
(8) レプリケーシンスロットの削除(スレーブ)
イルオーバとの違いとしては、新スレーブに旧マス時代のスロットが残る事があります
restart_lsn列に値が残って状態では、マスタVACUU M 処理を阻害するなど
悪影響の可能性があるため、削除しす。
ロットの削除は関数で行うめ、スレーブでも実行可能です。
レーブ2(server3)実施します
$ psql
=# SELECT slot_name FROM pg_replication_slots;
slot_name
--------------
slot_server3
(1 row)
=# SELECT pg_drop_replication_slot('slot_server3');
pg_create_physical_replication_slot
-------------------------------------
(1 row)
=# SELECT slot_name FROM pg_replication_slots;
(0 rows)
以上でスイッチバッが完了しました
5.4.4.14. pg_rewind使 使
pg _rew in dを使用したスイッバッいて記載します。
pg _rew in dはタイムラインのずれたレプリケーションを再同期させる機能です。 実行後、ターゲットクソースと置き換えれた状態になります そのた
pg _rew in d後の操作は、通常のスイッーバ時と同じで イムラインの分岐点からソースクラスタのW ALを適用するめ、更新量が少なければpg_baseb ack よる
複製より高速で りスイッオーバ時、旧マスを容易に新スレーブとして起動させるとができます
イッチーバー後、pg_rew in d で旧マスを新スレーブとして戻したレプーション構成図
PostgreSQL Enterprise Consortium
Page 97 of 285
関連パラータ
pg _rew in d必要な設定を記載します
5.30 p g _rew ind 必要な設定
pg _rew in d
実行サー
po stg resq l.con f fu ll_p age_w rites on ポイント後の更新時、ディスページの全内容をW AL書き込
む。
pg _rew in d
実行サー
po stg resq l.con f w al_lo g _h ints on ヒントビト更新時もfu ll_p age_w ritesを実行する
p g _rew indマンド
pg _rew in dマンドの主なオプションは次の通りです。
5.31 p g _rew ind のオプション
D <ーゲットクスタ> pg _rew in dを実行し、ソーススタの内容に置き換えるクを指定する。
sou rce-server= "<ソース> "
同期対象であるソースクラスタを指定します。主に次の接続文字列を使用します。
h ostソースのホスト名またIPアドレス
po rtソースのポート番号
db n ameソースの接続先データベース名
u serソースクラスタの接続先ユーザ
P 進行状況レポートとして表示する
フェイルバッ手順
※事前にマスで関連パラータの設定がされいること前提とします
PostgreSQL Enterprise Consortium
Page 98 of 285
(1) マスの正常停止
pg _rew in dを使用する正常停止る必要があります
停止した旧マスタを一旦起動した後正常停止さます
障害により正常に起動や停止ができない状態ではp g _rew indは使用できません。
その場合は、pg _b aseb acku pを使用します。
$ pg_ctl stop -m fast
(2) スレーブ(server2)昇格
レーブ(server2)実行します。
計画停止
同期レプリーションのインスンス障害(物理障害なし)
$ pg_ctl promote
(3) 旧マス(server1)postg resql.con fの修正
旧マス(server1)にて、パラメタの調整を行います
syn ch ro n o u s_co mmitパラータの無効化
syn ch ro n o u s_stan d b y_n amesパラータの無効化
pg _statsin foの無効化(有効化さてい場合)
同期レプリーションの設定無効化します
新スレーブのsh ared _prelo ad_lib rariesパラータ p g _statsinfoが設定さいる場合は、書き込みができずエラーが発生します
pg _statsin foの指定を削除します。
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = on
synchronous_standby_names = '*'
shared_preload_libraries = 'pg_stat_statements,pg_statsinfo'
[編集後]
synchronous_commit = off
synchronous_standby_names = ''
shared_preload_libraries = ''
(4) スプットブレイン状態状態を作るめ、旧マス(server1)を再度起動し、
データを更新する
$ pg_ctl start
$ psql
=# select * from test;
col1
------
1
3
2
(3 rows)
=# insert into test values(4);
INSERT 0 1
=# select * from test;
col1
------
1
3
2
4
(4 rows)
(5) p g _rew indの実行のため、旧マスタ(server1)正常停止する
PostgreSQL Enterprise Consortium
Page 99 of 285
$ pg_ctl stop -m fast
(6) 旧マス(server1)p g _rew ind の実
$ pg_rewind -D $PGDATA --source-server="host=server2 port=5432"
servers diverged at WAL location 0/D0000098 on timeline 45
rewinding from last common checkpoint at 0/D0000028 on timeline 45
Done!
(7) レプリケーシンスロットの作成
新マス(server2)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server2',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server2,0/D00000C8)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server2
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/D00000C8 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(8) recovery.con fの作成
旧マス(server1)にて実行します
以下を設定します。
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ cp $PGDATA/recovery.done $PGDATA/recovery.conf
$ vi $PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
application_name=server1 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
recovery_target_timeline = 'latest'
(9) 新スレーブ(server1)の起動
新スレーブ(server1)を起動します。
$ pg_ctl start
(10) 新スレーブ(server1)データ確認
pg _rew in dより、データが正常に巻き戻されいることを確認しす。
PostgreSQL Enterprise Consortium
Page 100 of 285
$ psql
=# select * from test;
col1
------
1
3
2
(3 rows)
(11) 新マス(server2)postg resql.con fの修正
新マス(server2)にて実行します
syn ch ro n o u s_co mmitパラータの有効化
syn ch ro n o u s_stan d b y_n amesパラータの有効化
同期レプリーションの設定有効化します
$ vi $PGDATA/postgresql.conf
[編集前]
synchronous_commit = off
synchronous_standby_names = ''
[編集後]
synchronous_commit = on
synchronous_standby_names = 'server1'
設定を反映
$ pg_ctl reload
(12) プリーションスロットの作成
新スレーブ1(server1)にて実行します
$ psql
=# SELECT pg_create_physical_replication_slot('slot_server1',true); -- 2パラータtrueを指定
pg_create_physical_replication_slot
-------------------------------------
(slot_server1,0/D0000028)
(1 )
=# \x on
拡張表示 on です。
=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name | slot_server1
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f -- ロットは使用されてないた false
active_pid |
xmin |
catalog_xmin |
restart_lsn | 0/D0000028 -- trueの指定により、作成直後からrestat_lsnを認識
confirmed_flush_lsn |
(13) レーブ2(server3)recovery.con f修正
レーブ2(server3)実行します
primary_co n n infoパラメーの「h o st= 」部分を修正
primary_co n n infoパラメーap p lication _nameを追加(任意/デフォルトはw alreceiver
PostgreSQL Enterprise Consortium
Page 101 of 285
primary_slot_n ameパラメータ追加
recovery_targ et_timelin eパラータ追加
$ vi $PGDATA/recovery.conf
[編集前]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=5432
sslmode=disable sslcompression=1 target_session_attrs=any'
[編集後]
standby_mode = 'on'
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=5432
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
recovery_target_timeline = 'latest'
再起動
$ pg_ctl restart
(14) 新マス(server2)でのレプーション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 82328
usesysid | 16384
usename | repuser
application_name | server1
client_addr | 172.16.25.111
client_hostname |
client_port | 63206
backend_start | 2018-02-28 22:40:16.337761+09
backend_xmin |
state | streaming --- ストリーミング
sent_lsn | 0/D0019538
write_lsn | 0/D0019538
flush_lsn | 0/D0019538
replay_lsn | 0/D0019538
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync --- 同期
(15) 新スレーブ(server1)でのレプリション確認
pg _stat_replication sビューを参照してレプリケーシン構成である事を確認しす。
pg _replication _slotsビューを参照して、スロットがアクィブである事を確認します
PostgreSQL Enterprise Consortium
Page 102 of 285
$ psql
=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 51369
usesysid | 16384
usename | repuser
application_name | server3
client_addr | 172.16.25.143
client_hostname |
client_port | 47281
backend_start | 2018-02-28 23:02:39.56715+09
backend_xmin |
sent_lsn | 0/D0019538
write_lsn | 0/D0019538
flush_lsn | 0/D0019538
replay_lsn | 0/D0019538
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --- 非同期
(16) スタ、スレーブとタイムラインID が揃っていることを確認する。
イムラインIDの取得には、p g _con tro ld ataマンドを使用する
厳密には最新チェックポイント実行時のタイムラIDであめ、
イムラインIDが揃っていないときは、マチェックポイント実行後、再確認します
[マス(server2)]
$ export LANG=C
$ pg_controldata | grep " TimeLineID"
Latest checkpoint's TimeLineID: 46
[スレーブ1(server1)]
$ export LANG=C
$ pg_controldata | grep " TimeLineID"
Latest checkpoint's TimeLineID: 46
[スレーブ2(server3)]
$ export LANG=C
$ pg_controldata | grep " TimeLineID"
Latest checkpoint's TimeLineID: 46
p g _rew ind使用時の注意点
正常停止が必要
pg _rew in dを実行するデータベースクラスタ正常終了しなければいけません。
物理障害等にり正常停止できない場合p g _rew in d は使用できません。p g _basebacku p を使用します。
同一タイムランの場合は実施不
pg _p romoteを実行せず旧スレーブを新マスした場合、新マスのタイムインID は変わらないため、
新マスと旧マスのタイムラインIDは同じ状態です。
の場合は、p g _rew in d は実行できません。
実行時期と所要時間の関係
pg _rew in dよるイルバックの所要時間は2つの要素から構成さます
Step 1. pg_rew ind よる巻き戻し 旧マスW ALを使用)
Step 2. W AL用にる追い付き 新マスタのW ALを使用)
新マスで大量更新がある場合は、Step1は短時間で終了してStep2で時間がかかります
結果としp g _basebacku pの方が効率が良い場合もあり得ます。
PostgreSQL Enterprise Consortium
Page 103 of 285
また新マスタ昇格時W ALが削除さてい場合は、後述するよStep2ーとなる可能性あります。その場合はpg_basebacku p
が必要となります
pg _rew in dはフルオーバー後、あまり時間を置かず実行する事がポイントです。
旧マスW AL保管
旧マスの巻き戻しに必要な旧マスW ALが削除さいる場合、pg_rew in d は失敗します
例えば旧マが障害により大量更新の途中で異常終了した場合などに発生します
pg _rew in d実行時に次のようなエーが発生しす。
could not open file "/home/pg96/pg96_data/pg_xlog/0000000D00000002000000CF": No
such file or directory
could not find previous WAL record at 2/CF000140
Failure, exiting
pg _rew in dが成功するかどうかは検証(d ry-ru n オプション)事前に確認する事ができます
$ pg_rewind -D $PGDATA --source-server="host=server2 port=5432" --dry-run
servers diverged at WAL position 0/5015B70 on timeline 1
rewinding from last common checkpoint at 0/5015B00 on timeline 1
Done!
| メッセージはdry-runオプションが無い場合と同じです。
| pg_rewindでエラーが発生する場合(レーブのWAL削除)は、の検証にて確認できますが、
| pg_rewindでエラーが発生しないで、後から発生する場合(マスWAL削除)は検知できません。
| 検証の仕様にいて認識下さ
新マスW AL保管
pg _rew in d後、新スレは新マスタのW ALを適用するとで、新マス同期します。
新マス昇格時のW ALファルが残っていない場合、新スレーブは追い付きができず、次のエラーがサーバログ出力さ続けます
対策としプリションストの有効化が有力でが、新マスタのW AL領域の枯渇にご注意下さい。
ERROR: requested WAL segment 0000000D00000000000000F3 has already been removed
イムラインの巻き戻し
pg _rew in dPostgreSQ L9.6からイムラインの巻き戻しができるよになっています
れによりスプットブレインが発生しても、新マスをスレーブに戻すことが可能です。
pg _rew in dが不要な場合
pg _rew in dはターゲとソーススタのイムラインIDが分岐した場合に実行が必要です。
そのためタイムラインが枝分かれしなかった場合、pg_rew ind を実行する必要はありません。
例えpg_rew in d 実行時にのようなメッセージが出た場合、pg _rew in d は実行せずに、以降の操作を継続します
servers diverged at WAL position 0/503A428 on timeline 2
no rewind required
5.4.4.15.
レーブ障害時の緊急対応の必要性は、非同期モードが同期モードかによって異なります。
非同期モードの場合は、スレーブ障害がマスの更新処理を阻害しないため、緊急対応必要ありませ
とはいえ、シングル状態であるため早期プリーシン構成に復旧します。
同期モードの場合、ス
PostgreSQL Enterprise Consortium
Page 104 of 285
$ psql -h server1 -U postgres postgres -c "INSERT INTO test1_t VALUES ( 1 )"
Cancel request sent
WARNING: canceling wait for synchronous replication due to user request
DETAIL: ** The transaction has already committed locally, but might not have been replicated to
the standby. **
INSERT 0 1
Ctrl+Cキーインする等、意図的にキャンセルしない限り、応答が返ってきません。
そのため、直ち非同期に設定する必要があります
非同期への切り替え処理以降に示す様に再起動不要であるため、即時対応が可能です。
非同期への切り替えではな、スレーブの再起動を試み方法も考えれます。その方が効率的のよう考えます
即座に起動でその通りですが、起動に時間がかかる、あるいは物理的な障害で起動できな状態である事も考えます
そのような試行錯誤より、まずは確実にマスのハング状態解消を優先します
マスの復旧後は、スレーブの復旧試みます
物理障害により起動できない場合は、フイルバッ処理と同様の作業を行います。
(1) スレーブの疑似障害発
immed iateプションにて止、またpo stg resプロセスのkill事で擬似障害を発生させます。
レーブ1(server2)実行します
$ pg_ctl -w -m immediate stop
(2) スレーブ1(server2)の死活監視に異常を検知
死活監視の方法には多数ありますが、ここではpg_isread yンドを使用します
pg _isreadyマンドはイアンツールですので、任意のノードから実行でます
$ pg_isready -h server2 -U postgres -d postgres
server2:5432 - no response
(3) 非同期ードに切り替え
syn ch ro n o u s_stan d b y_n amesパラータ''に設定する事で非同期の設定となります
マス(server1)にて実行します
PostgreSQL Enterprise Consortium
Page 105 of 285
$ vi $PGDATA/postgresql.conf
[変更前]
synchronous_standby_names = '*'
[変更後]
synchronous_standby_names = ''
$ pg_ctl reload
れでスタが更新処理が可能な状態に復旧しました
(4) スレーブ2(server3)非同期モードで復活
recovery.con fァイルを修正します。
primary_co n n infoパラメーの「h o st= 」部分を修正
primary_slot_n ameパラメータが設定されいる場合は、修正
$ vi $PGDATA/recovery.conf
[変更前]
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server2 port=12079
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server2'
[変更後]
primary_conninfo = 'user=repuser passfile=''/home/p101/.pgpass'' host=server1 port=12079
application_name=server3 sslmode=disable sslcompression=1 target_session_attrs=any'
primary_slot_name = 'slot_server1'
$ pg_ctl restart
(5) スレーブ2(server3)にてデータが伝播されること確認
同期モードのスレーブも復活させたい場合は、フェイルバッと同様の作業を行います。
5.5. まと
5.5.1. SR
Po stg reSQ L 9.0SR機能が実装されて以降ジャーバージョン毎にSR 関連の新機能を実装しています
"スオーショ""スオ"略記する場合があります。
"レプリーションスロッ"と表記した場合は物理型を指します。論理型の場合は明記します
"レプリーションスロッ""ロット"と略記する場合があります
5.32 SR機能拡張の歴
9.1 管理性の向上
データ保護
CO MM IT時にW ALの転送完了までを保証する。
データ保護とパフォーマンスとのトレードオフ
[マスpo stg resq l.con f]
syn ch ro n o u s_stan d b y_n ames
9.1 管理性向
昇格処理の明瞭化
pg_ctl promote
明確なコマンドとなり分かり易った
従来はtrig ger_fileで設定したパスto u ch マンド等でイルを作成する
式であった。
9.1 管理性向
SR状況把握の簡易
pg_stat_replication
マスでのスレーブへのW AL転送および適用の状況把握方法が簡易になっ
w al_receiver_statu s_in terval間隔で反映。
[スレーブのpo stg resql.con f]
w al_receiver_sta tus_interval
PostgreSQL Enterprise Consortium
Page 106 of 285
9.1 管理性向
SR状況把握の簡易
pg_last_xact_replay_tim estamp
レーブにて最終適用された時間を取得する
9.2 データ保護とパフォーマンス
の調整
remote_write
syn ch ro n o u s_co mmitの選択肢としてon /o ff/lo calえ、
remote_w riteが追加さ
レーブのメモリに書き込むまでを保証する。その時点でO Sがハングした場合、
W AL損失する。
[マスpo stg resq l.con f]
 syn ch ron o u s_co mmit
9.2 高可用性の向上
レーブにぶら下がる2段目SR 成が可能となった
マスの負荷を限定。
9.2 管理性の向上
SR状況把握の簡易
pg_xlog_location_diff
レーブの転送や適用がどの程度遅れいるかを取得するのが容易になった
従来は p g _stat_rep lication ューを参照していたが、ログの位置をバイト
換算する計算が必要だた。
本関数により16進の差分をバイト数として取得できる。
9.3 管理性の向上
役割交換の効率化
h isto ryァイルの転送により実装
9.3 管理性の向上
カスケードのSR構成において、スレーブの新マス格後に、スレーブとSR の継
続が可能に
9.3 障害時間の短縮
昇格処理にて、リカバリのみ実行し、チポイント省略する事で時間短縮
を実現。
従来はチェックポイントも昇格処理に実行していた。
9.4 管理性の向上
オペ対策
レーブでの適用を一定時間(reco very_min _apply_delay)遅らせる事で、
マスで発生したオペの伝搬を防ぐ。以下の事項に注意
一定時間内にスタでのオペを検知して対応が必要
昇格時には遅延分の適用が必要であるため時間を要す
[スレーブのrecovery.co n f]
 reco very_min _app ly_delay
9.4 管理性の向上
W AL保持の保証
レーブに必要W ALをマで保持し続ける事を保証。
特に複数スレーブ構成に効果的。以下の事項に注意。
マスW AL領域が溢れないよ監視を検討
不要スロッ削除(残存しているとW ALを保持)
[マスpo stg resq l.con f]
 max_rep lication _slo ts
[スレーブのpo stg resql.con f]
 ho t_stan d b y_feed b ack
9.4 論理レプリーショ
行レベルの変更内容を出力する関数が実装された
pg _lo gical_slot_g et_ch an ges
pg _lo gical_slot_p eek_ch an g es関数
必要な設定
w al_levellog ical設定
論理レプリーションスロッ作成
[マスpo stg resq l.con f]
w al_level
 max_rep lication _slo t
9.5 W AL転送効率の向上 WAL
W ALを圧縮する事で転送効率の向上する
圧縮/解凍にるオーヘッドとのトレードオフが、通常はットの方が大
きい。
SRに特化した機能では無いが、特に次のSR構成での適用が効果的と考え
れる。
同期モードまた完全同期ード
レーブを遠隔地に配置ディザスリカバリ
[マスpo stg resq l.con f]
 w al_co mpression
9.5 管理性の向上
SR構築の効率化
pg_rewind
昇格した新マスタと旧スタを再同期する事で、SR構成を実装。物理的な
害でない場合は、pg _rew in d対応可能な可能性がある。
新マスから旧マス差分バッアップを転送おび旧マスW ALを適用。
差分バッアップの転送はpg_basebacku pと同様であるため同様の設定が
必要。
[マスpo stg resq l.con f]
 w al_lo g_h ints
 fu ll_p age_w rites
 max_w al_sen d ers
[マスpg _h b a.con f]
 rep lication 似データベースと
の認証設
9.5 管理性の向上
ログ監視の利便性が向上しあまり多くは出力されない。
[マスpo stg resq l.con f]
 log_replica tion _comma n d s
PostgreSQL Enterprise Consortium
Page 107 of 285
9.5 管理性の向上
継続的アーカイ
レーブにおいて自分のW ALを出力するで、昇格時に途切れと無く
続的なアーカイブが可能。
[スレーブのpo stg resql.con f]
 arch ive_mode
9.6 ールアウト
参照負荷分散
レーブへの適用完了までを保証。
レーブ参照時にマスと同一データが保証さ事で、参照負荷分散による
ールアウトが期待さる。
[マスpo stg resq l.con f]
 syn ch ron o u s_co mmit
9.6 データ保護の多重化 スレ
従来は複数スレーブの内、同期モードが設定できる台のみであったが、そ
の制限が無くなった
同時に複数スレーブ対して同期モードが設定できる
[マスpo stg resq l.con f]
syn ch ro n o u s_stan d b y_n ames
9.6 管理性の向上
SR状況把握の簡易
pg_stat_wal_receiver
従来はマスタにpg _stat_replication ビューが参照でが、スレーブにて
pg _stat_w al_receiverビューが参照できる。
レーブからレプリーシンの状況が把握が容易に
9.6 管理性の向上
監視手法の多様化
pg_control_recovery
制御ファル情報の内、リカバリに関する情報を取得。
従来はpg_con troldataマンドで制御ファルの情報を取得したが、
SELECT文で取得でる事で管理手法の選択肢が増え
9.6 管理性の向上
役割交換の簡易化
pg_rewind
イムラインIDの変更後にも対応できるよなった
マス適用する事でスレーブに戻す事が可能。
10.0 管理性の向
レプーションスロットを一時的に作成できるようった
pg _b aseb acku pマンド実行時のみ使用する場合に有効
一時的なスロットかどうかはpg_replication _slotsカタログのtempora ry列で
判断する
10.0 管理性の向 Quorum-based
syn ch ro n o u s_stan d b y_n amesスレーブのリストに対してANYを指定す
る事で、同期レプリーシンとなるスレーブが定足数に応じて任意に選択さ
る。
[マスpo stg resq l.con f]
syn ch ro n o u s_stan d b y_n ames
10.0 W AL対象の拡充 W A L
従来は非推奨だったハッシュインデッスの活用が増え可能性あり。
SRの機能ではなが、関連事項として掲載。
[マスpo stg resq l.con f]
syn ch ro n o u s_stan d b y_n ames
PostgreSQL Enterprise Consortium
Page 108 of 285
6.
6.1. ジカルレリケーショの概
6.1.1.
Po stg reSQ L 10.0よりロジカルレプリケーション機能がサポートれました ロジカルレプーションでは、テーブルデータ対する論理的な変更内容を用いて、サーバ間の
データレプリーションを実現します Po stgreSQ L 9.0よりサポートさいるスーミングレプリケーションでは、データベースを構成するファイルの変更内容を物理的に
製するとで、 ーバ間のデータレプーションを実現します 従来のスングレプリーションの物理的なレプリーションと対比る形で、ロジカルレプリケーションと呼
称さていす。
6.1.2.
ロジカルレプリーションはPostgreSQ L 9.0りサポートさいるストリーミングレプリーションと比較する以下の特徴を持ちます。
任意のテーブルのみをレプリケーション可能
特定の処(例えINSERTのみ)のみをレプリケーション可能
異なるPostgreSQ Lバージョン間でのレプリーション可能
レプーション先でテーブルデータの更新やインデックス定義が可能
し、レプリーション先のテーブルデータを更新した場合や、特定の処理のみをレプリーシンす場合は、 レプリケーション元とプリーション先でデータが異なる状態
ります。 上記のような場合にデータの整合性ユーザが保証する必要があります
6.1.3.
ロジカルレプリーションではPu b lish er(パブリッシャ)/Sub scrib er(サブスイバ)デルを採用しており レプリケーション元のサーバはPu b lish er、レプリーション先のサー
バはSu b scrib erと呼称されます。 Pub lish er上には、レプーション対象とるテルの論理集合であるPu blica tion (パブリーシ)定義し Su b scriber上に
、レプリーション対象するパブリーションとその接続情報であるSu b scription (サブスリプショ)を定義します ロジカルレプーションにおける各用語の説明下表に
記載します。
6.1 用語説明
No.
1 Pub lish er(パブリッ) レプリーション元とサーバ
2 Su b scrib er(サブスイバ) レプリーション先とるサーバ
3 Pub lication (パブリーション) レプーション対象とるテルの定義。CR EATE PU B LICATIO Nコマンドで作成。
4 Su b scrip tion (ブスリプショ) レプリケーション対象するパブリーションとその接続定義。CR E ATE SUB SCRIPTIO Nンドで作成
5 Rep lica tion Slot(レプリーションス
ロット)
レプーションの状態を保持するオブジェクトSu b scriptio n 成時にPu b lish er上に作成さ
デフォルトでは作成さRep licatio n Slo tの名前は、Sub scrip tionの名前と同じに設定れる。
ロジカルレプリーションは、下記の2階でレプリケーションが実施さます
1. 初期データのナップショット取
2. データ変更内容の送受信によるデータ同
動作は下図のイメージとなります
PostgreSQL Enterprise Consortium
Page 109 of 285
Pu blish erからSub scrib erへの「2. データ変更内容の送受信によるデータ同期」は下図の処理で実施されます。
. Pu b lish erのディスW ALが書き込まれる
. Pu b lish erw alsen derプロセスが更新内容を論理的な変更内(論理変更)変換
. Su b scriberlo g ical replication w o rk erプロセスに論理変更を送信
. Su b scriberlo g ical replication w o rk erプロセスは理変更をテーブルに適用
6.1.4.
ロジカルレプリーションは以下のようなケースで有用と考えます。
1. 複数のD B サー上のデータ1台のDB サーバに統合したいケース(データ分析用途な)
2. 任意のテーブルデータのみレプリーションさせたいケース(システ間のデータの連携)
3. 異なるバージョン間でレプリケーションさせたいケー(バージョンアップ時のデータ移行など)
ロジカルレプリーションの典型的な利用例がPo stg reSQ L文書 [1] 記載さいますので、ご参照下さい。
[1] PostgreSQ L 10.0文書 - 31 理レプリケーショ
6.1.5.
ロジカルレプリーションの制限事項以下の通りです。(Po stg reSQ L 10時点)
PostgreSQL Enterprise Consortium
Page 110 of 285
6.2 ロジカルプリション制限事項
No.
1 データベーススキーおよびDDLンドはレプリ
ションされない
データベーススキーマは、p g_du mp --sch ema-o n lyを利用して移行可能
2 シーケンスはレプリケーションされない シーケンスはレプリーションさいが、
シーケンスよって裏付けさSERIAL型や識別列のデー、テーブルデータの一部としてレプリーショ
ン可能
3 TRUNCATEマンドはレプリケーションされない D ELETEマンドで回避することは可能
4 ラージオブジェトはレプリケーションされない 通常のテーブルにデータを格納する以外の回避方法
5 ル以外のオブジェクレプリケーシンでき
ビュー、マテリアイズドビュー、パーティションのルートテーブル(親テーブル) 外部ーブルはレプリケーションし
ようとるとエラーになる
制限事項の詳細は、Po stg reSQ Lの文書 [2] 記載さいますので、ご参照下さ
[2] PostgreSQ L 10.0文書 - 31 理レプリケーショ 31.4. 制限事項
6.2. ジカルレリケーショの設
ロジカルレプリーションの設定手順について確認します
ロジカルレプリーションでは、レプリーション対象とするテーブルを以下から選択することが可能です。
1. データベース内の全てのテーブルをレプリケーショ(本書ではデータベース単位の設定」と呼称)
2. データベースの任意のテーブルのみをレプリケーショ(本書ではテーブル単位の設定」呼称)
レプーション対象とるテルは、Pu b licatio n 成時に指定します。
Pu blicatio n の作成コマンドであるCREATE PU B LICATIO Nマンドの構文は以下の通りです。
CREATE PUBLICATION name
[ FOR TABLE [ ONLY ] table_name [ * ] [, ...]
| FOR ALL TABLES ]
[ WITH ( publication_parameter [= value] [, ... ] ) ]
CREATE PU B LICATIO Nマンド実行時にFO R ALL TAB LESを指定した場合は、
データベース内の全てのテーブルがレプリーション対象になり、
FO R TAB LEでは、レプリーション対象とるテルを指定します。
CREATE PUBLICATIO Nマンドの仕様は、Po stgreSQ Lの文 [1] 記載さていすので、ご照下さい。
[1] PostgreSQ L 10.0文書 - SQ Lマンド CREATE PU B LICATIO N
環境情報
手順は以下環境を前提に記載しております
6.3 環境情報
Po stg reSQ Lバージョン 10.1
O Sージョ Cen tO S 7.4
サーバ構成(各ホト名) 2ーバ(no d e1,no d e2)
6.2.1.
6.2.1.1.
データベース内の全てのテーブルをレプリケーションする際の設定手順にいて確認します。
6.2.1.2.
本検証で、下記のレプーション設定においてデータベース単位での、
柔軟なデータ連携(デープリーシ)が実現可能かの検証を実施しました。
PostgreSQL Enterprise Consortium
Page 111 of 285
6.2.1.3.
6.2.1.4.
事前準備
ロジカルレプリーションの環境を設定するn od e1およn o d e2おいて、
Po stg reSQ L10のインストールやデータベースクラスタ初期化・設定を実施します。
1. 環境準備
該当サーssh 接続します。
(node1,node2のサーバにおいて実)
ssh接続を用いて、
該当環境へ接続
ユーザ: root
パスワード: xxxxxxx
2. ホスト名の設定
名前解決のために各サーバのホスト名を設定します
(node1,node2のサーバにおいて実)
# vi /etc/hosts
[下記をファイル末尾に追加]
192.168.56.101 node1
192.168.56.102 node2
3. 5432ポートの解
Po stg reSQ L間の通信のため5432ポート解放しす。
(node1,node2のサーバにおいて実)
# firewall-cmd --permanent --add-port=5432/tcp
# firewall-cmd --reload
以下のコマンド5432でポートが解放されいることを確認します
PostgreSQL Enterprise Consortium
Page 112 of 285
(node1,node2のサーバにおいて実)
# firewall-cmd --list-ports
5432/tcp
4. Po stg reSQ L10yu mポジトリ追加
Po stg reSQ L10yu mポジトリ用のパッケージをインストールします
(node1,node2のサーバにおいて実)
# yum install -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-
x86_64/pgdg-centos10-10-1.noarch.rpm
以下のコマンドで該当のパッケージがインスールさとを確認します
(node1,node2のサーバにおいて実)
# yum list installed pgdg-centos10.noarch
[省略]
インスール済みパッージ
pgdg-centos10.noarch 10-1 installed
5. Po stg reSQ Lのインスール
yu mコマンドを用いてPo stg reSQ Lをインスールします。
(node1,node2のサーバにおいて実)
# yum install postgresql10 postgresql10-server postgresql10-libs postgresql10-contrib
以下のコマンドでパッージをインスールさとを確認します
(node1,node2のサーバにおいて実)
# yum list installed postgresql10 postgresql10-server postgresql10-libs postgresql10-
contrib
[省略]
インスール済みパッージ
postgresql10.x86_64 10.1-1PGDG.rhel7
@pgdg10-updates-testing
postgresql10-contrib.x86_64 10.1-1PGDG.rhel7
@pgdg10-updates-testing
postgresql10-libs.x86_64 10.1-1PGDG.rhel7
@pgdg10-updates-testing
postgresql10-server.x86_64 10.1-1PGDG.rhel7
@pgdg10-updates-testing
6. 環境変数の設定
po stg resーザの環境変数の設定を行います
PostgreSQL Enterprise Consortium
Page 113 of 285
(node1,node2のサーバにおいて実)
# su - postgres
$ vi ~/.bash_profile
[下記をファイル末尾に追加]
export PATH=${PATH}:/usr/pgsql-10/bin
export PGHOME=/usr/pgsql-10
export PGDATA=/var/lib/pgsql/10/data
export PGDATABASE=postgres
export PGPORT=5432
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/pgsql-10/lib
以下のコマンドで環境変数の設定を確認します。($PGDATA確認を例示しています。)
(node1,node2のサーバにおいて実)
$ exit
ログアウト
# su - postgres
$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/pgsql-10/bin
$ echo $PGDATA
/var/lib/pgsql/10/data
7. データベースク作成
データベースク作成を実施します
(node1,node2のサーバにおいて実)
$ initdb -D $PGDATA -A trust -U postgres --no-locale --encoding UTF8
8. po stg resq l.con f修正
po stg resq l.con fに以下を設定します
(node1,node2のサーバにおいて実)
$ vi $PGDATA/postgresql.conf
[下記の修正を加え]
listen_addresses = '*'  # 全てのネークインターフェースへの接続を受け付ける設定
wal_level = 'logical' # ロジカルレプリケーションに必要なWAL出力設定
max_wal_senders = 10 # wal senderプロセス数の最大数を10設定(デフォルト値)
max_replication_slots = 10 # プリーションスロッの最大数を10に設定(デフォト値)
log_line_prefix = '[%m][%d][%h][%u][%e][%p] ' # ログメッセージの解析時に必要な情報を付与
9. pg _h b a.con f
n od e1,n od e2間でのデータベース接続を許可します。
(node1,node2のサーバにおいて実)
$ vi $PGDATA/pg_hba.conf
[下記の修正を加え]
host all all 192.168.56.0/24 trust
上記の設定は、SubscriberPublisherのデータベースに接続る際に利用されます。
そのため、Publisherのみ上記設定が必要となります
10. Po stgreSQ L起動
Po stg reSQ Lを起動します
PostgreSQL Enterprise Consortium
Page 114 of 285
(node1,node2のサーバにおいて実)
$ pg_ctl start
以下のコマンドでPo stg reSQ Lの起動を確認しす。
(node1,node2のサーバにおいて実)
$ pg_ctl status
pg_ctl: サーが動作中で(PID: 3517)
/usr/pgsql-10/bin/postgres
ロジカルレプリーシンの動作確認(ータベース単位)
1. 動作確認用のデータベース作成
本検証で利用するータベースを作成します。
(node1,node2のサーバにおいて実)
$ createdb logicalreptest
以下のコマンドでデータベーが作成されたとを確認しす。
(node1,node2のサーバにおいて実)
$ psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
----------------+----------+----------+---------+-------+-----------------------
logicalreptest | postgres | UTF8 | C | C |
[省略]
2. 動作確認用のテーブル作成
作成したデーベーステス用のテーブルを作成します。
(node1,node2のサーバにおいて実)
$ psql -U postgres logicalreptest
=# CREATE TABLE t1logical (c1 INT, PRIMARY KEY (c1));
=# CREATE TABLE t2logical (c1 INT, PRIMARY KEY (c1));
以下のコマンドで作成したテーブルを確認しす。
=# \d
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+----------
public | t1logical | table | postgres
public | t2logical | table | postgres
(2 rows)
3. Pu blicatio n 作成
n od e1にデータベース内の全テーブル(作成したlog ica lt2logicalテーブル)をレプリーション対象とするPu b lication を作成しす。
PostgreSQL Enterprise Consortium
Page 115 of 285
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE PUBLICATION pub_node1_logicaldb FOR ALL TABLES;
以下のコマンドでPu b licatio n が作成されとを確認します。
作成したp u blication ではデータベース内の全テーブルをレプリーシン対象としているため
All tab les列がtru eであることを確認しす。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node1_logicaldb | postgres | t | t | t | t
(1 row)
4. Subscrip tio n 作成
n od e2n o d e1に作成したPu blica tion とレプリーションするSub scrip tion を作成します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node2_logicaldb CONNECTION 'host=node1 dbname=logicalreptest
port=5432 user=postgres' PUBLICATION pub_node1_logicaldb;
以下のコマンドでSub scrip tion が作成さとを確認します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node2_logicaldb | postgres | t | {pub_node1_logicaldb}
(1 row)
5. ロジカルレプリーション簡易動作検
スト用に作成し2つのーブルにードをそれぞINSERTします。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# INSERT INTO t1logical VALUES (1);
=# INSERT INTO t2logical VALUES (2);
=# SELECT * FROM t1logical;
c1
----
1
(1 rows)
=# SELECT * FROM t2logical;
c1
----
2
(1 rows)
Subscrip tio n 側のテーブルにレコードがINSERTれていることを確認します(プリーシンされいることを確認)
PostgreSQL Enterprise Consortium
Page 116 of 285
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t1logical;
c1
----
1 <-- node1同じ結果がレプリーションさてい
(1 rows)
----
2 <-- node1同じ結果がレプリーションさてい
(1 rows)
6.2.2.
6.2.2.1.
データベース内の任意のーブルのみレプリケーションする際の設定手順にいて確認します。
6.2.2.2.
本検証で、下記のレプーション設定においてテーブル単位での
柔軟なデータ連携(デープリーシ)が実現可能かの検証を実施しました。
6.2.2.3.
6.2.2.4.
データベース単位でレプリーションの構築手順にいて確認します。
ロジカルレプリーシンの動作確認(テーブル単位)
1. 動作確認用のデータベース作成
本検証で利用するータベースを作成します。
(node1,node2のサーバにおいて実)
$ createdb logicalreptest2
以下のコマンドでデータベーが作成されたとを確認しす。
PostgreSQL Enterprise Consortium
Page 117 of 285
(node1,node2のサーバにおいて実)
$ psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------------+----------+----------+---------+-------+-----------------------
logicalreptest2 | postgres | UTF8 | C | C |
[省略]
2. 動作確認用のテーブル作成
作成したデーベース検証用のーブルを作成します
(node1,node2のサーバにおいて実)
$ psql -U postgres logicalreptest2
=# CREATE TABLE t3logical (c1 INT, PRIMARY KEY (c1));
以下のコマンドでテーブルが作成さとを確認します
(node1,node2のサーバにおいて実)
=# \d
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+----------
public | t3logical | table | postgres
(1 row)
3. Pu blicatio n 作成
n od e1t3lo gicalテーブルのみをレプーション対象とPu b lication を作成します (F O R TAB LEt3logical)
(node1のサーおいて実施)
$ psql -U postgres logicalreptest2
=# CREATE PUBLICATION pub_node1_t3logical FOR TABLE t3logical;
以下のコマンドでPu b licatio n が作成されとを確認します。 作成しPu b lica tion では、All tables列がfalseであとを確認します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest2
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node1_t3logical | postgres | f | t | t | t
(1 row)
4. Subscrip tio n 作成
n od e2Pub licatio n プリーションするSu b scription を作成しす。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest2
=# CREATE SUBSCRIPTION sub_node2_t3logical CONNECTION 'host=node1 dbname=logicalreptest2
port=5432 user=postgres' PUBLICATION pub_node1_t3logical;
PostgreSQL Enterprise Consortium
Page 118 of 285
以下のコマンドでSub scrip tion が作成さとを確認します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest2
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node2_t3logical | postgres | t | {pub_node1_t3logical}
(1 row)
5. ロジカルレプリーション簡易動作検
スト用に作成したテーブルにレコードをINSERTします。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest2
=# INSERT INTO t3logical VALUES (1);
=# INSERT INTO t3logical VALUES (2);
=# SELECT * FROM t3logical;
c1
----
1
2
(2 rows)
Subscrip tio n 側のテーブルにもレコードINSERTていとを確認します(レプーションされていることを確認)
(node2のサーおいて実施)
$ psql -U postgres logicalreptest2
=# SELECT * FROM t3logical;
c1
----
1 <-- node1と同じ結果がレプーションさてい
2
(2 rows)
6.2.3.
6.2.3.1.
任意のテーブルをロジカルレプリケーションの対象とした状態で特定の更新処理のみ
レプーション対象とる際の手順を確認します。
6.2.3.2.
本検証で、下記のレプーション設定において更新処理の限定が実現可能かの検証を実施しました
6.2.3.3.
PostgreSQL Enterprise Consortium
Page 119 of 285
6.2.3.4.
初期状態
1. レプーション状態の確
現在のレプリーシン状態を確認します
(node1,node2のサーバにおいて実)
$ psql -x -U postgres -c "SELECT * FROM pg_stat_replication"
(0 rows)
2. スト用データース作成
本検証で利用するータベースを作成します。
(node1,node2のサーバにおいて実)
$ createdb testlogicalre
以下のコマンドでデータベーが作成された事を確認しす。
(node1,node2のサーバにおいて実)
$ psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+----------+----------+---------+-------+-----------------------
testlogicalre | postgres | UTF8 | C | C | <-- 成したDB
を確認
[省略]
3. スト用テーブル作成
作成したデーベーステス用のテーブルを作成します。
(node1,node2のサーバにおいて実)
$ psql -U postgres testlogicalre
=# CREATE TABLE t1logical (c1_no integer PRIMARY KEY, c2_date date);
=# SELECT * FROM t1logical;
c1_no | c2_date
-------+---------
(0 rows)
PostgreSQL Enterprise Consortium
Page 120 of 285
以下のコマンドで作成したテーブルを確認しす。
(node1,node2のサーバにおいて実)
=# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+----------
public | t1logical | table | postgres
(1 row)
ロジカルレプリーシンでのレプーション内容の変
1. Pu blicatio n Su b scriptio n を作成
n od e1作成したt1logicalーブルに対し、in sertu p d ateをレプリケーション対象とするPu b lication を作成しす。
(node1のサーおいて実施)
=# CREATE PUBLICATION pub_test_node1 FOR TABLE t1logical WITH (publish='insert,
update'); <-- 指定した更新処理のみをレプリケーショ
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
----------------+------------+-----------
pub_test_node1 | public | t1logical
(1 row)
以下のコマンドでPu b licatio n が作成され事を確認します。
作成したp u blication では対象のテーブルのin sertu p dateをレプリーシン対象としているため
In sertsUp d atestru eであること確認しす。
(node1のサーおいて実施)
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
----------------+----------+------------+---------+---------+---------
pub_test_node1 | postgres | f | t | t | f
<-- DELETEレプリーション対象に含め
(1 row)
n od e2n o de1作成しPub licatio n プリーションするSu b scription を作成しす。
(node2のサーおいて実施)
=# CREATE SUBSCRIPTION sub_test_node2 CONNECTION 'host=node1 dbname=testlogicalre
port=5432 user=postgres' PUBLICATION pub_test_node1;
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+-----------
16435 | 16430 | r | 0/181A380
(1 row)
以下のコマンドでSub scrip tion が作成さ事を確認します。
PostgreSQL Enterprise Consortium
Page 121 of 285
(node2のサーおいて実施)
# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
----------------+----------+---------+------------------
sub_test_node2 | postgres | t | {pub_test_node1}
(1 row)
2. レプーション状態確認
現在のレプリーシン状態を確認します
作成したPu b lica tion Su b scription が正常にレプリーシンされいるかを
applicatio n _n amestatesyn c_state項目で確認します。
(node1のサーおいて実施)
$ psql -x -U postgres -c "SELECT * FROM pg_stat_replication"
-[ RECORD 1 ]----+------------------------------
pid | 1264
usesysid | 10
usename | postgres
application_name | sub_test_node2
<-- subscription_nameが表示さ
client_addr | 192.168.56.102
client_hostname |
client_port | 53076
backend_start | 2017-12-20 10:44:04.503952+09
backend_xmin |
state | streaming
<-- streaming が表示される
sent_lsn | 0/181A380
write_lsn | 0/181A380
flush_lsn | 0/181A380
replay_lsn | 0/181A380
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
<-- async(非同期)
ロジカルレプリーシン動作確認
1. ーブルにデータを追加
スト用に作成しPu b lication 側のテーブルにレコードをINSERTします。
(node1のサーおいて実施)
=# INSERT INTO t1logical VALUES (1,'2017/12/20');
=# SELECT * FROM t1logical;
c1_no | c2_date
-------+------------
1 | 2017-12-20
(1 row)
Subscrip tio n 側のテーブルにもレコードINSERTてい事を確認します。(プリションされいる事を確認)
PostgreSQL Enterprise Consortium
Page 122 of 285
(node2のサーおいて実施)
=# SELECT * FROM t1logical;
c1_no | c2_date
-------+------------
1 | 2017-12-20
(1 row)
2. ーブルのデータを更新
Pu blicatio n 側のーブルのレコードをUPDATEします。
(node1のサーおいて実施)
=# UPDATE t1logical SET c2_date = '2017/12/25' WHERE c1_no = 1;
=# SELECT * FROM t1logical;
c1_no | c2_date
-------+------------
1 | 2017-12-25
(1 row)
Subscrip tio n 側のテーブルでもレコードがUPD ATEされいる事を確認します。(レプリケーシンされいる事を確認)
(node2のサーおいて実施)
=# SELECT * FROM t1logical;
c1_no | c2_date
-------+------------
1 | 2017-12-25
(1 row)
3. ーブルのデータを削除
Pu blicatio n 側のーブルのレコードをDELETEします
(node1のサーおいて実施)
=# DELETE FROM t1logical WHERE c1_no = 1;
=# SELECT * FROM t1logical;
c1_no | c2_date
-------+---------
(0 rows)
<-- 指定のデータが削除され
Subscrip tio n 側のテーブルではレコードがDELETEいない事を確認します(プリーシンされいない事を確認)
(node2のサーおいて実施)
=# SELECT * FROM t1logical;
c1_no | c2_date
-------+------------
1 | 2017-12-25
<-- DELETEレプリーションさてい
(1 row)
6.2.4.
ロジカルレプリーションの構築に必要な設定にいて説明します。
6.2.4.1.
PostgreSQL Enterprise Consortium
Page 123 of 285
ロジカルレプリーションに関係する行時パラータ以下のとおりです。
6.4 ロジカルプリションに関係る実行時パラータ
w al_level W AL書かれ情報量。ロジカルプリーションでは
lo g icalを設定する。
ロジカルレプリーションのPu blish er
ーミングレプーションのマス
max_w al_send ers w al sen d erプロセスの最大数 ロジカルレプリーションのPu blish er
ーミングレプーションのマス
max_log ical_rep lication _w o rk ers lo g ical replication w o rk erプロセスの最大数 ジカルレプリケーションのSu b scrib er
max_w orker_processes バックグラウンドプロセスの最大数 ロジカルレプリーションのPu blish erSu b scrib er
max_syn c_w orkers_p er_sub scrip tion Su b scrip tion あたりのワーカープロセスの並列 ロジカルレプリケーションのSu b scrib er
max_replication _slots レプーションスロットの最大数 ロジカルレプリーションのPu blish er
ーミングレプーションのマス
6.2.4.2.
いくかの実行時パラメタはロジカルレプリーシン稼働時に起動さプロセス数との関係を理解して設定値を決める必要があります。では以下の実行時パラ
ついて考察します
max_w al_send ers
max_log ical_rep lication _w o rk ers
max_w orker_processes
max_syn c_w orkers_p er_sub scrip tion
max_replication _slots
本章は以下の環境を利用した検証結果を元に解説します。
PostgreSQL Enterprise Consortium
Page 124 of 285
ロジカルレプリーションはPu b lish er1台、Su b scrib er1台で構成
ロジカルレプリーションのPu blish erサーバ1IPアドレス 19216812731では、データベースクラスタ内1のデータベースを作成
pu b d b: レプリーシン対象のテーブルを個別定義するPu b licatio n p u b 1
pu b 1のレプーション対象としてーブルdata1
ロジカルレプリーションのSubscrib erサーバ2IPアドレス 192.168.127.32では、データベー内に1のデータベースを
sub d b: Pu b lish erpu b d b デーベースに定義しPub licatio n から更データを受け取るSu b scrip tion sub 1およびテーブルd a ta1を作成
Pu blish erSu b scrib erのプロセスを認する以下のロセスが起動していることがわかります。
lo g ical replication lau n ch er: Pu b lish er, Sub scriber1
w al send er: Pu b lish er1
lo g ical replication w o rk er: Su b scrib er1
(サーバ1において実施)
$ ps aux | grep postgres
postgres 2503 0.0 0.8 389296 16492 pts/0 S 15:15 0:00 /usr/pgsql-10/bin/postgres
postgres 2504 0.0 0.1 242108 1936 ? Ss 15:15 0:00 postgres: logger process
postgres 2506 0.0 0.1 389448 3664 ? Ss 15:15 0:00 postgres: checkpointer process
postgres 2507 0.0 0.1 389296 3428 ? Ss 15:15 0:00 postgres: writer process
postgres 2508 0.0 0.3 389296 6324 ? Ss 15:15 0:00 postgres: wal writer process
postgres 2509 0.0 0.1 389752 3048 ? Ss 15:15 0:00 postgres: autovacuum launcher
process
postgres 2510 0.0 0.1 244360 2204 ? Ss 15:15 0:00 postgres: stats collector process
postgres 2511 0.0 0.1 389588 2492 ? Ss 15:15 0:00 postgres: bgworker: logical
replication launcher
postgres 2513 0.0 0.3 392428 5788 ? Ss 15:15 0:00 postgres: wal sender process
repusr1 192.168.127.32(40906) idle
(サーバ2において実施)
$ ps aux | grep postgres
postgres 2387 0.0 0.8 389296 16492 pts/0 S 15:15 0:00 /usr/pgsql-10/bin/postgres
postgres 2388 0.0 0.1 242108 1932 ? Ss 15:15 0:00 postgres: logger process
postgres 2390 0.0 0.2 389448 3928 ? Ss 15:15 0:00 postgres: checkpointer process
postgres 2391 0.0 0.1 389296 3428 ? Ss 15:15 0:00 postgres: writer process
postgres 2392 0.0 0.3 389296 6324 ? Ss 15:15 0:00 postgres: wal writer process
postgres 2393 0.0 0.1 389752 3076 ? Ss 15:15 0:00 postgres: autovacuum launcher
process
postgres 2394 0.0 0.1 244360 2200 ? Ss 15:15 0:00 postgres: stats collector process
postgres 2395 0.0 0.1 389588 2756 ? Ss 15:15 0:00 postgres: bgworker: logical
replication launcher
postgres 2398 0.0 0.3 397072 6320 ? Ss 15:15 0:00 postgres: bgworker: logical
replication worker for subscription 16394
Publication,Subscription
Pu blish er,Su b scrib erそれぞれテーブルdata2を追加し、テーブルdata2複製するPu b lication ,Su b scrip tion を作成します。
(サーバ1において実施)
pubdb=> CREATE TABLE data2 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
pubdb=> CREATE PUBLICATION pub2 FOR TABLE data2;
(サーバ2において実施)
subdb=> CREATE TABLE data2 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
subdb=# CREATE SUBSCRIPTION sub2 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub2;
NOTICE: created replication slot "sub2" on publisher
CREATE SUBSCRIPTION
Pu blish erの動的統計情報ビューpg_stat_rep lication を見ると、今回追加したレプリーシ(RECO RD 1)元々設定済のレプーショ(RECO RD 2)の情報が確認
できます。
PostgreSQL Enterprise Consortium
Page 125 of 285
(サーバ1において実施)
pubdb=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 2692
usesysid | 16385
usename | repusr1
application_name | sub2
client_addr | 192.168.127.32
client_hostname |
client_port | 40909
backend_start | 2017-12-14 16:22:28.821828+09
backend_xmin |
state | streaming
sent_lsn | 0/16D7B60
write_lsn | 0/16D7B60
flush_lsn | 0/16D7B60
replay_lsn | 0/16D7B60
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 2 ]----+------------------------------
pid | 2513
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 40906
backend_start | 2017-12-14 15:15:46.183256+09
backend_xmin |
state | streaming
sent_lsn | 0/16D7B60
write_lsn | 0/16D7B60
flush_lsn | 0/16D7B60
replay_lsn | 0/16D7B60
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
Pu blish erSu b scrib erのプロセスを認する以下のプロセスが起動しており、w al sen d er, lo g ical replication w orkerがそれぞSub scription単位に起
動していることがわかりす。
lo g ical replication lau n ch er: Pu b lish er, Sub scriber1で変化なし
w al send er: Pu b lish er2
lo g ical replication w o rk er: Su b scriber2
PostgreSQL Enterprise Consortium
Page 126 of 285
(サーバ1において実施)
$ ps aux | grep postgres
postgres 2503 0.0 0.8 389296 16492 pts/0 S 15:15 0:00 /usr/pgsql-10/bin/postgres
postgres 2504 0.0 0.1 242108 1936 ? Ss 15:15 0:00 postgres: logger process
postgres 2506 0.0 0.2 389448 4188 ? Ss 15:15 0:00 postgres: checkpointer process
postgres 2507 0.0 0.1 389296 3428 ? Ss 15:15 0:00 postgres: writer process
postgres 2508 0.0 0.3 389296 6324 ? Ss 15:15 0:00 postgres: wal writer process
postgres 2509 0.0 0.1 389752 3048 ? Ss 15:15 0:00 postgres: autovacuum launcher
process
postgres 2510 0.0 0.1 244360 2204 ? Ss 15:15 0:00 postgres: stats collector process
postgres 2511 0.0 0.1 389588 2492 ? Ss 15:15 0:00 postgres: bgworker: logical
replication launcher
postgres 2513 0.0 0.3 392428 5788 ? Ss 15:15 0:00 postgres: wal sender process
repusr1 192.168.127.32(40906) idle
postgres 2692 0.0 0.2 392292 5252 ? Ss 16:22 0:00 postgres: wal sender process
repusr1 192.168.127.32(40909) idle
(サーバ2において実施)
$ ps aux | grep postgres
postgres 2387 0.0 0.8 389296 16492 pts/0 S 15:15 0:00 /usr/pgsql-10/bin/postgres
postgres 2388 0.0 0.1 242108 1932 ? Ss 15:15 0:00 postgres: logger process
postgres 2390 0.0 0.2 389448 4192 ? Ss 15:15 0:00 postgres: checkpointer process
postgres 2391 0.0 0.1 389296 3428 ? Ss 15:15 0:00 postgres: writer process
postgres 2392 0.0 0.3 389296 6324 ? Ss 15:15 0:00 postgres: wal writer process
postgres 2393 0.0 0.1 389752 3076 ? Ss 15:15 0:00 postgres: autovacuum launcher
process
postgres 2394 0.0 0.1 244360 2200 ? Ss 15:15 0:00 postgres: stats collector process
postgres 2395 0.0 0.1 389588 2756 ? Ss 15:15 0:00 postgres: bgworker: logical
replication launcher
postgres 2398 0.0 0.3 397072 6320 ? Ss 15:15 0:00 postgres: bgworker: logical
replication worker for subscription 16394
postgres 2571 0.0 0.3 397072 5992 ? Ss 16:22 0:00 postgres: bgworker: logical
replication worker for subscription 16400
次にロジカルプリーシンのSu b scriptio n 成時に実行さ初期データのコピー処理による起動プロセスの増減を確認します。ここではベンチークツールp g b ench
を使ってあらかじめデータベースpub d b 1000万件の初期データを持つテーブルpgb en ch _acco u n tsを作成します
(サーバ1において実施)
$ pgbench -i -s 10 -U pubusr1 pubdb
Pu blish erのデータベースp u b db 接続し、新たなPu b lication pu b 3作成します。
(サーバ1において実施)
pubdb=> CREATE PUBLICATION pub3 FOR TABLE pgbench_accounts;
Subscrib erのデータベースsu b db 接続し、レプリケーション対象テーブルを作成します
(サーバ2において実施)
subdb=> CREATE TABLE pgbench_accounts (aid INT PRIMARY KEY, bid INT, abalance INT, filler
character(84));
データベースsu b d b Su b scription sub 3を作成し、ロジカルプリーションを開始します
(サーバ2において実施)
subdb=# CREATE SUBSCRIPTION sub3 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub3;
Subscrip tio n su b 3作成した直後Pu b lish er,Su bscrib erの起動プロセスを確認すると、w al send er, logical replication w orkerがそれぞSu b scription
加え初期データピーを実行するプロセス分増えていることがわかります
lo g ical replication lau n ch er: Pu b lish er, Sub scriber1で変化なし
PostgreSQL Enterprise Consortium
Page 127 of 285
w al send er: Pu b lish er4。うち1は初期データピー用のプロセス
lo g ical replication w o rk er: Su b scriber4。うち1は初期データピー用のプロセス
(サーバ1において実施)
$ ps aux | grep postgres
postgres 2503 0.0 0.6 389296 12532 ? S 1214 0:01 /usr/pgsql-10/bin/postgres
postgres 2504 0.0 0.0 242108 1576 ? Ss 1214 0:00 postgres: logger process
postgres 2506 0.0 2.2 389612 42160 ? Ss 1214 0:00 postgres: checkpointer process
postgres 2507 0.0 0.1 389296 2892 ? Ss 1214 0:00 postgres: writer process
postgres 2508 0.0 0.3 389296 5836 ? Ss 1214 0:02 postgres: wal writer process
postgres 2509 0.0 0.1 389752 2564 ? Ss 1214 0:00 postgres: autovacuum launcher
process
postgres 2510 0.0 0.0 244360 1816 ? Ss 1214 0:02 postgres: stats collector process
postgres 2511 0.0 0.1 389588 2120 ? Ss 1214 0:00 postgres: bgworker: logical
replication launcher
postgres 2513 0.0 1.9 425924 36336 ? Ss 1214 0:24 postgres: wal sender process
repusr1 192.168.127.32(40906) idle
postgres 2692 0.0 1.9 425852 35920 ? Ss 1214 0:24 postgres: wal sender process
repusr1 192.168.127.32(40909) idle
postgres 5731 0.0 0.2 392292 5248 ? Ss 10:15 0:00 postgres: wal sender process
repusr1 192.168.127.32(40958) idle
postgres 5732 19.8 0.4 392592 8788 ? Ss 10:15 0:01 postgres: wal sender process
repusr1 192.168.127.32(40959) COPY
(サーバ2において実施)
$ ps aux | grep postgres
postgres 2387 0.0 0.8 389296 16492 ? S 1214 0:01 /usr/pgsql-10/bin/postgres
postgres 2388 0.0 0.1 242108 2000 ? Ss 1214 0:00 postgres: logger process
postgres 2390 0.0 2.3 389612 43740 ? Ss 1214 0:00 postgres: checkpointer process
postgres 2391 0.0 0.1 389296 3428 ? Ss 1214 0:00 postgres: writer process
postgres 2392 0.0 0.3 389296 6324 ? Ss 1214 0:01 postgres: wal writer process
postgres 2393 0.0 0.1 389752 3092 ? Ss 1214 0:00 postgres: autovacuum launcher
process
postgres 2394 0.0 0.1 244360 2200 ? Ss 1214 0:02 postgres: stats collector process
postgres 2395 0.0 0.1 389588 2756 ? Ss 1214 0:00 postgres: bgworker: logical
replication launcher
postgres 2398 0.0 0.3 397072 6320 ? Ss 1214 0:03 postgres: bgworker: logical
replication worker for subscription 16394
postgres 2571 0.0 0.3 397072 5992 ? Ss 1214 0:03 postgres: bgworker: logical
replication worker for subscription 16400
postgres 5597 0.0 0.3 397072 5728 ? Ss 10:15 0:00 postgres: bgworker: logical
replication worker for subscription 16418
postgres 5598 83.0 3.5 397536 67052 ? Rs 10:15 0:06 postgres: bgworker: logical
replication worker for subscription 16418 sync 16413
お、初期データのコピーが完了するコピー用のプロセス(上記PID 5732,5598)が終了し、w al sen d er,logical replication w orkerの数がSu b scrip tion と同じ3
変化する確認できました
max_w orker_processes
max_w orker_processesはバックグラウンドプロセスの最大数を定義する実行時パラータでデフォルト値は8です。ロジカルレプリケーションに関係するプロセスもバックグラ
ウンドプロセスとして起動するため、このパラータとの関係を検証しす。
まずSu b scrib ermax_w orker_processes3変更して再起動すると、サーバログ以下の様エラーメッセージが出力さます
(サーバ2のサーバログ)
2017-12-15 11:00:44.951 JST [5755] LOG: logical replication apply worker for subscription "sub1"
has started
2017-12-15 11:00:44.963 JST [5756] LOG: logical replication apply worker for subscription "sub2"
has started
2017-12-15 11:00:44.966 JST [5754] WARNING: out of background worker slots
2017-12-15 11:00:44.966 JST [5754] HINT: You might need to increase max_worker_processes.
の時、Su b scriberの動的統計情報ビューp g _stat_activityでバッウンドプロセスの情報を表示すると、lo g ical replication lau n ch er log ical rep licatio n
w orker がそれぞれバッウンドプロセスとして起動しいるとがわかります
PostgreSQL Enterprise Consortium
Page 128 of 285
(サーバ2において実施)
postgres=# select datname,pid,usename,backend_start,wait_event_type,wait_event,state,backend_type
from pg_stat_activity where backend_type = 'background worker';
datname | pid | usename | backend_start | wait_event_type | wait_event
| state | backend_type
---------+------+----------+-------------------------------+-----------------+---------------------
+-------+-------------------
| 5790 | postgres | 2017-12-15 11:01:16.733998+09 | Activity | LogicalLauncherMain
| | background worker
subdb | 5791 | postgres | 2017-12-15 11:01:16.742653+09 | Activity | LogicalApplyMain
| idle | background worker
subdb | 5792 | postgres | 2017-12-15 11:01:16.750161+09 | Activity | LogicalApplyMain
| idle | background worker
subdb | 5793 | postgres | 2017-12-15 11:01:16.760481+09 | Activity | LogicalApplyMain
| idle | background worker
一方でPu b lish ermax_w orker_pro cesses3に変更し再起動してもサーバログエラーメッセージは力されません。の時のPublish erのバッウンドプロセス
の情報を表示すると、lo g ical replication lau n ch er けがカウントさw al sen d erはカウントさていせん。
(サーバ1において実施)
pubdb=# select datname,pid,usename,backend_start,wait_event_type,wait_event,state,backend_type
from pg_stat_activity where backend_type = 'background worker';
datname | pid | usename | backend_start | wait_event_type | wait_event
| state | backend_type
---------+------+----------+-------------------------------+-----------------+---------------------
+-------+-------------------
| 2511 | postgres | 2017-12-14 15:15:28.478386+09 | Activity | LogicalLauncherMain
| | background worker
のようにPu blish erw al sen derSu b scriberlo g ical replication w o rk erはともSub scrip tion の数に合せて増加しますが、Pu b lish erw al send er
max_w orker_processes管理するバックグラウンドプロセスとは異なるいであることがわかりました
6.2.4.3.
検証結果踏まえて以下の実行時パラータの決め方にいて考察します。
max_w al_senders
ロジカルレプリーションでの起動数とスーミングレプーションのスレーブ数を考慮して以下の数が必要です。
必要数 = (ストリーミングレプリーシンのスレーブ数) + (ロジカルプリーションのSub scrip tion 2)
ロジカルレプリーションの初期データ同期プロセスが起動する分を考慮して2倍する。
初期データ同期プロセス max_syn c_w o rk ers_p er_su b scrip tion デフォルト2応じて変化するめ、こ増やす場合は2の部分も変化す
る。
Po stg reSQ L10.1のデフォルト値10上記必要数で不足しそうなら変更しておく
max_logical_replication_workers
ロジカルレプリーションでの起動数考慮して以下の数が必要で
必要数 = のサー作成するSub scrip tion 2
ロジカルレプリーションの初期データ同期時に増えるプセス数を考慮して2倍する。
初期データ同期プロセス max_syn c_w o rk ers_p er_su b scrip tion デフォルト2応じて変化するめ、こ増やす場合は2の部分も変化す
る。
Po stg reSQ L10.1のデフォルト値4。上記必要数で不足しそうなら変更しておく
max_w orker_processes
ロジカルレプリーションでの起動数考慮して以下の数が必要で
必要数 = のサー作成するSub scrip tion 2 + 1(= lo gical replica tion lau n ch erの分) + その他のバッウンドプロセス(任意)
初期データ同期プロセス max_syn c_w o rk ers_p er_su b scrip tion デフォルト2応じて変化するめ、こ増やす場合は2の部分も変化す
る。
Po stg reSQ L10.1のデフォルト値8。上記必要数で不足しそうなら変更しておく
max_sync_workers_per_subscription
Po stg reSQ L10.1のデフォルト値2の場合1がレプリーシン用に確保されるため初期データ同期の並列度は1で固定されます
初期データ同期の並列度は1テーブルにつ1までです。複数テーブルに対する同期処理の並列度上がりますが、同じテーブルに対する並列度は上がりません。
max_replication_slots
PostgreSQL Enterprise Consortium
Page 129 of 285
ロジカルレプリーションでの作成数と合わせ以下の数が必要です。
必要数 = ロジカルレプーションで作成するSu bscrip tionの数 2 + ストリーミングレプリーションで作成するレプリーシンストの(任意)
初期データ同期プロセスは一時的にレプリケーションスロットを作成するめ、こを増やす場合は2の部分も変化する
Po stg reSQ L10.1のデフォルト値10上記必要数で不足しそうなら変更しておく
6.3. ジカルレリケーショの応
6.3.1. primary key
6.3.1.1.
primary keyが定義さいないテルにおけるロジカルレプリーシンの設定方法を確認します。
ロジカルレプリーションではUPDATEもしくDELTEをレプリーシンさせるめに 変更したレコードを特定するめの情報であるREPLICA IDENTITYPu b lication
のテーブルに設定する必要があります REPLICA ID ENTITYが指定さていいテーブルがPu b licatio n 加された場合、UPD ATEDELETE行われるとエラー
が発生します。
デフォルトではp rimary keyが定義されテーブルの場合p rimary keyR EPLICA IDENTITYして自動設定さます またREPLICA ID E NTITYにユニークインデック
(NO T NULLつ部分インデックスや遅延可能インデッスではない)を設定するとで、UPDATEDELE TEのレプリーションが可能で テーブルに上記のキーが存在しな
い場合は、REPLICA IDENTITYF ULLを設定するで、UPDATED ELETEのレプーションが可能です。[1]
REPLICA ID ENTITYは、ロジカルプリーシン利用時においてW ALファルに書き込む情報量に影響します REPLICA IDENTITY指定さた列では、変更前の古
いレコードがW ALイルに書き込まれます。 FULLを指定した場合には、古いレコードを全てW ALファイルに書き込みため非効率です。
REPLICA ID ENTITYの設定方法の詳細は、Po stgreSQ L 文書をご確認下さい[2]
[1] PostgreSQ L 10.0文書 - 31 理レプリケーショ 31.1. パブリーショ
[2] PostgreSQ L 10.0文書 - SQ Lマンド ALTER TAB LE
6.3.1.2.
primary keyが定義さいないテルにおけるレプーションが可能な否かを確認するめ、 表のパターンでロジカルレプリションの設定を実施しました パタ
ンと動作確認結果は下表の通りです。(○:プリーション可能、× :レプーション不可)
6.5 primary keyが定義さいないテルの動作確認
IN SERT UPDATE DELETE
primary keyが定義さーブル -
u n iq u e制約(n o t n u ll制約)replica
id en tityu n iq u eインデッを指定
-
上記に該当しいテーブ × × Pu b lication のテーブルにDELETE
よびUPDATEを実施した場合、エラーに
上記に該当しいテーブルにreplica
id en tityfu llを指定
-
6.3.1.3.
PostgreSQL Enterprise Consortium
Page 130 of 285
6.3.1.4.
1. 動作確認用のテーブル作成
スト用のテーブルを作成しす。
(node1,node2のサーバにおいて実)
$ psql -U postgres logicalreptest3
=# CREATE TABLE t8logical (c1 INT, c2 TEXT, PRIMARY KEY (c1));
=# CREATE TABLE t9logical (c1 INT NOT NULL, c2 TEXT);
=# CREATE UNIQUE INDEX t9logical_ukey ON t9logical (c1);
=# ALTER TABLE t9logical REPLICA IDENTITY USING INDEX t9logical_ukey;
=# CREATE TABLE t10logical (c1 INT, c2 TEXT);
=# CREATE TABLE t11logical (c1 INT, c2 TEXT);
=# ALTER TABLE t11logical REPLICA IDENTITY FULL;
以下のコマンドでテーブルが作成さとを確認します
(node1,node2のサーバにおいて実)
=# \d
List of relations
Schema | Name | Type | Owner
--------+------------+-------+----------
public | t10logical | table | postgres
public | t11logical | table | postgres
public | t8logical | table | postgres
public | t9logical | table | postgres
(4 rows)
2. Pu blicatio n 作成
n od e1の各テーブルをレプリケーション対象とするPu b licatio n を作成しす。
PostgreSQL Enterprise Consortium
Page 131 of 285
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# CREATE PUBLICATION pub_node1_t8logical FOR TABLE t8logical;
=# CREATE PUBLICATION pub_node1_t9logical FOR TABLE t9logical;
=# CREATE PUBLICATION pub_node1_t10logical FOR TABLE t10logical;
=# CREATE PUBLICATION pub_node1_t11logical FOR TABLE t11logical;
以下のコマンドでPu b licatio n が作成されとを確認します。
(node1のサーおいて実施)
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
----------------------+----------+------------+---------+---------+---------
pub_node1_t10logical | postgres | f | t | t | t
pub_node1_t11logical | postgres | f | t | t | t
pub_node1_t8logical | postgres | f | t | t | t
pub_node1_t9logical | postgres | f | t | t | t
(5 rows)
3. Subscrip tio n 作成
n od e2n o d e1作成したPu b lication とレプリケーシンすSu b scrip tion を作成します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest3
=# CREATE SUBSCRIPTION sub_node2_t8logical CONNECTION 'host=node1 dbname=logicalreptest3
port=5432 user=postgres' PUBLICATION pub_node1_t8logical;
=# CREATE SUBSCRIPTION sub_node2_t9logical CONNECTION 'host=node1 dbname=logicalreptest3
port=5432 user=postgres' PUBLICATION pub_node1_t9logical;
=# CREATE SUBSCRIPTION sub_node2_t10logical CONNECTION 'host=node1
dbname=logicalreptest3 port=5432 user=postgres' PUBLICATION pub_node1_t10logical;
=# CREATE SUBSCRIPTION sub_node2_t11logical CONNECTION 'host=node1
dbname=logicalreptest3 port=5432 user=postgres' PUBLICATION pub_node1_t11logical;
以下のコマンドでSub scrip tion が作成さとを確認します。
(node2のサーおいて実施)
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
----------------------+----------+---------+------------------------
sub_node2_t10logical | postgres | t | {pub_node1_t10logical}
sub_node2_t11logical | postgres | t | {pub_node1_t11logical}
sub_node2_t8logical | postgres | t | {pub_node1_t8logical}
sub_node2_t9logical | postgres | t | {pub_node1_t9logical}
(4 rows)
4. ロジカルレプリーション動作検証確
primary keyが定義さーブルに対してINSERT,UPDATE,DELE TEを実施します。
PostgreSQL Enterprise Consortium
Page 132 of 285
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# INSERT INTO t8logical VALUES (1, 'MERRY CHRISTMAS');
=# INSERT INTO t8logical VALUES (2, 'CHRISTMAS DAY');
=# UPDATE t8logical SET c2 = 'HAPPY NEW YEAR' WHERE c1 = 2;
=# DELETE FROM t8logical WHERE c1 = 1;
=# SELECT * FROM t8logical;
c1 | c2
----+----------------
2 | HAPPY NEW YEAR
(1 row)
Subscrip tio n 側にデータが反映されいること確認します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# SELECT * FROM t8logical;
c1 | c2
----+----------------
2 | HAPPY NEW YEAR
(1 row)
u n iq u e制約(n o t n u ll制約)replica id en tityu n iq u eインデッが定義さーブルに対してINSERT,UPDATE,DELETEを実施します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# INSERT INTO t9logical VALUES (1, 'MERRY CHRISTMAS');
=# INSERT INTO t9logical VALUES (2, 'CHRISTMAS DAY');
=# UPDATE t9logical SET c2 = 'HAPPY NEW YEAR' WHERE c1 = 2;
=# DELETE FROM t9logical WHERE c1 = 1;
=# SELECT * FROM t9logical;
c1 | c2
----+----------------
2 | HAPPY NEW YEAR
(1 row)
Subscrip tio n 側にデータが反映されいること確認します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# SELECT * FROM t9logical;
c1 | c2
----+----------------
2 | HAPPY NEW YEAR
(1 row)
上記に該当しいテーブルに対してINSERT,U PD ATE,DELETEを実施します
PostgreSQL Enterprise Consortium
Page 133 of 285
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# INSERT INTO t10logical VALUES (1, 'MERRY CHRISTMAS');
=# INSERT INTO t10logical VALUES (2, 'CHRISTMAS DAY');
=# UPDATE t10logical SET c2 = 'HAPPY NEW YEAR' WHERE c1 = 2;
ERROR: cannot update table "t10logical" because it does not have a replica identity and
publishes updates
HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
REPLICA IDENTITY指定さいない場合はUPDATEできない旨がメッセージとして出力さ
=# DELETE FROM t10logical WHERE c1 = 1;
ERROR: cannot delete from table "t10logical" because it does not have a replica
identity and publishes deletes
HINT: To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.
=# SELECT * FROM t10logical;
c1 | c2
----+-----------------
1 | MERRY CHRISTMAS
2 | CHRISTMAS DAY
(2 rows)
Subscrip tio n 側にデータが反映されないことを確認します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# SELECT * FROM t10logical;
c1 | c2
----+-----------------
1 | MERRY CHRISTMAS
2 | CHRISTMAS DAY
(2 rows)
上記に該当しいテーブルにreplica id en tityfu llを指定したテーブルに対してINSERT,U PDATE,DELETEを実施します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# INSERT INTO t11logical VALUES (1, 'MERRY CHRISTMAS');
=# INSERT INTO t11logical VALUES (2, 'CHRISTMAS DAY');
=# UPDATE t11logical SET c2 = 'HAPPY NEW YEAR' WHERE c1 = 2;
=# DELETE FROM t11logical WHERE c1 = 1;
=# SELECT * FROM t11logical;
c1 | c2
----+----------------
2 | HAPPY NEW YEAR
(1 row)
Subscrip tio n 側にデータが反映されいること確認します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest3
=# SELECT * FROM t11logical;
c1 | c2
----+----------------
2 | HAPPY NEW YEAR
(1 row)
6.3.2.
6.3.2.1.
PostgreSQL Enterprise Consortium
Page 134 of 285
6.3.2.1.
ロジカルレプリーションにおいて同期レプリケーシンを定する順を確認します
6.3.2.2.
本検証で、下記のレプーション設定において同期モードが実現可能かの検証を実施しました
6.3.2.3.
6.3.2.4.
初期状態
1. レプーション状態の確
現在のレプリーシン状態を確認します
(node1,node2のサーバにおいて実)
$ psql -x -U postgres -c "SELECT * FROM pg_stat_replication"
(0 rows)
2. スト用データース作成
本検証で利用するータベースを作成します。
(node1,node2のサーバにおいて実)
$ createdb testlogicaldb
以下のコマンドでデータベーが作成された事を確認しす。
(node1,node2のサーバにおいて実)
$ psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+----------+----------+---------+-------+-----------------------
testlogicaldb | postgres | UTF8 | C | C | <-- 成したDB
を確認
[省略]
3. スト用テーブル作成
作成したデーベーステス用のテーブルを作成します。
PostgreSQL Enterprise Consortium
Page 135 of 285
(node1,node2のサーバにおいて実)
$ psql -U postgres testlogicaldb
=# CREATE TABLE t1logical (c1_no integer PRIMARY KEY, c2_date_time timestamp);
=# SELECT * FROM t1logical;
c1_no | c2_date_time
-------+--------------
(0 rows)
以下のコマンドで作成したテーブルを確認しす。
(node1,node2のサーバにおいて実)
=# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+----------
public | t1logical | table | postgres
(1 row)
ロジカルレプリーシンでの作成
1. Pu blicatio n Su b scriptio n を作成
n od e1作成したt1logicalーブルをレプーション対象とするPu b lication を作成します
(node1のサーおいて実施)
=# CREATE PUBLICATION test_slot1 FOR TABLE t1logical;
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
------------+------------+-----------
test_slot1 | public | t1logical
(1 row)
以下のコマンドでPu b licatio n が作成され事を確認します。
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
------------+----------+------------+---------+---------+---------
test_slot1 | postgres | f | t | t | t <-- オールテーブ
ルではな
(1 row)
n od e2n o de1作成しPub licatio n プリーションするSu b scription を作成しす。
(node2のサーおいて実施)
=# CREATE SUBSCRIPTION test_slot1 CONNECTION 'host=node1 dbname=testlogicaldb port=5432
user=postgres' PUBLICATION test_slot1;
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
24755 | 24750 | r | 2/912A8A10
(1 row)
以下のコマンドでSub scrip tion が作成さ事を確認します。
PostgreSQL Enterprise Consortium
Page 136 of 285
# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
------------+----------+---------+--------------
test_slot1 | postgres | t | {test_slot1}
(1 row)
2. レプーション状態確認
現在のレプリーシン状態を確認します
作成したPu b lica tion Su b scription が正常にレプリーシンされいるかを
applicatio n _n amestatesyn c_state項目で確認します。(syn c_state時点ではasyn cります。)
(node1のサーおいて実施)
$ psql -x -U postgres -c "SELECT * FROM pg_stat_replication"
-[ RECORD 1 ]----+------------------------------
pid | 1667
usesysid | 10
usename | postgres
application_name | test_slot1
<-- subscription_nameが表示さ
client_addr | 192.168.43.11
client_hostname |
client_port | 35564
backend_start | 2018-01-05 10:39:02.914132+09
backend_xmin |
state | streaming
<-- streaming が表示される
sent_lsn | 2/912A8A10
write_lsn | 2/912A8A10
flush_lsn | 2/912A8A10
replay_lsn | 2/912A8A10
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
<-- async(現時点で非同期)
同期レプリーションの設定
1. マンドラインで設定
マンドラインからレプリケーシンの設定を同期レプリケーションにします
(node1のサーおいて実施)
$ psql -U postgres testlogicaldb
=# ALTER SYSTEM SET synchronous_standby_names = 'test_slot1'; <--
application_nameを指定する
設定ファルで同期レプリーションに変更さ事を確認します
(node1のサーおいて実施)
$ cat /var/lib/pgsql/10/data/postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by ALTER SYSTEM command.
synchronous_standby_names = 'test_slot1'
<-- 同期設定にapplication_nameが設定されいる
PostgreSQL Enterprise Consortium
Page 137 of 285
設定ファルの内容を反映します。
(node1のサーおいて実施)
$ pg_ctl reload
Po stg reSQ L起動時にsyn ch ro n o u s_stan d by_namesパラータが読み込まれている事を確認します
(nodeのサーバにおいてサーバ実施)
$ tail /var/lib/pgsql/10/data/log/postgresql-2018-01-05.log <-- で設定が
読み込まれていること確認
LOG: received SIGHUP, reloading configuration files
LOG: parameter "synchronous_standby_names" changed to "test_slot1"
LOG: standby "test_slot1" is now a synchronous standby with priority 1
現在のレプリーシン状態を確認します
syn c_statesyn cっている事を確認します
(node1のサーおいて実施)
$ psql -x -U postgres -c "SELECT * FROM pg_stat_replication"
-[ RECORD 1 ]----+------------------------------
pid | 1667
usesysid | 10
usename | postgres
application_name | test_slot1
client_addr | 192.168.43.11
client_hostname |
client_port | 35564
backend_start | 2018-01-05 10:39:02.914132+09
backend_xmin |
state | streaming
sent_lsn | 2/912A8A10
write_lsn | 2/912A8A10
flush_lsn | 2/912A8A10
replay_lsn | 2/912A8A10
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync
<-- sync(同期)になる
ロジカルレプリーシン動作確認
1. ーブルにデータを追加
スト用に作成しPu b lication 側のテーブルにレコードをINSERTします。
(node1のサーおいて実施)
$ psql -U postgres testlogicaldb
=# INSERT INTO t1logical VALUES (1,localtimestamp);
=# SELECT * FROM t1logical;
c1_no | c2_date_time
-------+----------------------------
1 | 2018-01-05 11:07:36.590471
(1 row)
Subscrip tio n 側のテーブルにもレコードINSERTてい事を確認します。(プリションされいる事を確認)
PostgreSQL Enterprise Consortium
Page 138 of 285
(node2のサーおいて実施)
=# SELECT * FROM t1logical;
c1_no | c2_date_time
-------+----------------------------
1 | 2018-01-05 11:07:36.590471
(1 row)
2. ーブルのデータを更新
Pu blicatio n 側のーブルのレコードをUPDATEします。
(node1のサーおいて実施)
=# UPDATE t1logical SET c2_date_time = localtimestamp WHERE c1_no = 1;
=# SELECT * FROM t1logical;
c1_no | c2_date_time
-------+----------------------------
1 | 2018-01-05 11:10:14.419084
(1 row)
Subscrip tio n 側のテーブルでもレコードがUPD ATEされいる事を確認します。(レプリケーシンされいる事を確認)
(node2のサーおいて実施)
=# SELECT * FROM t1logical;
c1_no | c2_date_time
-------+----------------------------
1 | 2018-01-05 11:10:14.419084
(1 row)
3. ーブルのデータを削除
Pu blicatio n 側のーブルのレコードをDELETEします
(node1のサーおいて実施)
=# DELETE FROM t1logical WHERE c1_no = 1;
=# SELECT * FROM t1logical;
c1_no | c2_date_time
-------+--------------
(0 rows)
<-- 指定のデータが削除され
Subscrip tio n 側のテーブルでもレコードがDELETEいる事を確認しす。(レプリーションさいる事を確認)
(node2のサーおいて実施)
=# SELECT * FROM t1logical;
c1_no | c2_date_time
-------+--------------
(0 rows)
<-- 指定のデータが削除され
4. ーブルロックを実施し同期レプリケーションを確認
Subscrip tio n 側のデータベース、テーブルのoid を確認します
PostgreSQL Enterprise Consortium
Page 139 of 285
(node2のサーおいて実施)
=# SELECT oid, datname FROM pg_database;
oid | datname
-------+---------------
24748 | testlogicaldb
[省略]
=# SELECT oid, datname FROM pg_database;
relid | relname
-------+-----------------
24750 | t1logical
[省略]
Subscrip tio n 側のロ情報を確認します。
(node2のサーおいて実施)
=# SELECT locktype, database, relation, mode FROM pg_locks;
locktype | database | relation | mode
------------+----------+----------+-----------------
relation | 24748 | 11577 | AccessShareLock <--
ロックさいない
virtualxid | | | ExclusiveLock
(2 rows)
Subscrip tio n 側のテーブルをンザション内でロック状態のままにします。(ロックード : EXCLU SIVE M O DE)
(node2のサーおいて実施)
=# BEGIN;
=# LOCK t1logical IN ACCESS EXCLUSIVE MODE ;
<-- ーブルをロッ
Subscrip tio n 側のロ情報を確認します。
(node2のサーおいて実施)
=# SELECT locktype, database, relation, mode FROM pg_locks;
locktype | database | relation | mode
---------------+----------+----------+---------------------
relation | 24748 | 11577 | AccessShareLock
virtualxid | | | ExclusiveLock
transactionid | | | ExclusiveLock
relation | 24748 | 24750 | AccessExclusiveLock <-- テーブルをロッ
[省略]
Subscrip tio n 側のテーブルがロッ状態のまま、Pu b licatio n のテーブルにレコードINSERTします
Subscrip tio n (スタンバ)からCommitの応答があるまで待機状態となります
(し、60以上応答がない場合は、イムアウトのログが出力されます。)
(node1のサーおいて実施)
=# INSERT INTO t1logical VALUES (1,localtimestamp); <--
セカンダリから commit 応答がないためプロンプが止ま
PostgreSQL Enterprise Consortium
Page 140 of 285
(node1のサーおいて実施)
$ tail /var/lib/pgsql/10/data/log/postgresql-2018-01-05.log
LOG: terminating walsender process due to replication timeout <-- 定値
wal_sender_timeout (default 60s)待ってが出力れる
[Ctrl+c]
Cancel request sent
WARNING: canceling wait for synchronous replication due to user request
DETAIL: The transaction has already committed locally, but might not have been
replicated to the standby.
INSERT 0 1
Subscrip tio n 側のテーブルロックを解除するとレプリーションが動作します。
Subscrip tio n 側のテーブルでもレコードがINSERTされいる事を確認します。
(node2のサーおいて実施)
=# COMMIT; <-- ロック解除
=# SELECT locktype, database, relation, mode FROM pg_locks;
locktype | database | relation | mode
------------+----------+----------+-----------------
relation | 24748 | 11577 | AccessShareLock <--
ロックさいない
virtualxid | | | ExclusiveLock
(2 rows)
=# SELECT * FROM t1logical ;
c1_no | c2_date_time
-------+----------------------------
1 | 2018-01-05 13:44:52.134441
<-- プリーションされている
(1 row)
6.3.3.
6.3.3.1.
ロジカルレプリーションで複数のSu b scrip tion レプーションが可能か確認します
6.3.3.2.
本検証で3ノードで下記構成のレプーションが実現可能かの検証を実施しました
6.3.3.3.
PostgreSQL Enterprise Consortium
Page 141 of 285
6.3.3.4.
ロジカルレプリーシンの動作確認(テーブル単位)
1. 動作確認用のデータベース作成
本検証で利用するータベースを作成します。
(node1,node2,node3のサーバにおいて実)
$ createdb logicalreptest
以下のコマンドでデータベーが作成された事を確認しす。
(node1,node2,node3のサーバにおいて実)
$ psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
----------------+----------+----------+---------+-------+-----------------------
logicalreptest | postgres | UTF8 | C | C |
[省略]
2. 動作確認用のテーブル作成
作成したデーベーステス用のテーブルを作成します。
(node1,node2,node3のサーバにおいて実)
$ psql -U postgres logicalreptest
=# CREATE TABLE t1logical (c1 INT, PRIMARY KEY (c1));
=# CREATE TABLE t2logical (c1 INT, PRIMARY KEY (c1));
=# CREATE TABLE t3logical (c1 INT, PRIMARY KEY (c1));
以下のコマンドで作成したテーブルを確認しす。
PostgreSQL Enterprise Consortium
Page 142 of 285
(node1,node2,node3のサーバにおいて実)
=# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+----------
public | t1logical | table | postgres
public | t2logical | table | postgres
public | t3logical | table | postgres
(3 rows)
3. 1ト目Pu b lication Sub scrip tion
n od e1作成したt1logicalーブルをレプーション対象とするPu b lication を作成します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE PUBLICATION pub_node1_t1logical FOR TABLE t1logical;
以下のコマンドでPu b licatio n が作成され事を確認します。
(node1のサーおいて実施)
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node1_t1logical | postgres | f | t | t | t
(1 row)
n od e2n o de1作成しPub licatio n プリーションするSu b scription を作成しす。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node2_t1logical CONNECTION 'host=node1 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node1_t1logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
(node2のサーおいて実施)
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node2_t1logical | postgres | t | {pub_node1_t1logical}
(1 row)
n od e3n o de1作成しPub licatio n プリーションするSu b scription を作成しす。
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node3_t1logical CONNECTION 'host=node1 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node1_t1logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
PostgreSQL Enterprise Consortium
Page 143 of 285
(node3のサーおいて実施)
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node3_t1logical | postgres | t | {pub_node1_t1logical}
(1 row)
4. 2ト目Pu b lication Sub scrip tion
n od e2作成したt2logicalーブルをレプーション対象とするPu b lication を作成します
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE PUBLICATION pub_node2_t2logical FOR TABLE t2logical;
以下のコマンドでPu b licatio n が作成され事を確認します。
(node2のサーおいて実施)
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node2_t2logical | postgres | f | t | t | t
(1 row)
n od e3n o de2作成しPub licatio n プリーションするSu b scription を作成しす。
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node3_t2logical CONNECTION 'host=node2 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node2_t2logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
(node3のサーおいて実施)
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node3_t1logical | postgres | t | {pub_node1_t1logical}
sub_node3_t2logical | postgres | t | {pub_node2_t2logical}
(2 rows)
n od e1n o de2作成しPub licatio n プリーションするSu b scription を作成しす。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node1_t2logical CONNECTION 'host=node2 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node2_t2logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
PostgreSQL Enterprise Consortium
Page 144 of 285
(node1のサーおいて実施)
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node1_t2logical | postgres | t | {pub_node2_t2logical}
(1 row)
5. 3ト目Pu b lication Sub scrip tion
n od e3作成したt3logicalーブルをレプーション対象とするPu b lication を作成します
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE PUBLICATION pub_node3_t3logical FOR TABLE t3logical;
以下のコマンドでPu b licatio n が作成され事を確認します。
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node3_t3logical | postgres | f | t | t | t
(1 row)
n od e3作成したPu blication とレプリーションするSub scrip tionを作成します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node2_t3logical CONNECTION 'host=node3 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node3_t3logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node2_t1logical | postgres | t | {pub_node1_t1logical}
sub_node2_t3logical | postgres | t | {pub_node3_t3logical}
(2 rows)
n od e3作成したPu blication とレプリーションするSub scrip tionを作成します。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node1_t3logical CONNECTION 'host=node3 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node3_t3logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
PostgreSQL Enterprise Consortium
Page 145 of 285
(node1のサーおいて実施)
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node1_t2logical | postgres | t | {pub_node2_t2logical}
sub_node1_t3logical | postgres | t | {pub_node3_t3logical}
(2 rows)
6. 1ト目 ジカルレプリケーション動作検
n od e1Pu b lication 側のテーブ(t1lo gical)にレコードをINSER Tします。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# INSERT INTO t1logical VALUES (1);
=# INSERT INTO t1logical VALUES (2);
=# SELECT * FROM t1logical;
c1
----
1
2
(2 rows)
n od e2Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(レプーションさてい事を確認)
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t1logical;
c1
----
1 <-- node1と同じ結果がレプーションさてい
2
(2 rows)
n od e3Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(レプーションさてい事を確認)
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t1logical;
c1
----
1 <-- node1と同じ結果がレプーションさてい
2
(2 rows)
7. 2ト目 ジカルレプリケーション動作検
n od e2Pu b lication 側のテーブ(t2lo gical)にレコードをINSER Tします。
PostgreSQL Enterprise Consortium
Page 146 of 285
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# INSERT INTO t2logical VALUES (3);
=# INSERT INTO t2logical VALUES (4);
=# SELECT * FROM t2logical;
c1
----
3
4
(2 rows)
n od e3Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(レプーションさてい事を確認)
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t2logical;
c1
----
3 <-- node2と同じ結果がレプーションさてい
4
(2 rows)
n od e1Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(レプーションさてい事を確認)
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t2logical;
c1
----
3 <-- node2と同じ結果がレプーションさてい
4
(2 rows)
8. 3ト目 ジカルレプリケーション動作検
n od e3Pu b lication 側のテーブ(t3lo gical)にレコードをINSER Tします。
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# INSERT INTO t3logical VALUES (5);
=# INSERT INTO t3logical VALUES (6);
=# SELECT * FROM t3logical;
c1
----
5
6
(2 rows)
n od e2Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(レプーションさてい事を確認)
PostgreSQL Enterprise Consortium
Page 147 of 285
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t3logical;
c1
----
5 <-- node3同じ結果がレプリーションされているこ
6
(2 rows)
n od e1Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(レプーションさてい事を確認)
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t3logical;
c1
----
5 <-- node3と同じ結果がレプーションさてい
6
(2 rows)
動作確認
1. VIEW でのステ
n od e1の各Pu b licatio n /Subscrip tio n の定義確認しす。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
Publication設定したテーブルを確認
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------------------+------------+-----------
pub_node1_t1logical | public | t1logical
(1 row)
レプーションしている状態の確認
=# SELECT pid, application_name, client_addr, state, sync_state FROM
pg_stat_replication;
pid | application_name | client_addr | state | sync_state
------+---------------------+---------------+-----------+------------
1291 | sub_node2_t1logical | node2 | streaming | async
1298 | sub_node3_t1logical | node3 | streaming | async
(2 rows)
Subscriptionの設定情
=# SELECT subslotname, subpublications, subconninfo FROM pg_subscription;
subslotname | subpublications |
subconninfo
---------------------+-----------------------+------------------------------------------
-----------------------------------
sub_node1_t2logical | {pub_node2_t2logical} | host=node2 dbname=logicalreptest
port=5432 user=postgres password=postgres
sub_node1_t3logical | {pub_node3_t3logical} | host=node3 dbname=logicalreptest
port=5432 user=postgres password=postgres
(2 rows)
n od e2の各Pu b licatio n /Subscrip tio n の定義確認しす。
PostgreSQL Enterprise Consortium
Page 148 of 285
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
Publication設定したテーブルを確認
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------------------+------------+-----------
pub_node2_t2logical | public | t2logical
(1 row)
レプーションしている状態の確認
=# SELECT pid, application_name, client_addr, state, sync_state FROM
pg_stat_replication;
pid | application_name | client_addr | state | sync_state
------+---------------------+---------------+-----------+------------
1323 | sub_node1_t2logical | node1 | streaming | async
1344 | sub_node3_t2logical | node3 | streaming | async
(2 rows)
Subscriptionの設定情
=# SELECT subslotname, subpublications, subconninfo FROM pg_subscription;
subslotname | subpublications |
subconninfo
---------------------+-----------------------+------------------------------------------
-----------------------------------
sub_node2_t3logical | {pub_node3_t3logical} | host=node3 dbname=logicalreptest
port=5432 user=postgres password=postgres
sub_node2_t1logical | {pub_node1_t1logical} | host=node1 dbname=logicalreptest
port=5432 user=postgres password=postgres
(2 rows)
n od e3の各Pu b licatio n /Subscrip tio n の定義確認しす。
PostgreSQL Enterprise Consortium
Page 149 of 285
(node3おいて実施)
$ psql -U postgres logicalreptest
Publication設定したテーブルを確認
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------------------+------------+-----------
pub_node3_t3logical | public | t3logical
(1 row)
レプーションしている状態の確認
=# SELECT pid, application_name, client_addr, state, sync_state FROM
pg_stat_replication;
pid | application_name | client_addr | state | sync_state
------+---------------------+---------------+-----------+------------
1346 | sub_node1_t3logical | node1 | streaming | async
1348 | sub_node2_t3logical | node2 | streaming | async
(2 rows)
Subscriptionの設定情
=# SELECT subslotname, subpublications, subconninfo FROM pg_subscription;
subslotname | subpublications |
subconninfo
---------------------+-----------------------+------------------------------------------
----------------------------------
sub_node3_t1logical | {pub_node1_t1logical} | host=node1 dbname=logicalreptest
port=5432 user=postgres password=postgres
sub_node3_t2logical | {pub_node2_t2logical} | host=node2 dbname=logicalreptest
port=5432 user=postgres password=postgres
(2 rows)
6.3.4.
6.3.4.1.
ロジカルレプリーションを利用したカスケード構成の挙動を確認しす。
6.3.4.2.
本検証で、下記構成のレプリーションが実現可能かの検証を実施しました
6.3.4.3.
PostgreSQL Enterprise Consortium
Page 150 of 285
6.3.4.4.
ロジカルレプリーシンの動作確認(テーブル単位)
1. 動作確認用のデータベース作成
本検証で利用するータベースを作成します。
(node1,node2,node3のサーバにおいて実)
$ createdb logicalreptest
以下のコマンドでデータベーが作成された事を確認しす。
(node1,node2,node3のサーバにおいて実)
$ psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
----------------+----------+----------+---------+-------+-----------------------
logicalreptest | postgres | UTF8 | C | C |
[省略]
2. 動作確認用のテーブル作成
作成したデーベーステス用のテーブルを作成します。
(node1,node2,node3のサーバにおいて実)
$ psql -U postgres logicalreptest
=# CREATE TABLE t1logical (c1 INT, PRIMARY KEY (c1));
以下のコマンドで作成したテーブルを確認しす。
(node1,node2,node3のサーバにおいて実)
=# \d
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+----------
public | t1logical | table | postgres
(1 row)
3. Pu blicatio n 作成
n od e1作成したt1logicalーブルをレプーション対象とするPu b lication を作成します
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE PUBLICATION pub_node1_t1logical FOR TABLE t1logical;
以下のコマンドでPu b licatio n が作成され事を確認します。
PostgreSQL Enterprise Consortium
Page 151 of 285
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node1_t1logical | postgres | f | t | t | t
(1 row)
4. Subscrip tio n 作成
n od e2n o de1作成しPub licatio n プリーションするSu b scription を作成しす。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node2_t1logical CONNECTION 'host=node1 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node1_t1logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node2_t1logical | postgres | t | {pub_node1_t1logical}
(1 row)
5. Pu blicatio n 作成
n od e1作成したPu blication とレプリーションする対象とっていたテーブ(t1lo g ical)
新たレプリケーション対象としたPu b lication n o d e2作成します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE PUBLICATION pub_node2_t1logical FOR TABLE t1logical;
以下のコマンドでPu b licatio n が作成され事を確認します。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node2_t1logical | postgres | f | t | t | t
(1 row)
6. Subscrip tio n 作成
n od e3n o de2作成しPub licatio n プリーションするSu b scription を作成しす。
PostgreSQL Enterprise Consortium
Page 152 of 285
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node3_t1logical CONNECTION 'host=node2 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node2_t1logical;
以下のコマンドでSub scrip tion が作成さ事を確認します。
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
---------------------+----------+---------+-----------------------
sub_node3_t1logical | postgres | t | {pub_node2_t1logical}
(1 row)
7. ロジカルレプリーション簡易動作検
n od e1Pu b lication 側のテーブルにレコードをINSERTします。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# INSERT INTO t1logical VALUES (1);
=# INSERT INTO t1logical VALUES (2);
=# SELECT * FROM t1logical;
c1
----
1
2
(2 rows)
8. ロジカルレプリーション簡易動作検証確認
n od e2Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(n od e1からレプリーシンされいる事を確認)
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t1logical;
c1
----
1 <-- node1と同じ結果がレプーションさてい
2
(2 rows)
n od e3Su b scription 側のーブルにレコードがINSER Tてい事を確認します。(n od e2からレプリーシンされいる事を確認)
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# SELECT * FROM t1logical;
c1
----
1 <-- node1と同じ結果がレプーションさてい
2
(2 rows)
動作確認
PostgreSQL Enterprise Consortium
Page 153 of 285
1. VIEW でのステ
n od e1Pu b lication の定義を確認します。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
Publication設定したテーブルを確認
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------------------+------------+-----------
pub_node1_t1logical | public | t1logical
(1 row)
レプーションしている状態の確認
=# SELECT pid, application_name, client_addr, state, sync_state FROM
pg_stat_replication;
pid | application_name | client_addr | state | sync_state
------+---------------------+---------------+-----------+------------
31121| sub_node2_t1logical | node2 | streaming | async
(1 rows)
n od e2Pu blica tion /Su b scrip tion の定義確認しす。
(node2のサーおいて実施)
$ psql -U postgres logicalreptest
Publication設定したテーブルを確認
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------------------+------------+-----------
pub_node2_t1logical | public | t1logical
(1 row)
レプーションしている状態の確認
=# SELECT pid, application_name, client_addr, state, sync_state FROM
pg_stat_replication;
pid | application_name | client_addr | state | sync_state
------+---------------------+---------------+-----------+------------
9185 | sub_node3_t1logical | node3 | streaming | async
(1 rows)
Subscriptionの設定情
=# SELECT subslotname, subpublications, subconninfo FROM pg_subscription;
subslotname | subpublications |
subconninfo
---------------------+-----------------------+------------------------------------------
-----------------------------------
sub_node2_t1logical | {pub_node1_t1logical} | host=node1 dbname=logicalreptest
port=5432 user=postgres password=postgres
(1 rows)
n od e3Su b scription の定義を確認します
PostgreSQL Enterprise Consortium
Page 154 of 285
(node3おいて実施)
$ psql -U postgres logicalreptest
レプーションしている状態の確認
=# SELECT pid, application_name, client_addr, state, sync_state FROM
pg_stat_replication;
(0 rows)
Subscriptionの設定情
=# SELECT subslotname, subpublications, subconninfo FROM pg_subscription;
subslotname | subpublications |
subconninfo
---------------------+-----------------------+------------------------------------------
----------------------------------
sub_node3_t1logical | {pub_node2_t1logical} | host=node2 dbname=logicalreptest
port=5432 user=postgres password=postgres
(1 row)
追加検証(Pu b lication Sub scrip tion 関係をループさせた場合の挙動)
1. Pu blicatio n 作成
n od e2作成したPu blication とレプリーションする対象とっていたテーブ(t1lo g ical)
新たレプリケーション対象としたPu b lication n o d e3作成します。
(node3のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE PUBLICATION pub_node3_t1logical FOR TABLE t1logical;
以下のコマンドでPu b licatio n が作成され事を確認します。
$ psql -U postgres logicalreptest
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
---------------------+----------+------------+---------+---------+---------
pub_node3_t1logical | postgres | f | t | t | t
(1 row)
2. Subscrip tio n 作成
n od e1n o de3作成しPub licatio n プリーションするSu b scription を作成しす。
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# CREATE SUBSCRIPTION sub_node1_t1logical CONNECTION 'host=node3 dbname=logicalreptest
port=5432 user=postgres password=postgres' PUBLICATION pub_node3_t1logical;
3. ロジカルレプリーション簡易動作検(ループ時)
レプーション元とレプリーシン先がループしているため、
初期データのピー時に一意制約違反が発生し、5秒毎にエラーメセージが出力されます
PostgreSQL Enterprise Consortium
Page 155 of 285
(node1のサーおいて実施)
$ psql -U postgres logicalreptest
=# INSERT INTO t1logical VALUES (1);
(PostgreSQLログのエラーメッセージ)
[2018-01-31 17:18:03.060 JST][][][00000][444] LOG: logical replication table
synchronization worker for subscription "sub_node1_t1logical", table "t1logical" has
started
[2018-01-31 17:18:03.072 JST][][][23505][444] ERROR: duplicate key value violates
unique constraint "t1logical_pkey"
[2018-01-31 17:18:03.072 JST][][][23505][444] DETAIL: Key (c1)=(1) already exists.
[2018-01-31 17:18:03.072 JST][][][23505][444] CONTEXT: COPY t1logical, line 1
[2018-01-31 17:18:03.073 JST][][][00000][227] LOG: worker process: logical replication
worker for subscription 16393 sync 16385 (PID 444) exited with exit code 1
6.3.5.
6.3.5.1.
6.3.5.2.
パーティショニングは大規模なテルに対しデータを複数テーブルに分割して格納するで性能や運用性を向上させるができます。
また、ロジカルレプリーシンは理的な変更内容を伝播さレプーションさせるで、複数サーバからデータを複製先のデータース集約させる事ができます。
れらを組み合わせる事で、複数サーバのデータ1の集約サーバ上でパーティションテーブルとして管理る事が可能となります
6.3.5.3.
レプーション対象としたパーティショニングテーブルがSub scrib er反映されることを確認する
Pu blish erと同等の処理がSub scrib erのパーティショニングテーブルに行事を確認する
複数サーの子テーブルを1つのサーのパーティショニングテーブルに統合する構成が組めか確認る。
6.3.5.4.
環境構築
1. レプーション状態の確
現在のレプリーシン状態を確認します
(node1,node2のサーバにおいて実)
$ psql -x -U postgres -c "SELECT * FROM pg_stat_replication;"
(0 rows)
PostgreSQL Enterprise Consortium
Page 156 of 285
2. 試験用データベース作成
本検証で利用するータベースを作成します。
(node1,node2のサーバにおいて実)
$ createdb testlogicalre
以下のコマンドでデータベーが作成された事を確認しす。
(node1,node2のサーバにおいて実)
$ psql -U postgres -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
---------------+----------+----------+---------+-------+-----------------------
testlogicalre | postgres | UTF8 | C | C |
[省略]
3. 試験用テーブル作成(p g ben ch )
作成したデーベースpg b en ch を使用してテスト用のテーブルを作成します
その後に、対象のテーブル(p g ben ch _h isto ry)をパーティション構文を用いてパーティショニングします
(node1,node2のサーバにおいて実)
$ pgbench -i -U postgres testlogicalre
$ psql -U postgres testlogicalre
=# DROP TABLE pgbench_history;
=# CREATE TABLE pgbench_history(tid integer, bid integer, aid integer, delta integer,
mtime timestamp without time zone, filler character(22)) PARTITION BY RANGE (mtime);
=# CREATE TABLE pgbench_history_201801 PARTITION OF pgbench_history FOR VALUES FROM
('2018-01-01') TO ('2018-02-01');
=# CREATE TABLE pgbench_history_201712 PARTITION OF pgbench_history FOR VALUES FROM
('2017-12-01') TO ('2018-01-01');
=# CREATE TABLE pgbench_history_201711 PARTITION OF pgbench_history FOR VALUES FROM
('2017-11-01') TO ('2017-12-01');
=# ALTER TABLE pgbench_history_201801 ADD CONSTRAINT pgbench_history_201801_pkey PRIMARY
KEY(tid, aid);
=# ALTER TABLE pgbench_history_201712 ADD CONSTRAINT pgbench_history_201712_pkey PRIMARY
KEY(tid, aid);
=# ALTER TABLE pgbench_history_201711 ADD CONSTRAINT pgbench_history_201711_pkey PRIMARY
KEY(tid, aid);
=# SELECT relname, n_live_tup AS rowcount FROM pg_stat_all_tables WHERE relname LIKE
'pgbench_history%' ORDER BY relname;
relname | rowcount
------------------------+----------
pgbench_history_201711 | 0
pgbench_history_201712 | 0
pgbench_history_201801 | 0
(3 rows)
4. Pu blicatio n Su b scriptio n を作成
n od e1作成したパーティションの子テーブルをレプリーション対象とするPu b licatio n を作成します
PostgreSQL Enterprise Consortium
Page 157 of 285
(node1のサーおいて実施)
=# CREATE PUBLICATION pub_node1_parttables FOR TABLE pgbench_history_201711;
=# ALTER PUBLICATION pub_node1_parttables ADD TABLE pgbench_history_201712;
=# ALTER PUBLICATION pub_node1_parttables ADD TABLE pgbench_history_201801;
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
----------------------+------------+------------------------
pub_node1_parttables | public | pgbench_history_201801
pub_node1_parttables | public | pgbench_history_201712
pub_node1_parttables | public | pgbench_history_201711
(3 rows)
以下のコマンドでPu b licatio n が作成され事を確認します。
(node1のサーおいて実施)
=# \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes
----------------------+----------+------------+---------+---------+---------
pub_node1_parttables | postgres | f | t | t | t
(1 row)
n od e2n o de1作成しPub licatio n プリーションするSu b scription を作成しす。
(node2のサーバにおいて実)
=# CREATE SUBSCRIPTION sub_node2_parttables CONNECTION 'host=node1 dbname=testlogicalre
port=5432 user=postgres' PUBLICATION pub_node1_parttables;
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
18381 | 18372 | r | 0/109C2570
18381 | 18369 | r | 0/109C2570
18381 | 18366 | r | 0/109C25A8
(3 rows)
以下のコマンドでSub scrip tion が作成さ事を確認します。
(node2のサーおいて実施)
=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
----------------------+----------+---------+------------------------
sub_node2_parttables | postgres | t | {pub_node1_parttables}
(1 row)
ロジカルレプリーシン簡易動作確認
1. ーブルデータ追加
pg b ench で動作さるスリプ作成します
PostgreSQL Enterprise Consortium
Page 158 of 285
(node1のサーおいて実施)
$ vi part_test.sql
-----
\set aid random(1, 90 * :scale)
\set bid random(1, 1 * :scale)
\set tid random(1, 10000 * :scale)
\set delta random(-5000, 5000)
BEGIN;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid,
:delta, CAST('2018-01-31' AS date) - CAST(:aid AS integer));
UPDATE pgbench_history SET filler = to_char(:bid + :delta, '9999') WHERE tid = :tid AND
aid = :aid;
END;
-----
n od e1Pu b lication 側のテーブルに対して、pg b ench でスクプトを実行します
(node1のサーおいて実施)
$ pgbench -U postgres -c 1 -t 1000 -f part_test.sql testlogicalre
レコードがパーティショニングテーブルに振り分けられている事を確認します
(node1のサーおいて実施)
$ psql -U postgres testlogicalre
=# ANALYZE;
=# SELECT relname, n_live_tup AS rowcount FROM pg_stat_all_tables WHERE relname LIKE
'pgbench_history%' ORDER BY relname;
relname | rowcount
------------------------+----------
pgbench_history_201711 | 348
pgbench_history_201712 | 332
pgbench_history_201801 | 320
(3 rows)
Pu blicatio n 側のパーティショニングテーブルのレコード情報確認しす。
PostgreSQL Enterprise Consortium
Page 159 of 285
(node1のサーおいて実施)
=# SELECT * FROM pgbench_history_201711 ORDER BY tid LIMIT 3;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+---------------------+------------------------
27 | 1 | 75 | 2772 | 2017-11-17 00:00:00 | 2773
125 | 1 | 90 | 1513 | 2017-11-02 00:00:00 | 1514
146 | 1 | 81 | -3348 | 2017-11-11 00:00:00 | -3347
(3 rows)
(node1のサーおいて実施)
=# SELECT * FROM pgbench_history_201712 ORDER BY tid LIMIT 3;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+---------------------+------------------------
66 | 1 | 35 | -4563 | 2017-12-27 00:00:00 | -4562
156 | 1 | 55 | 1206 | 2017-12-07 00:00:00 | 1207
231 | 1 | 51 | -894 | 2017-12-11 00:00:00 | -893
(3 rows)
(node1のサーおいて実施)
=# SELECT * FROM pgbench_history_201801 ORDER BY tid LIMIT 3;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+---------------------+------------------------
13 | 1 | 22 | 339 | 2018-01-09 00:00:00 | 340
22 | 1 | 29 | -1540 | 2018-01-02 00:00:00 | -1539
41 | 1 | 13 | -4569 | 2018-01-18 00:00:00 | -4568
(3 rows)
パーティショニングテーブルの予測行数がn o d e1と一致しているか否かを確認します
(node2のサーおいて実施)
$ psql -U postgres testlogicalre
=# ANALYZE;
=# SELECT relname, n_live_tup AS rowcount FROM pg_stat_all_tables WHERE relname LIKE
'pgbench_history%' ORDER BY relname;
relname | rowcount
------------------------+----------
pgbench_history_201711 | 348
pgbench_history_201712 | 332
pgbench_history_201801 | 320
(3 rows)
Subscrip tio n 側のパーティショニンテーブルでn o de1ードが一致している事を確認します。(レプリケーシンされいる事を確認)
PostgreSQL Enterprise Consortium
Page 160 of 285
(node2のサーおいて実施)
=# SELECT * FROM pgbench_history_201711 ORDER BY tid LIMIT 3;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+---------------------+------------------------
27 | 1 | 75 | 2772 | 2017-11-17 00:00:00 | 2773
125 | 1 | 90 | 1513 | 2017-11-02 00:00:00 | 1514
146 | 1 | 81 | -3348 | 2017-11-11 00:00:00 | -3347
(3 rows)
=# SELECT * FROM pgbench_history_201712 ORDER BY tid LIMIT 3;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+---------------------+------------------------
66 | 1 | 35 | -4563 | 2017-12-27 00:00:00 | -4562
156 | 1 | 55 | 1206 | 2017-12-07 00:00:00 | 1207
231 | 1 | 51 | -894 | 2017-12-11 00:00:00 | -893
(3 rows)
=# SELECT * FROM pgbench_history_201801 ORDER BY tid LIMIT 3;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+---------------------+------------------------
13 | 1 | 22 | 339 | 2018-01-09 00:00:00 | 340
22 | 1 | 29 | -1540 | 2018-01-02 00:00:00 | -1539
41 | 1 | 13 | -4569 | 2018-01-18 00:00:00 | -4568
(3 rows)
2. レプーション状態確認
現在のレプリーシン状態を確認します
作成したPu b lica tion Su b scription が正常にレプリーシンされいるかを
applicatio n _n amestatesyn c_state項目で確認します。
(node1のサーおいて実施)
$ psql -x -U postgres -c "SELECT * FROM pg_stat_replication;"
-[ RECORD 1 ]----+------------------------------
pid | 1446
usesysid | 10
usename | postgres
application_name | sub_node2_parttables <-- subscriptionの名前が表示さ
client_addr | 192.168.56.102
client_hostname |
client_port | 52428
backend_start | 2018-02-05 10:21:33.710471+09
backend_xmin |
state | streaming <-- streaming が表示される
sent_lsn | 0/10A29160
write_lsn | 0/10A29160
flush_lsn | 0/10A29160
replay_lsn | 0/10A29160
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async <-- async(非同期)
ーブル追加
1. ーブル作成
新たパーティショニングテーブルを作成します。
PostgreSQL Enterprise Consortium
Page 161 of 285
(node1,node2のサーバにおいて実)
$ psql -U postgres testlogicalre
=# CREATE TABLE pgbench_history_201802 PARTITION OF pgbench_history FOR VALUES FROM
('2018-02-01') TO ('2018-03-01');
=# ALTER TABLE pgbench_history_201802 ADD CONSTRAINT pgbench_history_201802_pkey PRIMARY
KEY(tid, aid);
以下のコマンドで作成したテーブルを確認しす。
=# \dt
List of relations
Schema | Name | Type | Owner
--------+------------------------+-------+----------
public | pgbench_accounts | table | postgres
public | pgbench_branches | table | postgres
public | pgbench_history | table | postgres
public | pgbench_history_201711 | table | postgres
public | pgbench_history_201712 | table | postgres
public | pgbench_history_201801 | table | postgres
public | pgbench_history_201802 | table | postgres
public | pgbench_tellers | table | postgres
(8 rows)
2. 既存のロジカルレプリケーションにテーブルを追加
作成したパーティショニングテーブルを既存のPu b lication 追加します。
(node1のサーおいて実施)
$ psql -U postgres testlogicalre
=# ALTER PUBLICATION pub_node1_parttables ADD TABLE pgbench_history_201802;
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
----------------------+------------+------------------------
pub_node1_parttables | public | pgbench_history_201801
pub_node1_parttables | public | pgbench_history_201712
pub_node1_parttables | public | pgbench_history_201711
pub_node1_parttables | public | pgbench_history_201802
(4 rows)
更新したPu b lica tion の情報をSub scrip tion 反映させます
PostgreSQL Enterprise Consortium
Page 162 of 285
(node2のサーおいて実施)
$ psql -U postgres testlogicalre
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
18381 | 18372 | r | 0/109C2570
18381 | 18369 | r | 0/109C2570
18381 | 18366 | r | 0/109C25A8
(3 rows)
=# ALTER SUBSCRIPTION sub_node2_parttables REFRESH PUBLICATION;
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
18381 | 18382 | r | 0/10A3EB98
18381 | 18372 | r | 0/109C2570
18381 | 18369 | r | 0/109C2570
18381 | 18366 | r | 0/109C25A8
(4 rows)
ロジカルレプリーシン動作確認
1. 新規テーブルにデータ追
新た作成したPu b licatio n 側のパーティショニングーブルにレコードINSERTします
(node1のサーおいて実施)
$ psql -U postgres testlogicalre
=# SELECT * FROM pgbench_history_201802;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+-------+--------
(0 rows)
=# INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (7777, 1, 12, 4321,
'2018-02-11 00:00:00');
=# SELECT * FROM pgbench_history_201802;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
7777 | 1 | 12 | 4321 | 2018-02-11 00:00:00 |
(1 row)
Subscrip tio n 側のパーティショニンテーブルにもレードがINSERTされいる事を確認します(レプリーションさてい事を確認)
(node2のサーおいて実施)
$ psql -U postgres testlogicalre
=# SELECT * FROM pgbench_history_201802;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
7777 | 1 | 12 | 4321 | 2018-02-11 00:00:00 |
(1 row)
子テーブルの取り外し/取り付け
1. パーティションからーブルを取り外し
n od e1パーティショニングテーブルの取り外しとPub licatio n らの削除を行います
PostgreSQL Enterprise Consortium
Page 163 of 285
(node1のサーおいて実施)
$ psql -U postgres testlogicalre
=# SELECT * FROM pgbench_history WHERE tid = 7777;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
7777 | 1 | 24 | 4321 | 2018-02-11 00:00:00 |
(1 row)
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
----------------------+------------+------------------------
pub_node1_parttables | public | pgbench_history_201801
pub_node1_parttables | public | pgbench_history_201712
pub_node1_parttables | public | pgbench_history_201711
pub_node1_parttables | public | pgbench_history_201802
(4 rows)
=# ALTER TABLE pgbench_history DETACH PARTITION pgbench_history_201802;
=# ALTER PUBLICATION pub_node1_parttables DROP TABLE pgbench_history_201802;
=# SELECT * FROM pgbench_history WHERE tid = 7777;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+-------+--------
(0 rows)
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
----------------------+------------+------------------------
pub_node1_parttables | public | pgbench_history_201801
pub_node1_parttables | public | pgbench_history_201712
pub_node1_parttables | public | pgbench_history_201711
(3 rows)
n od e2パーティショニングテーブルの取り外しと更新したPu b licatio n の情報のSub scrip tion の反映を行います
PostgreSQL Enterprise Consortium
Page 164 of 285
(node2のサーおいて実施)
$ psql -U postgres testlogicalre
=# SELECT * FROM pgbench_history WHERE tid = 7777;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
7777 | 1 | 24 | 4321 | 2018-02-11 00:00:00 |
(1 row)
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
18381 | 18382 | r | 0/10A3EB98
18381 | 18372 | r | 0/109C2570
18381 | 18369 | r | 0/109C2570
18381 | 18366 | r | 0/109C25A8
(4 rows)
=# ALTER TABLE pgbench_history DETACH PARTITION pgbench_history_201802;
=# ALTER SUBSCRIPTION sub_node2_parttables REFRESH PUBLICATION;
=# SELECT * FROM pgbench_history WHERE tid = 7777;
tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+-------+--------
(0 rows)
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
18381 | 18372 | r | 0/109C2570
18381 | 18369 | r | 0/109C2570
18381 | 18366 | r | 0/109C25A8
(3 rows)
2. パーティションにテーブルを取り付け
n od e1パーティショニングテーブルの取り付けとPublicatio n への追加を行います
(node1のサーおいて実施)
$ psql -U postgres testlogicalre
=# TRUNCATE TABLE pgbench_history_201802;
=# ALTER TABLE pgbench_history ATTACH PARTITION pgbench_history_201802 FOR VALUES FROM
('2018-02-01') TO ('2018-03-01');
=# ALTER PUBLICATION pub_node1_parttables ADD TABLE pgbench_history_201802;
=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
----------------------+------------+------------------------
pub_node1_parttables | public | pgbench_history_201801
pub_node1_parttables | public | pgbench_history_201712
pub_node1_parttables | public | pgbench_history_201711
pub_node1_parttables | public | pgbench_history_201802
(4 rows)
n od e2パーティショニングテーブルの取り付けと更新したPu blicatio n の情報のSub scrip tion の反映を行います
PostgreSQL Enterprise Consortium
Page 165 of 285
(node2のサーおいて実施)
$ psql -U postgres testlogicalre
=# TRUNCATE TABLE pgbench_history_201802;
=# ALTER TABLE pgbench_history ATTACH PARTITION pgbench_history_201802 FOR VALUES FROM
('2018-02-01') TO ('2018-03-01');
=# ALTER SUBSCRIPTION sub_node2_parttables REFRESH PUBLICATION;
=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
18381 | 18382 | r | 0/10A523F8
18381 | 18372 | r | 0/109C2570
18381 | 18369 | r | 0/109C2570
18381 | 18366 | r | 0/109C25A8
(4 rows)
子テーブルをレプリケーションし、パーティショニングを構成
1. 試験用データベース作成
本検証で利用するータベースを作成します。
(node1のサーおいて実施)
$ createdb testlogicalre2
(node2のサーおいて実施)
$ createdb testlogicalre2_c1
$ createdb testlogicalre2_c2
$ createdb testlogicalre2_c3
以下のコマンドでデータベーが作成された事を確認しす。
PostgreSQL Enterprise Consortium
Page 166 of 285
(node1のサーおいて実施)
$ psql -U postgres -p 5432 -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
----------------+----------+----------+---------+-------+-----------------------
testlogicalre2 | postgres | UTF8 | C | C |
[省略]
(node2のサーおいて実施)
$ psql -U postgres -p 5432 -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-------------------+----------+----------+---------+-------+-----------------------
testlogicalre2_c1 | postgres | UTF8 | C | C |
testlogicalre2_c2 | postgres | UTF8 | C | C |
testlogicalre2_c3 | postgres | UTF8 | C | C |
[省略]
2. 試験用テーブル作成(p g ben ch )
n od e1作成したデータベーpg b ench を使用してテス用のテーブルを作成しす。
その後に、対象のテーブル(p g ben ch _h isto ry)をパーティション構文を用いてパーティショニングします
(node1のサーおいて実施)
$ pgbench -i -U postgres testlogicalre2
$ psql -U postgres testlogicalre2
=# DROP TABLE pgbench_history;
=# CREATE TABLE pgbench_history(tid integer, bid integer, aid integer, delta integer,
mtime timestamp without time zone, filler character(22)) PARTITION BY RANGE (mtime);
=# CREATE TABLE pgbench_history_201711 PARTITION OF pgbench_history FOR VALUES FROM
('2017-11-01') TO ('2017-12-01');
=# CREATE TABLE pgbench_history_201712 PARTITION OF pgbench_history FOR VALUES FROM
('2017-12-01') TO ('2018-01-01');
=# CREATE TABLE pgbench_history_201801 PARTITION OF pgbench_history FOR VALUES FROM
('2018-01-01') TO ('2018-02-01');
=# ALTER TABLE pgbench_history_201711 ADD CONSTRAINT pgbench_history_201711_pkey PRIMARY
KEY(tid, aid);
=# ALTER TABLE pgbench_history_201712 ADD CONSTRAINT pgbench_history_201712_pkey PRIMARY
KEY(tid, aid);
=# ALTER TABLE pgbench_history_201801 ADD CONSTRAINT pgbench_history_201801_pkey PRIMARY
KEY(tid, aid);
=# SELECT relname, n_live_tup AS rowcount FROM pg_stat_all_tables WHERE relname LIKE
'pgbench_history%' ORDER BY relname;
relname | rowcount
------------------------+----------
pgbench_history_201711 | 0
pgbench_history_201712 | 0
pgbench_history_201801 | 0
(3 rows)
n od e2作成した各データベーステーブルを作成します。
PostgreSQL Enterprise Consortium
Page 167 of 285
(node2のサーおいて実施)
$ psql -U postgres -p 5432 testlogicalre2_c1
=# CREATE TABLE pgbench_history_201711(tid integer, bid integer, aid integer, delta
integer, mtime timestamp without time zone, filler character(22));
=# ALTER TABLE pgbench_history_201711 ADD CONSTRAINT pgbench_history_201711_pkey PRIMARY
KEY(tid, aid);
$ psql -U postgres -p 5432 testlogicalre2_c2
=# CREATE TABLE pgbench_history_201712(tid integer, bid integer, aid integer, delta
integer, mtime timestamp without time zone, filler character(22));
=# ALTER TABLE pgbench_history_201712 ADD CONSTRAINT pgbench_history_201712_pkey PRIMARY
KEY(tid, aid);
$ psql -U postgres -p 5432 testlogicalre2_c3
=# CREATE TABLE pgbench_history_201801(tid integer, bid integer, aid integer, delta
integer, mtime timestamp without time zone, filler character(22));
=# ALTER TABLE pgbench_history_201801 ADD CONSTRAINT pgbench_history_201801_pkey PRIMARY
KEY(tid, aid);
3. Pu blicatio n Su b scriptio n を作成
n od e2各データベースに作成したテーブルをレプリケーション対象とするPu b licatio n をそれぞ作成します
(node2のサーおいて実施)
$ psql -U postgres -p 5432 testlogicalre2_c1
=# CREATE PUBLICATION pub_node2_parttables1 FOR TABLE pgbench_history_201711;
$ psql -U postgres -p 5432 testlogicalre2_c2
=# CREATE PUBLICATION pub_node2_parttables2 FOR TABLE pgbench_history_201712;
$ psql -U postgres -p 5432 testlogicalre2_c3
=# CREATE PUBLICATION pub_node2_parttables3 FOR TABLE pgbench_history_201801;
n od e1n o de2作成しPub licatio n プリーションするSu b scription を作成しす。
(node1のサーおいて実施)
$ psql -U postgres -p 5432 testlogicalre2
=# CREATE SUBSCRIPTION sub_node1_parttables1 CONNECTION 'host=node2
dbname=testlogicalre2_c1 port=5432 user=postgres' PUBLICATION pub_node2_parttables1;
=# CREATE SUBSCRIPTION sub_node1_parttables2 CONNECTION 'host=node2
dbname=testlogicalre2_c2 port=5432 user=postgres' PUBLICATION pub_node2_parttables2;
=# CREATE SUBSCRIPTION sub_node1_parttables3 CONNECTION 'host=node2
dbname=testlogicalre2_c3 port=5432 user=postgres' PUBLICATION pub_node2_parttables3;
4. ロジカルレプリーション簡易動作確
n od e2各データベースのPu blicatio n 側のーブルにレコードをINSERTします
PostgreSQL Enterprise Consortium
Page 168 of 285
(node2のサーおいて実施)
$ psql -U postgres -p 5432 testlogicalre2_c1
=# INSERT INTO pgbench_history_201711 (tid, bid, aid, delta, mtime) VALUES (1111, 1, 12,
4321, '2017-11-11 00:00:00');
=# SELECT * FROM pgbench_history_201711;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
1111 | 1 | 12 | 4321 | 2017-11-11 00:00:00 |
(1 row)
$ psql -U postgres -p 5432 testlogicalre2_c2
=# INSERT INTO pgbench_history_201712 (tid, bid, aid, delta, mtime) VALUES (2222, 2, 34,
8765, '2017-12-11 00:00:00');
=# SELECT * FROM pgbench_history_201712;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
2222 | 2 | 34 | 8765 | 2017-12-11 00:00:00 |
(1 row)
$ psql -U postgres -p 5432 testlogicalre2_c3
=# INSERT INTO pgbench_history_201801 (tid, bid, aid, delta, mtime) VALUES (3333, 3, 56,
2109, '2018-01-11 00:00:00');
=# SELECT * FROM pgbench_history_201801;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
3333 | 3 | 56 | 2109 | 2018-01-11 00:00:00 |
(1 row)
Subscrip tio n 側のテーブルにもレコードINSERTてい事を確認します。(プリションされいる事を確認)
(node1のサーおいて実施)
$ psql -U postgres -p 5432 testlogicalre2
=# SELECT * FROM pgbench_history;
tid | bid | aid | delta | mtime | filler
------+-----+-----+-------+---------------------+--------
3333 | 3 | 56 | 2109 | 2018-01-11 00:00:00 |
2222 | 2 | 34 | 8765 | 2017-12-11 00:00:00 |
1111 | 1 | 12 | 4321 | 2017-11-11 00:00:00 |
(3 rows)
6.4. ジカルレリケーショの運
6.4.1.
ロジカルレプリーションが稼働する境を監視する際に利用する報について説明します
6.4.1.1.
本章は以下の環境を利用した検証結果を元に解説します。なお、スリーミングレプリーションと共用する(動的統計情報ビュー pg _stat_replication )もある
め、それぞれの表示形式の違いが比較できるようロジカルレプリーシンとストリーミングレプリーシンを両方利用る環境を利用します
PostgreSQL Enterprise Consortium
Page 169 of 285
Po stg reSQ Lサーバは3構成
ロジカルレプリーションはPu b lish er1台(ーバ1IPアドレス 19216812731Sub scrib er1サーバ2IPアドレス 19216812732で構成
ーミングレプーションは、マスタ1台(Pu b lish erと同一)スタンバ1台(サーバ3IPアドレス 19216812733で構
ロジカルレプリーションのPu blish erでは、データベー内に2のデータベースを作成
pu b d b: レプリーシン対象のテーブルを個別定義するPu b licatio n を作成
pu b d b_all_tab le: デーベース内に存在する全テーブルをレプリケーション対象とするPu b lication を作成
ロジカルレプリーションのSubscrib erでは、データベースクラスタ内2のデータベースを作成
sub d b: Pu b lish erpu b d b デーベースに定義しPub licatio n から更データを受け取るSu b scrip tion を作成
sub d b_all_table: Pu b lish erpu b d b_all_tab leデータース定義したPu b lication から変更デー受け取Sub scrip tionを作成
6.4.1.2.
6.4.1.2.1. Publisher
Pu blish erのサーおいてPu b lica tion が作成さデータベースに接続して確認できる情報は以下のとおりです。
pg_pu blication [1]
接続中のデータベースに定義れているPu b lica tion の情報を確認でます Pu b lica tion の名前、所有者に加えて、レプーションが行われる更新処理の種別がわ
かります。 またFO R ALL TAB LES句を指定して作成したPu b licatio n pu balltables = t となります
(サーバ1において実施)
pubdb=# select oid, * from pg_publication;
oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete
-------+---------+----------+--------------+-----------+-----------+-----------
16392 | pub1 | 16386 | f | t | t | t
16399 | pub2 | 16386 | f | t | t | t
16471 | pub3 | 10 | f | t | t | t
pubdb_all_table=# select oid, * from pg_publication;
oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete
-------+---------------+----------+--------------+-----------+-----------+-----------
16475 | pub_all_table | 10 | t | t | t | t
[1] PostgreSQ L 10.0文書 - 51.40. p g _pu b lication
pg_pu blication_rel [2]
接続中のデータベースに定義れているPu b lica tion がレプーション対象とるテルを確認できます
PostgreSQL Enterprise Consortium
Page 170 of 285
(サーバ1において実施)
pubdb=# select * from pg_publication_rel;
prpubid | prrelid
---------+---------
16392 | 16387
16399 | 16394
16471 | 16465
16392 | 16496
pubdb_all_table=# select * from pg_publication_rel;
prpubid | prrelid
---------+---------
し、Pu b lication 、テブルのO IDしか保有しないため、実際に利用する pg _p u b lication , pg_class と結合して、 それぞれの名称を取得する必要があるでしょ
。まF O R ALL TAB LES指定して作成したPu blica tion では レプリーション対象とっているテーブルが表示されません。
[2] PostgreSQ L 10.0文書 - 51.41. p g _pu b lication _rel
pg_pu blication_tables [3]
接続中のデータベースに定義れているPu b lica tion がレプーション対象とるテルを確認できます
(サーバ1において実施)
pubdb=# select * from pg_publication_tables;
pubname | schemaname | tablename
---------+------------+-----------
pub1 | public | data1
pub1 | public | data1_1
pub2 | public | data2
pub3 | public | data3
pubdb_all_table=# select * from pg_publication_tables;
pubname | schemaname | tablename
---------------+------------+-----------
pub_all_table | public | data1
pub_all_table | public | data2
前述のp g_pu b licatio n _relと比較してPu b lication 、テーブルの名前が直接確認できること、 FO R ALL TAB LES指定して作成したPu blicatio n でもレプ
ション対象のテーブルが確認できるから 際の運用ではこを活用するいでしう。
[3] PostgreSQ L 10.0文書 - 51.78. p g _pu b lication _tables
psql
psqlマンドのメタコマンド「dR p + Pu blicatio n の情報を確認できます。
PostgreSQL Enterprise Consortium
Page 171 of 285
(サーバ1において実施)
pubdb=# \dRp+
Publication pub1
Owner | All tables | Inserts | Updates | Deletes
---------+------------+---------+---------+---------
pubusr1 | f | t | t | t
Tables:
"public.data1"
"public.data1_1"
Publication pub2
Owner | All tables | Inserts | Updates | Deletes
---------+------------+---------+---------+---------
pubusr1 | f | t | t | t
Tables:
"public.data2"
Publication pub3
Owner | All tables | Inserts | Updates | Deletes
----------+------------+---------+---------+---------
postgres | f | t | t | t
Tables:
"public.data3"
pubdb_all_table=# \dRp+
Publication pub_all_table
Owner | All tables | Inserts | Updates | Deletes
----------+------------+---------+---------+---------
postgres | t | t | t | t
システムカログpg_pu b lication , p g _pu blica tion _relの情報がまとめて表示さますが、 F O R ALL TAB LES句を指定して作成したPu blication のテーブルは表示さ
れません。
pg_replication_slots [4]
Pu blish er自動作成されるロジカルレプリケーシンスロットの情報を確認できます。
(サーバ1において実施)
pubdb=# select * from pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid
| xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
---------------+----------+-----------+--------+-----------------+-----------+--------+------------
+------+--------------+-------------+---------------------
sub3 | pgoutput | logical | 16384 | pubdb | f | t | 31511
| | 684 | 0/56083970 | 0/560839A8
sub2 | pgoutput | logical | 16384 | pubdb | f | t | 31509
| | 684 | 0/56083970 | 0/560839A8
sub1 | pgoutput | logical | 16384 | pubdb | f | t | 32366
| | 684 | 0/56083970 | 0/560839A8
sub_all_table | pgoutput | logical | 16474 | pubdb_all_table | f | t | 31512
| | 684 | 0/56083970 | 0/560839A8
Pu blicatio n の情報は接続するデータベースに存在するもしか見えませんが、レプリーシンストはデータベースクラスタ内に存在するのが全て表示さます なお、
slot_type はロジカルレプリーシンストで log ical 、ストリーミングレプリションストは p h ysical と表示されます。
[4] PostgreSQ L 10.0文書 - 51.80. p g _replication _slots
6.4.1.2.2. Subscriber
Subscrib erのサーバにおいてSu bscrip tion が作成さデータベースに接続して確認できる情報は以下のとおりです。
pg_subscription [5]
データベースに存在するSu bscrip tion の情報を確認できます。 Sub scriptionの名前、所有者に加え接続先のデータベース、Pu b licatio n 名前等がわかります
お、pg _p u b lication では接続したデータベース内のPu b licatio n みが見えましたが、p g _su b scriptionでは接続したデータベース関わらず、 全て
Subscrip tio n が表示さます
PostgreSQL Enterprise Consortium
Page 172 of 285
(サーバ2において実施)
subdb=# select * from pg_subscription;
subdbid | subname | subowner | subenabled | subconninfo
| subslotname | subsynccommit | subpublications
---------+---------------+----------+------------+-------------------------------------------------
-------------------------+---------------+---------------+-----------------
16384 | sub2 | 10 | t | host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1 | sub2 | off | {pub2}
16384 | sub3 | 10 | t | host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1 | sub3 | off | {pub3}
16477 | sub_all_table | 10 | t | host=192.168.127.31 dbname=pubdb_all_table
user=repusr1 password=repusr1 | sub_all_table | off | {pub_all_table}
16384 | sub1 | 10 | t | host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1 | sub1 | off | {pub1}
[5] PostgreSQ L 10.0文書 - 51.52. p g _su b scriptio n
pg_subscription_rel [6]
接続中のデータベースに定義れているSu b scrip tion がレプリーシン対象とするテーブルを確認でます また、対象テーブルの他に、レプリーシンのステータ(i =
in itialize, d = d ata is b ein g cop ied , s = syn ch ro n ized , r = read y (n o rma l replication ))LSNが表示されます
(サーバ2において実施)
subdb=# select * from pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
16463 | 16455 | r | 0/55FB63D0
16400 | 16395 | r | 0/16D7B60
16476 | 16470 | r | 0/55FDE4A0
16463 | 16490 | r | 0/56068D38
subdb_all_table=# select * from pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+------------
16484 | 16479 | r | 0/5602B818
16484 | 16485 | r | 0/56048B00
し、Su bscrip tio n 、テーブルのO IDしか保有しないため実際に利用るには p g_su b scrip tion , p g _class と結合して、それぞれの名称を取得する要がある
しょ
[6] PostgreSQ L 10.0文書 - 51.53. p g _su b scriptio n _rel
psql
psqlマンドのメタコマンド「dR s+でもSu b scrip tion の情報確認でます システムカタpg _sub scrip tion 同様の情報が見やすく整形されて表示されます
PostgreSQL Enterprise Consortium
Page 173 of 285
(サーバ2において実施)
subdb=# \dRs+
List of subscriptions
Name | Owner | Enabled | Publication | Synchronous commit | Conninfo
------+----------+---------+-------------+--------------------+------------------------------------
----------------------------
sub1 | postgres | t | {pub1} | off | host=192.168.127.31 dbname=pubdb
user=repusr1 password=repusr1
sub2 | postgres | t | {pub2} | off | host=192.168.127.31 dbname=pubdb
user=repusr1 password=repusr1
sub3 | postgres | t | {pub3} | off | host=192.168.127.31 dbname=pubdb
user=repusr1 password=repusr1
subdb_all_table=# \dRs+
List of subscriptions
Name | Owner | Enabled | Publication | Synchronous commit |
Conninfo
---------------+----------+---------+-----------------+--------------------+-----------------------
---------------------------------------------------
sub_all_table | postgres | t | {pub_all_table} | off | host=192.168.127.31
dbname=pubdb_all_table user=repusr1 password=repusr1
お、pg _sub scrip tion データベースク内のSUB SCRIPTIO Nが全て表示されたのに対しマンド「d R s+では接続中のデータベー内のSub scriptio n
しか表示されません。
6.4.1.3.
6.4.1.3.1. Publisher
Pu blish erのサーおいて確認でる情報は以下のとおりです。
CREATE PU B LICATIO N文を実行した時点でPu b lish erのサーログには何も表示されません。 Su bscrib erCREATE SU B SCRIPTIO N文を実行した時点で以下
のログが出力されます。
(サーバ1のサーバログ)
2018-02-06 11:24:40.990 JST [20086] LOG: starting logical decoding for slot "sub_all_table"
2018-02-06 11:24:40.990 JST [20086] DETAIL: streaming transactions committing after 0/56084A90,
reading WAL from 0/56084A58
pg_stat_replication [7]
ーミングレプーションと同様に、ロジカルプリーションの稼働状況確認でます 接続中のデータベーず、データベースクラスタ全体の情報が表示さ
れます。
(サーバ1において実施)
postgres=# \x
postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 20086
usesysid | 16385
usename | repusr1
application_name | sub_all_table
client_addr | 192.168.127.32
client_hostname |
client_port | 46452
backend_start | 2018-02-06 11:24:40.988512+09
backend_xmin |
state | streaming
sent_lsn | 0/58000140
write_lsn | 0/58000140
flush_lsn | 0/58000140
replay_lsn | 0/58000140
write_lag |
flush_lag |
PostgreSQL Enterprise Consortium
Page 174 of 285
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 2 ]----+------------------------------
pid | 31511
usesysid | 16385
usename | repusr1
application_name | sub3
client_addr | 192.168.127.32
client_hostname |
client_port | 46353
backend_start | 2018-01-17 11:07:07.204636+09
backend_xmin |
state | streaming
sent_lsn | 0/58000140
write_lsn | 0/58000140
flush_lsn | 0/58000140
replay_lsn | 0/58000140
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 3 ]----+------------------------------
pid | 32366
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 46411
backend_start | 2018-01-17 15:01:47.434102+09
backend_xmin |
state | streaming
sent_lsn | 0/58000140
write_lsn | 0/58000140
flush_lsn | 0/58000140
replay_lsn | 0/58000140
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 4 ]----+------------------------------
pid | 31509
usesysid | 16385
usename | repusr1
application_name | sub2
client_addr | 192.168.127.32
client_hostname |
client_port | 46351
backend_start | 2018-01-17 11:07:07.188398+09
backend_xmin |
state | streaming
sent_lsn | 0/58000140
write_lsn | 0/58000140
flush_lsn | 0/58000140
replay_lsn | 0/58000140
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 5 ]----+------------------------------
pid | 21625
usesysid | 16385
usename | repusr1
PostgreSQL Enterprise Consortium
Page 175 of 285
application_name | nk_PGECons3
client_addr | 192.168.127.33
client_hostname |
client_port | 55519
backend_start | 2018-02-06 16:00:40.749454+09
backend_xmin |
state | streaming
sent_lsn | 0/58000140
write_lsn | 0/58000140
flush_lsn | 0/58000140
replay_lsn | 0/58000140
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
では RECO R D 14 でサーバ1-2間のロジカルレプリーション、RECO R D 5 サーバ1-3間のスーミングレプーションの情報が表示されいます。ジカルレプ
ーションとストリーミングレプリケーシンはほぼ同じ形式で見えますが、app licatio n _nameそれぞ以下の情報が表示れています。
ロジカルレプリーション:Su b scription 名前
ーミングレプーション: レーブのreco very.con fに記載したapplicatio n _n ame
お、Su b scrip tion を停止させるp g _stat_rep licatio n ら該当するレプリージョンの情報が表示れなくります
(サーバ2において実施)
subdb=# ALTER SUBSCRIPTION sub1 DISABLE;
ALTER SUBSCRIPTION
pubdb=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 20086
usesysid | 16385
usename | repusr1
application_name | sub_all_table
client_addr | 192.168.127.32
client_hostname |
client_port | 46452
backend_start | 2018-02-06 11:24:40.988512+09
backend_xmin |
state | streaming
sent_lsn | 0/580074E0
write_lsn | 0/580074E0
flush_lsn | 0/580074E0
replay_lsn | 0/580074E0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 2 ]----+------------------------------
pid | 31511
usesysid | 16385
usename | repusr1
application_name | sub3
client_addr | 192.168.127.32
client_hostname |
client_port | 46353
backend_start | 2018-01-17 11:07:07.204636+09
backend_xmin |
state | streaming
sent_lsn | 0/580074E0
write_lsn | 0/580074E0
flush_lsn | 0/580074E0
replay_lsn | 0/580074E0
write_lag |
flush_lag |
replay_lag |
PostgreSQL Enterprise Consortium
Page 176 of 285
sync_priority | 0
sync_state | async
-[ RECORD 3 ]----+------------------------------
pid | 31509
usesysid | 16385
usename | repusr1
application_name | sub2
client_addr | 192.168.127.32
client_hostname |
client_port | 46351
backend_start | 2018-01-17 11:07:07.188398+09
backend_xmin |
state | streaming
sent_lsn | 0/580074E0
write_lsn | 0/580074E0
flush_lsn | 0/580074E0
replay_lsn | 0/580074E0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 4 ]----+------------------------------
pid | 21625
usesysid | 16385
usename | repusr1
application_name | nk_PGECons3
client_addr | 192.168.127.33
client_hostname |
client_port | 55519
backend_start | 2018-02-06 16:00:40.749454+09
backend_xmin |
state | streaming
sent_lsn | 0/580074E0
write_lsn | 0/580074E0
flush_lsn | 0/580074E0
replay_lsn | 0/580074E0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
ロジカルレプリーションもストリーミングレプリケーションも、p g _stat_rep lication の件数を定期的に確認ることで稼働状況監視するとよいでしう。
[7] PostgreSQ L 10.0文書 - 28.5 p g _stat_rep lication ュー
6.4.1.3.2. Subscriber
Subscrib erのサーバにおいて確認できる情報は以下のとおりです。
CREATE SUB SCR IPTIO N文を実行し時点で以下のログが出力さます
(サーバ2のサーバログ)
2018-02-06 11:20:29.883 JST [4245] LOG: logical replication apply worker for subscription
"sub_all_table" has started
2018-02-06 11:20:29.888 JST [4246] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data1" has started
2018-02-06 11:20:29.899 JST [4247] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data2" has started
2018-02-06 11:20:29.901 JST [4246] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data1" has finished
2018-02-06 11:20:29.912 JST [4247] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data2" has finished
PostgreSQL Enterprise Consortium
Page 177 of 285
lo g ical replica tion table syn ch ro n ization w ork er for sub scrip tion (Sub scrip tion ), tab le (テーブル名) h as fin ish ed 出力されていれば、レプ
ション対象のテーブルに対する初期データの転送が完了しており正常にロジカルレプリケーションが開始したこが確認できます。
pg_stat_subscription [8]
Subscrip tio n 単位にロジカルレプーションの稼働状況を確認できます。 接続中のデータベースに関わら、データベースクラスタ全体の情報が表示されます
(サーバ2において実施)
subdb_all_table=# select * from pg_stat_subscription;
subid | subname | pid | relid | received_lsn | last_msg_send_time |
last_msg_receipt_time | latest_end_lsn | latest_end_time
-------+---------------+-------+-------+--------------+-------------------------------+------------
-------------------+----------------+-------------------------------
16400 | sub2 | 31707 | | 0/58000140 | 2018-02-06 16:00:07.649126+09 | 2018-02-06
16:00:07.482495+09 | 0/58000140 | 2018-02-06 16:00:07.649126+09
16476 | sub3 | 31709 | | 0/58000140 | 2018-02-06 16:00:07.649515+09 | 2018-02-06
16:00:07.482694+09 | 0/58000140 | 2018-02-06 16:00:07.649515+09
16463 | sub1 | 32626 | | 0/58000140 | 2018-02-06 16:00:07.649203+09 | 2018-02-06
16:00:07.482386+09 | 0/58000140 | 2018-02-06 16:00:07.649203+09
16508 | sub_all_table | 4267 | | 0/58000140 | 2018-02-06 16:00:07.649259+09 | 2018-02-06
16:00:07.482608+09 | 0/58000140 | 2018-02-06 16:00:07.649259+09
[8] PostgreSQ L 10.0文書 - 28.7 p g _stat_su b scrip tion View
6.4.2.
ロジカルレプリーションが稼働する境で障害が発生した場合の挙動を確認しす。
6.4.2.1.
本章は以下の環境を利用した検証結果を元に解説します。
PostgreSQL Enterprise Consortium
Page 178 of 285
ロジカルレプリーションはPu b lish er1台、Su b scrib er1台で構成
ロジカルレプリーションのPu blish erサーバ1IPアドレス 19216812731では、データベースクラスタ内1のデータベースを作成
pu b d b: レプリーシン対象のテーブルを個別定義するPu b licatio n p u b 1
ロジカルレプリーションのSubscrib erサーバ2IPアドレス 19216812732では、データベース内に1のデータベースを作成
sub d b: Pu b lish erpu b d b デーベースに定義しPub licatio n から更データを受け取るSu b scrip tion sub 1を作成
6.4.2.2. 1
ロジカルレプリーションに関連する下のプロセスが異常終了した時の挙動を確認しす。
lo g ical replication lau n ch er
w al send er
lo g ical replication w o rk er
Pu blish erでは lo g ical replica tion lau n ch er w al send er のプロセスが起動していす。 また、pg_stat_replication ロジカルレプリーションが稼働中である
とが確認できます
PostgreSQL Enterprise Consortium
Page 179 of 285
(サーバ1において実施)
-bash-4.2$ ps aux | grep postgres
postgres 2179 0.0 0.8 389356 16552 ? S 109 0:56 /usr/pgsql-10/bin/postgres
postgres 2180 0.0 0.1 242164 2404 ? Ss 109 0:00 postgres: logger process
postgres 2182 0.0 0.3 389496 5716 ? Ss 109 0:01 postgres: checkpointer process
postgres 2183 0.0 0.2 389356 4092 ? Ss 109 0:20 postgres: writer process
postgres 2184 0.0 0.3 389356 6744 ? Ss 109 0:23 postgres: wal writer process
postgres 2185 0.0 0.1 389812 3352 ? Ss 109 0:38 postgres: autovacuum launcher
process
postgres 2186 0.0 0.1 244420 2620 ? Ss 109 1:09 postgres: stats collector process
postgres 2187 0.0 0.1 389648 3060 ? Ss 109 0:01 postgres: bgworker: logical
replication launcher
postgres 21882 0.0 0.3 392540 5780 ? Ss 206 0:00 postgres: wal sender process
repusr1 192.168.127.32(46474) idle
pubdb=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 21882
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 46474
backend_start | 2018-02-06 16:40:08.541313+09
backend_xmin |
state | streaming
sent_lsn | 0/5800DBB0
write_lsn | 0/5800DBB0
flush_lsn | 0/5800DBB0
replay_lsn | 0/5800DBB0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
また、Su b scriberでは lo gical replicatio n lau n ch er logical replica tion w orker ロセスが起動しており pg_stat_su b scriptio n からもロジカルレプリ
ションが稼働中であることが確認できます
PostgreSQL Enterprise Consortium
Page 180 of 285
(サーバ2において実施)
-bash-4.2$ ps aux | grep postgres
postgres 5405 0.0 0.3 397072 6264 ? Ss 206 0:02 postgres: bgworker: logical
replication worker for subscription 16463
postgres 31698 0.0 0.8 389296 16496 ? S 117 0:47 /usr/pgsql-10/bin/postgres
postgres 31699 0.0 0.1 242108 2008 ? Ss 117 0:00 postgres: logger process
postgres 31701 0.0 0.2 389448 4724 ? Ss 117 0:00 postgres: checkpointer process
postgres 31702 0.0 0.1 389296 3436 ? Ss 117 0:15 postgres: writer process
postgres 31703 0.0 0.3 389296 6332 ? Ss 117 0:18 postgres: wal writer process
postgres 31704 0.0 0.1 389752 3132 ? Ss 117 0:32 postgres: autovacuum launcher
process
postgres 31705 0.0 0.1 244360 2264 ? Ss 117 1:07 postgres: stats collector process
postgres 31706 0.0 0.1 389588 2760 ? Ss 117 0:01 postgres: bgworker: logical
replication launcher
subdb=# select * from pg_stat_subscription;
-[ RECORD 1 ]---------+------------------------------
subid | 16463
subname | sub1
pid | 5405
relid |
received_lsn | 0/5800DBB0
last_msg_send_time | 2018-02-07 13:45:31.222443+09
last_msg_receipt_time | 2018-02-07 13:45:31.05565+09
latest_end_lsn | 0/5800DBB0
latest_end_time | 2018-02-07 13:45:31.222443+09
logical replication launcher
Pu blish erlo g ical replica tion lau n ch er Killンドで強制終了する再度別のプロセスID で起動さいることがわかります。
(サーバ1において実施)
-bash-4.2$ kill -9 2187
-bash-4.2$ ps aux | grep postgres
postgres 2179 0.0 0.8 389356 16552 ? S 109 0:56 /usr/pgsql-10/bin/postgres
postgres 2180 0.0 0.1 242168 2404 ? Ss 109 0:00 postgres: logger process
postgres 28990 0.0 0.1 389356 2152 ? Ss 13:56 0:00 postgres: checkpointer process
postgres 28991 0.0 0.1 389356 2156 ? Ss 13:56 0:00 postgres: writer process
postgres 28992 0.0 0.1 389356 2116 ? Ss 13:56 0:00 postgres: wal writer process
postgres 28993 0.0 0.1 389784 3004 ? Ss 13:56 0:00 postgres: autovacuum launcher
process
postgres 28994 0.0 0.1 244288 1988 ? Ss 13:56 0:00 postgres: stats collector process
postgres 28995 0.0 0.1 389656 2520 ? Ss 13:56 0:00 postgres: bgworker: logical
replication launcher
の時Pu b lish erSu b scriberのログにはそれぞれ以下のメセージが出力さいます
PostgreSQL Enterprise Consortium
Page 181 of 285
(サーバ1のサーバログ)
2018-02-07 13:56:05.609 JST [2179] LOG: worker process: logical replication launcher (PID 2187)
was terminated by signal 9: Killed
2018-02-07 13:56:05.609 JST [2179] LOG: terminating any other active server processes
2018-02-07 13:56:05.609 JST [21882] WARNING: terminating connection because of crash of another
server process
2018-02-07 13:56:05.609 JST [21882] DETAIL: The postmaster has commanded this server process to
roll back the current transaction and exit, because another server process exited abnormally and
possibly corrupted shared memory.
2018-02-07 13:56:05.609 JST [21882] HINT: In a moment you should be able to reconnect to the
database and repeat your command.
2018-02-07 13:56:05.614 JST [2185] WARNING: terminating connection because of crash of another
server process
2018-02-07 13:56:05.614 JST [2185] DETAIL: The postmaster has commanded this server process to
roll back the current transaction and exit, because another server process exited abnormally and
possibly corrupted shared memory.
2018-02-07 13:56:05.614 JST [2185] HINT: In a moment you should be able to reconnect to the
database and repeat your command.
2018-02-07 13:56:05.620 JST [28988] FATAL: the database system is in recovery mode
2018-02-07 13:56:05.621 JST [2179] LOG: all server processes terminated; reinitializing
2018-02-07 13:56:05.652 JST [28989] LOG: database system was interrupted; last known up at 2018-
02-07 13:45:23 JST
2018-02-07 13:56:05.692 JST [28989] LOG: database system was not properly shut down; automatic
recovery in progress
2018-02-07 13:56:05.693 JST [28989] LOG: redo starts at 0/5800DAD0
2018-02-07 13:56:05.693 JST [28989] LOG: invalid record length at 0/5800DBB0: wanted 24, got 0
2018-02-07 13:56:05.693 JST [28989] LOG: redo done at 0/5800DB78
2018-02-07 13:56:05.698 JST [2179] LOG: database system is ready to accept connections
2018-02-07 13:56:10.640 JST [28998] LOG: starting logical decoding for slot "sub1"
2018-02-07 13:56:10.640 JST [28998] DETAIL: streaming transactions committing after 0/5800DB78,
reading WAL from 0/5800DB78
2018-02-07 13:56:10.640 JST [28998] LOG: logical decoding found consistent point at 0/5800DB78
2018-02-07 13:56:10.640 JST [28998] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
WARNING: terminating connection because of crash of another server process
DETAIL: The postmaster has commanded this server process to roll back the current transaction and
exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT: In a moment you should be able to reconnect to the database and repeat your command.
2018-02-07 13:56:05.444 JST [5405] ERROR: could not receive data from WAL stream: server closed
the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
2018-02-07 13:56:05.446 JST [31698] LOG: worker process: logical replication worker for
subscription 16463 (PID 5405) exited with exit code 1
2018-02-07 13:56:05.450 JST [9938] LOG: logical replication apply worker for subscription "sub1"
has started
2018-02-07 13:56:05.453 JST [9938] ERROR: could not connect to the publisher: FATAL: the database
system is in recovery mode
2018-02-07 13:56:05.454 JST [31698] LOG: worker process: logical replication worker for
subscription 16463 (PID 9938) exited with exit code 1
2018-02-07 13:56:10.463 JST [9939] LOG: logical replication apply worker for subscription "sub1"
has started
上記より、Pu b lish erlo g ical replication lau n ch erが停止した場合、Pu b lish erのインスンス再起動、リ処理が行われた後にレプリーションが再開されるこ
がわかりました。
同様にSu b scriberlog ical replica tion lau n ch er Killンドで強制終了した場合も、再度別のプロセスIDで起動さいることがわかります。また、この時
Subscrib erのインスンス再起動、リカバリ処理が行われてからレプリーションが再開されています。
PostgreSQL Enterprise Consortium
Page 182 of 285
(サーバ2において実施)
-bash-4.2$ kill -9 31706
-bash-4.2$ ps aux | grep postgres
postgres 9947 0.0 0.1 389296 2124 ? Ss 13:57 0:00 postgres: checkpointer process
postgres 9948 0.0 0.1 389296 2128 ? Rs 13:57 0:00 postgres: writer process
postgres 9949 0.0 0.1 389296 2108 ? Rs 13:57 0:00 postgres: wal writer process
postgres 9950 0.0 0.1 389616 2980 ? Ss 13:57 0:00 postgres: autovacuum launcher
process
postgres 9951 0.0 0.1 244228 2008 ? Ss 13:57 0:00 postgres: stats collector process
postgres 9952 0.0 0.1 389588 2760 ? Ss 13:57 0:00 postgres: bgworker: logical
replication launcher
postgres 9953 0.0 0.3 397084 6240 ? Ss 13:57 0:00 postgres: bgworker: logical
replication worker for subscription 16463
postgres 31698 0.0 0.8 389296 16500 ? S 117 0:47 /usr/pgsql-10/bin/postgres
postgres 31699 0.0 0.1 242108 2008 ? Ss 117 0:00 postgres: logger process
(サーバ1のサーバログ)
2018-02-07 13:57:43.391 JST [28998] LOG: unexpected EOF on standby connection
2018-02-07 13:57:43.498 JST [29004] LOG: starting logical decoding for slot "sub1"
2018-02-07 13:57:43.498 JST [29004] DETAIL: streaming transactions committing after 0/5800DC58,
reading WAL from 0/5800DC20
2018-02-07 13:57:43.498 JST [29004] LOG: logical decoding found consistent point at 0/5800DC20
2018-02-07 13:57:43.498 JST [29004] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-02-07 13:57:43.216 JST [31698] LOG: worker process: logical replication launcher (PID 31706)
was terminated by signal 9: Killed
2018-02-07 13:57:43.216 JST [31698] LOG: terminating any other active server processes
2018-02-07 13:57:43.218 JST [31704] WARNING: terminating connection because of crash of another
server process
2018-02-07 13:57:43.218 JST [31704] DETAIL: The postmaster has commanded this server process to
roll back the current transaction and exit, because another server process exited abnormally and
possibly corrupted shared memory.
2018-02-07 13:57:43.218 JST [31704] HINT: In a moment you should be able to reconnect to the
database and repeat your command.
2018-02-07 13:57:43.226 JST [31698] LOG: all server processes terminated; reinitializing
2018-02-07 13:57:43.250 JST [9946] LOG: database system was interrupted; last known up at 2018-02-
07 13:46:06 JST
2018-02-07 13:57:43.309 JST [9946] LOG: recovered replication state of node 1 to 0/5800DA98
2018-02-07 13:57:43.309 JST [9946] LOG: database system was not properly shut down; automatic
recovery in progress
2018-02-07 13:57:43.310 JST [9946] LOG: redo starts at 0/73706380
2018-02-07 13:57:43.310 JST [9946] LOG: invalid record length at 0/73706460: wanted 24, got 0
2018-02-07 13:57:43.310 JST [9946] LOG: redo done at 0/73706428
2018-02-07 13:57:43.315 JST [31698] LOG: database system is ready to accept connections
2018-02-07 13:57:43.327 JST [9953] LOG: logical replication apply worker for subscription "sub1"
has started
w al sender
Pu blish erw al sen derKillマンドで強制終了します。
PostgreSQL Enterprise Consortium
Page 183 of 285
(サーバ1において実施)
-bash-4.2$ kill -9 29004
-bash-4.2$ ps aux | grep postgres
postgres 2179 0.0 0.8 389356 16552 ? S 109 0:56 /usr/pgsql-10/bin/postgres
postgres 2180 0.0 0.1 242168 2404 ? Ss 109 0:00 postgres: logger process
postgres 29085 0.0 0.1 389356 2156 ? Ss 14:12 0:00 postgres: checkpointer process
postgres 29086 0.0 0.1 389356 2160 ? Ss 14:12 0:00 postgres: writer process
postgres 29087 0.0 0.1 389356 2120 ? Ss 14:12 0:00 postgres: wal writer process
postgres 29088 0.0 0.1 389784 3004 ? Ss 14:12 0:00 postgres: autovacuum launcher
process
postgres 29089 0.0 0.1 244288 1992 ? Ss 14:12 0:00 postgres: stats collector process
postgres 29090 0.0 0.1 389656 2520 ? Ss 14:12 0:00 postgres: bgworker: logical
replication launcher
postgres 29093 0.0 0.3 392476 5952 ? Ss 14:12 0:00 postgres: wal sender process
repusr1 192.168.127.32(46482) idle
(サーバ1のサーバログ)
2018-02-07 14:12:19.446 JST [2179] LOG: server process (PID 29004) was terminated by signal 9:
Killed
2018-02-07 14:12:19.447 JST [2179] LOG: terminating any other active server processes
2018-02-07 14:12:19.450 JST [28993] WARNING: terminating connection because of crash of another
server process
2018-02-07 14:12:19.450 JST [28993] DETAIL: The postmaster has commanded this server process to
roll back the current transaction and exit, because another server process exited abnormally and
possibly corrupted shared memory.
2018-02-07 14:12:19.450 JST [28993] HINT: In a moment you should be able to reconnect to the
database and repeat your command.
2018-02-07 14:12:19.456 JST [2179] LOG: all server processes terminated; reinitializing
2018-02-07 14:12:19.485 JST [29083] LOG: database system was interrupted; last known up at 2018-
02-07 14:11:06 JST
2018-02-07 14:12:19.511 JST [29084] FATAL: the database system is in recovery mode
2018-02-07 14:12:19.519 JST [29083] LOG: database system was not properly shut down; automatic
recovery in progress
2018-02-07 14:12:19.519 JST [29083] LOG: redo starts at 0/5800DEE8
2018-02-07 14:12:19.519 JST [29083] LOG: invalid record length at 0/5800DFC8: wanted 24, got 0
2018-02-07 14:12:19.519 JST [29083] LOG: redo done at 0/5800DF90
2018-02-07 14:12:19.524 JST [2179] LOG: database system is ready to accept connections
2018-02-07 14:12:24.529 JST [29093] LOG: starting logical decoding for slot "sub1"
2018-02-07 14:12:24.529 JST [29093] DETAIL: streaming transactions committing after 0/5800DF90,
reading WAL from 0/5800DF90
2018-02-07 14:12:24.529 JST [29093] LOG: logical decoding found consistent point at 0/5800DF90
2018-02-07 14:12:24.529 JST [29093] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-02-07 14:12:19.280 JST [9953] ERROR: could not receive data from WAL stream: server closed
the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
2018-02-07 14:12:19.281 JST [31698] LOG: worker process: logical replication worker for
subscription 16463 (PID 9953) exited with exit code 1
2018-02-07 14:12:19.285 JST [9998] LOG: logical replication apply worker for subscription "sub1"
has started
2018-02-07 14:12:19.344 JST [9998] ERROR: could not connect to the publisher: FATAL: the database
system is in recovery mode
2018-02-07 14:12:19.345 JST [31698] LOG: worker process: logical replication worker for
subscription 16463 (PID 9998) exited with exit code 1
2018-02-07 14:12:24.354 JST [9999] LOG: logical replication apply worker for subscription "sub1"
has started
上記よりPu b lish erw al sen d erが停止した場合もPu b lish erインスンスの再起動、リカバリ処理が行わ後にプリーションが再開されることがわかりました。
logical replication worker
Subscrib erlo g ical replication w o rk erKillマンドで強制終了します。
PostgreSQL Enterprise Consortium
Page 184 of 285
(サーバ2において実施)
-bash-4.2$ kill -9 9999
-bash-4.2$ ps aux | grep postgres
postgres 10013 0.0 0.1 389296 2124 ? Ss 14:16 0:00 postgres: checkpointer process
postgres 10014 0.0 0.1 389296 2128 ? Ss 14:16 0:00 postgres: writer process
postgres 10015 0.0 0.1 389296 2104 ? Ss 14:16 0:00 postgres: wal writer process
postgres 10016 0.0 0.1 389616 2980 ? Ss 14:16 0:00 postgres: autovacuum launcher
process
postgres 10017 0.0 0.1 244228 1968 ? Ss 14:16 0:00 postgres: stats collector process
postgres 10018 0.0 0.1 389588 2760 ? Ss 14:16 0:00 postgres: bgworker: logical
replication launcher
postgres 10019 0.0 0.3 397052 6340 ? Ss 14:16 0:00 postgres: bgworker: logical
replication worker for subscription 16463
postgres 31698 0.0 0.8 389296 16500 ? S 117 0:47 /usr/pgsql-10/bin/postgres
postgres 31699 0.0 0.1 242108 2008 ? Ss 117 0:00 postgres: logger process
(サーバ1のサーバログ)
2018-02-07 14:16:13.087 JST [29093] LOG: unexpected EOF on standby connection
2018-02-07 14:16:13.161 JST [29139] LOG: starting logical decoding for slot "sub1"
2018-02-07 14:16:13.161 JST [29139] DETAIL: streaming transactions committing after 0/5800E360,
reading WAL from 0/5800E328
2018-02-07 14:16:13.161 JST [29139] LOG: logical decoding found consistent point at 0/5800E328
2018-02-07 14:16:13.161 JST [29139] DETAIL: Logical decoding will begin using saved snapshot.
(サーバ2のサーバログ)
2018-02-07 14:16:12.920 JST [31698] LOG: worker process: logical replication worker for
subscription 16463 (PID 9999) was terminated by signal 9: Killed
2018-02-07 14:16:12.920 JST [31698] LOG: terminating any other active server processes
2018-02-07 14:16:12.924 JST [9950] WARNING: terminating connection because of crash of another
server process
2018-02-07 14:16:12.924 JST [9950] DETAIL: The postmaster has commanded this server process to
roll back the current transaction and exit, because another server process exited abnormally and
possibly corrupted shared memory.
2018-02-07 14:16:12.924 JST [9950] HINT: In a moment you should be able to reconnect to the
database and repeat your command.
2018-02-07 14:16:12.930 JST [31698] LOG: all server processes terminated; reinitializing
2018-02-07 14:16:12.957 JST [10012] LOG: database system was interrupted; last known up at 2018-
02-07 14:12:43 JST
2018-02-07 14:16:12.973 JST [10012] LOG: recovered replication state of node 1 to 0/5800DEB0
2018-02-07 14:16:12.973 JST [10012] LOG: database system was not properly shut down; automatic
recovery in progress
2018-02-07 14:16:12.974 JST [10012] LOG: redo starts at 0/73706710
2018-02-07 14:16:12.974 JST [10012] LOG: invalid record length at 0/73706A30: wanted 24, got 0
2018-02-07 14:16:12.974 JST [10012] LOG: redo done at 0/737069F8
2018-02-07 14:16:12.974 JST [10012] LOG: last completed transaction was at log time 2018-02-07
14:15:21.893165+09
2018-02-07 14:16:12.980 JST [31698] LOG: database system is ready to accept connections
2018-02-07 14:16:12.990 JST [10019] LOG: logical replication apply worker for subscription "sub1"
has started
上記より、Su b scrib erlo gical replicatio n lau n ch erが停止した場合もSu b scriberインスンス再起動、リカバリ処理が行われた後にレプリーションが再開さ
とがわかりました。
6.4.2.3. 2 Publisher
ロジカルレプリーションのPu blish erが停止した時の挙動を確認します
Subscrib erpg _stat_su b scription よりレプリーションが稼働中であることを確認しました
PostgreSQL Enterprise Consortium
Page 185 of 285
(サーバ2において実施)
subdb=# select * from pg_stat_subscription;
-[ RECORD 1 ]---------+------------------------------
subid | 16463
subname | sub1
pid | 10084
relid |
received_lsn | 0/5800ECB8
last_msg_send_time | 2018-02-07 14:37:30.310381+09
last_msg_receipt_time | 2018-02-07 14:37:30.143584+09
latest_end_lsn | 0/5800ECB8
latest_end_time | 2018-02-07 14:37:30.310381+09
Publisher
Pu blish erで起動中のPo stg reSQ Lサーバを強制終了します
(サーバ1において実施)
-bash-4.2$ pg_ctl -m f stop
サーバ停止処理の完了を待っています....
サーバは停止しした
次にSubscrib erpg _stat_su b scription を確認すると、レコードは消えないもののp id, LSN等の情報が表示されなくなりました
(サーバ2において実施)
subdb=# select * from pg_stat_subscription;
-[ RECORD 1 ]---------+------
subid | 16463
subname | sub1
pid |
relid |
received_lsn |
last_msg_send_time |
last_msg_receipt_time |
latest_end_lsn |
latest_end_time |
また、この時のSu b scriberのサーバログを確認すると、5秒毎に接続試行しlog ical replicatio n w ork erプロセスがエー終了する象が繰り返さいました。
(サーバ2のサーバログ)
2018-02-07 14:55:44.067 JST [10084] LOG: data stream from publisher has ended
2018-02-07 14:55:44.067 JST [10084] ERROR: could not send end-of-streaming message to primary: no
COPY in progress
2018-02-07 14:55:44.069 JST [10075] LOG: worker process: logical replication worker for
subscription 16463 (PID 10084) exited with exit code 1
2018-02-07 14:55:44.072 JST [10118] LOG: logical replication apply worker for subscription "sub1"
has started
2018-02-07 14:55:44.073 JST [10118] ERROR: could not connect to the publisher: FATAL: the
database system is shutting down
2018-02-07 14:55:44.074 JST [10075] LOG: worker process: logical replication worker for
subscription 16463 (PID 10118) exited with exit code 1
2018-02-07 14:55:49.083 JST [10119] LOG: logical replication apply worker for subscription "sub1"
has started
2018-02-07 14:55:49.084 JST [10119] ERROR: could not connect to the publisher: could not connect
to server: Connection refused
Is the server running on host "192.168.127.31" and accepting
TCP/IP connections on port 5432?
2018-02-07 14:55:49.085 JST [10075] LOG: worker process: logical replication worker for
subscription 16463 (PID 10119) exited with exit code 1
の状態からPu blish erPo stgreSQ Lーバを再度起動します
PostgreSQL Enterprise Consortium
Page 186 of 285
(サーバ1において実施)
-bash-4.2$ pg_ctl start
サーバの起動完了待ってい....2018-02-07 14:58:44.785 JST [29300] LOG: listening on IPv4 address
"0.0.0.0", port 5432
2018-02-07 14:58:44.785 JST [29300] LOG: listening on IPv6 address "::", port 5432
2018-02-07 14:58:44.785 JST [29300] LOG: listening on Unix socket
"/var/run/postgresql/.s.PGSQL.5432"
2018-02-07 14:58:44.790 JST [29300] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
2018-02-07 14:58:44.807 JST [29300] LOG: redirecting log output to logging collector process
2018-02-07 14:58:44.807 JST [29300] HINT: Future log output will appear in directory "log".
完了
サーバ起動完了
の時、Su b scriberpg _stat_su b scription を見ると初期状態の様にレプリケーションが稼働中であることが確認できました。
(サーバ2において実施)
subdb=# select * from pg_stat_subscription;
-[ RECORD 1 ]---------+------------------------------
subid | 16463
subname | sub1
pid | 10161
relid |
received_lsn | 0/5800ED60
last_msg_send_time | 2018-02-07 14:58:59.837546+09
last_msg_receipt_time | 2018-02-07 14:58:59.670736+09
latest_end_lsn | 0/5800ED60
latest_end_time | 2018-02-07 14:58:59.837546+09
の時Pu b lish erSu b scriberのログにはそれぞれ以下のメセージが出力さいます
(サーバ2のサーバログ)
2018-02-07 14:58:49.397 JST [10161] LOG: logical replication apply worker for subscription "sub1"
has started
(サーバ1のサーバログ)
2018-02-07 14:55:44.215 JST [2179] LOG: received fast shutdown request
2018-02-07 14:55:44.226 JST [2179] LOG: aborting any active transactions
2018-02-07 14:55:44.232 JST [2179] LOG: worker process: logical replication launcher (PID 29090)
exited with exit code 1
2018-02-07 14:55:44.232 JST [29085] LOG: shutting down
2018-02-07 14:55:44.240 JST [29290] FATAL: the database system is shutting down
2018-02-07 14:55:44.252 JST [2179] LOG: database system is shut down
2018-02-07 14:58:44.809 JST [29302] LOG: database system was shut down at 2018-02-07 14:55:44 JST
2018-02-07 14:58:44.813 JST [29300] LOG: database system is ready to accept connections
2018-02-07 14:58:49.572 JST [29310] LOG: starting logical decoding for slot "sub1"
2018-02-07 14:58:49.572 JST [29310] DETAIL: streaming transactions committing after 0/5800EC80,
reading WAL from 0/5800EC80
2018-02-07 14:58:49.572 JST [29310] LOG: logical decoding found consistent point at 0/5800EC80
2018-02-07 14:58:49.572 JST [29310] DETAIL: There are no running transactions.
の結果より、Pu b lish erが停止した場合はレプリケーションが停止するが、再度起動すれレプーションも再開されることがわかりました
6.4.2.4. 3 Su bscriber
ロジカルレプリーションのSubscrib erが停止した時の挙動確認しす。
Pu blish erp g _stat_rep lication よりレプリーションが稼働中であることを確認しした
PostgreSQL Enterprise Consortium
Page 187 of 285
(サーバ1において実施)
pubdb=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 29213
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 46484
backend_start | 2018-02-07 14:33:55.842956+09
backend_xmin |
state | catchup
sent_lsn | 0/5800EBD8
write_lsn | 0/5800EBD8
flush_lsn | 0/5800EBD8
replay_lsn | 0/5800EBD8
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
Subscriber
Subscrib erで起動中のPostgreSQ Lサーを強制終了します。
(サーバ2において実施)
-bash-4.2$ pg_ctl -m f stop
サーバ停止処理の完了を待っています....
サーバは停止しした
次にPu blish erp g _stat_rep lication を確認すると、レプリケーションの情報が表示されなくりました また、この時Pu b lish erのサーバログは何も出力さていませ
んでした
(サーバ1において実施)
pubdb=# select * from pg_stat_replication;
(0 rows)
お、この状態のままPu b lish er1データINSERTしても特に問題処理は完了します
(サーバ1において実施)
pubdb=# insert into data1 values (6, 'pub6');
INSERT 0 1
の状態からSubscrib erPostg reSQ Lサーバを再度起動します
(サーバ2において実施)
-bash-4.2$ pg_ctl start
サーバの起動完了待ってい....2018-02-07 14:33:55.641 JST [10075] LOG: listening on IPv4 address
"0.0.0.0", port 5432
2018-02-07 14:33:55.641 JST [10075] LOG: listening on IPv6 address "::", port 5432
2018-02-07 14:33:55.642 JST [10075] LOG: listening on Unix socket
"/var/run/postgresql/.s.PGSQL.5432"
2018-02-07 14:33:55.642 JST [10075] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
2018-02-07 14:33:55.656 JST [10075] LOG: redirecting log output to logging collector process
2018-02-07 14:33:55.656 JST [10075] HINT: Future log output will appear in directory "log".
完了
サーバ起動完了
で、Pu b lish er側のp g _stat_rep lica tion を見ると初期状態の様にレプリーションが復旧してとが確認できました
PostgreSQL Enterprise Consortium
Page 188 of 285
(サーバ1において実施)
pubdb=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 29213
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 46484
backend_start | 2018-02-07 14:33:55.842956+09
backend_xmin |
state | catchup
sent_lsn | 0/5800EBD8
write_lsn | 0/5800EBD8
flush_lsn | 0/5800EBD8
replay_lsn | 0/5800EBD8
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
また、Pu blish erINSERTしたードがSu b scriberのテーブルにも転送されています。
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2 | c3
----+------+----
1 | pub1 |
2 | pub2 |
3 | pub3 |
4 | pub4 |
5 | pub5 |
6 | pub6 |
の時Pu b lish erSu b scriberのログにはそれぞれ以下のメセージが出力さいます
(サーバ1のサーバログ)
2018-02-07 14:33:55.845 JST [29213] LOG: starting logical decoding for slot "sub1"
2018-02-07 14:33:55.845 JST [29213] DETAIL: streaming transactions committing after 0/5800E858,
reading WAL from 0/5800E820
2018-02-07 14:33:55.845 JST [29213] LOG: logical decoding found consistent point at 0/5800E820
2018-02-07 14:33:55.845 JST [29213] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-02-07 14:33:55.658 JST [10077] LOG: database system was shut down at 2018-02-07 14:29:59 JST
2018-02-07 14:33:55.659 JST [10077] LOG: recovered replication state of node 1 to 0/5800E740
2018-02-07 14:33:55.662 JST [10075] LOG: database system is ready to accept connections
2018-02-07 14:33:55.674 JST [10084] LOG: logical replication apply worker for subscription "sub1"
has started
の結果より、Su b scriberが停止した場合はレプリーションが停止するが、再度起動レプーションも再開されることがわかりした
6.4.2.5. 4 Publisher/Subscriber
ロジカルレプリーションで利用するネットワークが断絶した時の挙動を確認します
Pu blish erp g _stat_rep lication よりレプリーションが稼働中であることを確認しした
PostgreSQL Enterprise Consortium
Page 189 of 285
(サーバ1において実施)
pubdb=# select * from pg_stat_replication;
-[ RECORD 1 ]----+-----------------------------
pid | 29310
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 46522
backend_start | 2018-02-07 14:58:49.56556+09
backend_xmin |
state | streaming
sent_lsn | 0/5800EE40
write_lsn | 0/5800EE40
flush_lsn | 0/5800EE40
replay_lsn | 0/5800EE40
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
Pu blish erでレプリーションに使用するネットワークを停止します ではO S(Cen tO S7.2)Netw o rkManagerを利用して対象インタフェース(ens192)を停止しまし
(サーバ1において実施)
[root@nk_PGECons_1 ~]# nmcli connection down ens192
Connection 'ens192' successfully deactivated (D-Bus active path:
/org/freedesktop/NetworkManager/ActiveConnection/0)
[root@nk_PGECons_1 ~]# nmcli connection show
名前 UUID タイ デバイス
ens192 fa64b28e-a7db-45f0-b7b1-0b2b298b20d2 802-3-ethernet --
ens160 c0791a7a-43be-4254-847d-2b793b583bba 802-3-ethernet ens160
しばらくの間Pu b lish erp g_stat_rep lication が初期状態のまですが 1分ほど経過するとレプリーションの情報が表示されなくりました
(サーバ1において実施)
pubdb=# select * from pg_stat_replication;
(0 rows)
の時のPu b lish erのログには以下のメッセージが出力されました。ここではw al_send er_timeo u tパラータをデフォルトの60秒で設定していため、 イムアウトを検知
して非活動のプリーション接続を停止しています。
(サーバ1のサーバログ)
2018-02-07 15:41:12.504 JST [29310] LOG: terminating walsender process due to replication timeout
Pu blish erで停止したネッワークのインタフェースを復旧します
(サーバ1において実施)
[root@nk_PGECons_1 ~]# nmcli connection up ens192
接続が正常にアクィベートさました (D-Bus ィブパス: /org/freedesktop/NetworkManager/ActiveConnection/2)
[root@nk_PGECons_1 ~]# nmcli connection show
名前 UUID タイ デバイス
ens192 fa64b28e-a7db-45f0-b7b1-0b2b298b20d2 802-3-ethernet ens192
ens160 c0791a7a-43be-4254-847d-2b793b583bba 802-3-ethernet ens160
Pu blish er側のp g_stat_replication を確認すると、レプーションの情報が再び表示されるよなりました
PostgreSQL Enterprise Consortium
Page 190 of 285
(サーバ1において実施)
pubdb=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 29665
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 46523
backend_start | 2018-02-07 15:44:40.511419+09
backend_xmin |
state | catchup
sent_lsn | 0/5800F300
write_lsn | 0/5800F300
flush_lsn | 0/5800F300
replay_lsn | 0/5800F300
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
Pu blish erのログには以下のメッセージが出力さレプリケーションが再開さとがわかります
(サーバ1のサーバログ)
2018-02-07 15:44:40.514 JST [29665] LOG: starting logical decoding for slot "sub1"
2018-02-07 15:44:40.514 JST [29665] DETAIL: streaming transactions committing after 0/5800EE40,
reading WAL from 0/5800EE08
2018-02-07 15:44:40.514 JST [29665] LOG: logical decoding found consistent point at 0/5800EE08
2018-02-07 15:44:40.514 JST [29665] DETAIL: There are no running transactions.
また、Su b scriberのログは下のメッセージが出力されており、ネットワークの復旧に伴っ lo gica l replication w orker が再起動したとがわかります
(サーバ2のサーバログ)
2018-02-07 15:44:40.338 JST [10161] ERROR: could not receive data from WAL stream: server closed
the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
2018-02-07 15:44:40.339 JST [10075] LOG: worker process: logical replication worker for
subscription 16463 (PID 10161) exited with exit code 1
2018-02-07 15:44:40.343 JST [10247] LOG: logical replication apply worker for subscription "sub1"
has started
れらの結果より、ネットワークの断絶により一時的にレプリーシンが停止した場合でも、ネットワークが復旧すればレプリケーションも自動的に再開さとがわかりまし
6.4.3. /
ロジカルレプリーションが稼働している環境で新た作成したテーブルをレプリケーション対象として追加したテーブル定義を変更する手順を確認しす。
6.4.3.1.
本章は以下の環境を利用した検証結果を元に解説します。
PostgreSQL Enterprise Consortium
Page 191 of 285
Po stg reSQ LサーバはロジカルプリーションのPu blish er1台、Subscrib er1台で構
ロジカルレプリーションのPu blish erサーバ1IPアドレス 19216812731では、新規に作成したデータベースp u b db ,pu b d b_all_tab leのみを作成
ロジカルレプリーションのSubscrib erサーバ2IPアドレス 19216812732では、新規に作成したデータベースsu b d b ,su b d b_all_tableのみを作成
6.4.3.2. ( Publication)
データベース単位のPu b lica tion が作成さデータベースに対しテーブルを追加する手順を説明します。
Pu blish erのデータベースp u b db _all_tab le接続し、データベース単位のPu b lication pu b_all_tab leを作成します。
(サーバ1において実施)
pubdb_all_table=# CREATE PUBLICATION pub_all_table FOR ALL TABLES;
CREATE PUBLICATION
pubdb_all_table=# \dRp+
Publication pub_all_table
Owner | All tables | Inserts | Updates | Deletes
----------+------------+---------+---------+---------
postgres | t | t | t | t
Pu lish erのデータベースpu b d b_all_tableテーフdata1を作成しす。システカタログpg_pu blication _tablesでテd ata1Pu b lication
pu b _all_tab leのレプリション対象として認識さとが確認できます
PostgreSQL Enterprise Consortium
Page 192 of 285
(サーバ1において実施)
pubdb_all_table=# CREATE TABLE data1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
pubdb_all_table=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------------+------------+-----------
pub_all_table | public | data1
Subscrib erのデータベースsu b db _all_table接続し、Su b scription を作成します。なお、Subscrip tio n 作成時点で接続先のPu b lication の対象テーブルが存在し
いとーになるめ、あらかじめSu b scrib erのデータベー同一名称のーブルを作成しておいてい。
(サーバ2において実施)
subdb_all_table=# CREATE SUBSCRIPTION sub_all_table CONNECTION 'host=192.168.127.31
dbname=pubdb_all_table user=repusr1 password=repusr1' PUBLICATION pub_all_table;
ERROR: relation "public.data1" does not exist data1ーブルが存在しいとエラーとなる
subdb_all_table=# CREATE TABLE data1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
subdb_all_table=# CREATE SUBSCRIPTION sub_all_table CONNECTION 'host=192.168.127.31
dbname=pubdb_all_table user=repusr1 password=repusr1' PUBLICATION pub_all_table;
NOTICE: created replication slot "sub_all_table" on publisher
CREATE SUBSCRIPTION
Subscrip tio n を作成するSub scrib erのログに初期データ転送のメッセージが出力さロジカルレプリケーションが開始されたとが確認できます。
(サーバ2のサーバログ)
2018-01-17 11:09:23.050 JST [31749] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data1" has started
2018-01-17 11:09:23.062 JST [31749] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data1" has finished
初期状態からPu lish erのデータースpu b d b _all_tab leテーフdata2作成します。FO R ALL TAB LES句を付けてCRATEしたPu b lication のため、作成した
ーブルdata2が自動的にレプリケーション対象として認識れていることがわかります。
(サーバ1において実施)
pubdb_all_table=# CREATE TABLE data2 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
pubdb_all_table=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------------+------------+-----------
pub_all_table | public | data1
pub_all_table | public | data2
次にSu b scrib erのデータベースsubd b _all_tableテーブd ata2を作成します。の時点でSu b scrip tion su b _all_tableーブルdata2識されておら
ず、ーブルdata2のレプリーションが開始されていないことがわかります
(サーバ2において実施)
subdb_all_table=# CREATE TABLE data2 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
subdb_all_table=# select a3.subname, a2.relname, a1.srsubstate, a1.srsublsn from
pg_subscription_rel as a1 left outer join pg_class as a2 on a1.srrelid = a2.oid left outer join
pg_stat_subscription as a3 on a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
---------------+---------+------------+------------
sub_all_table | data1 | r | 0/5602B818
既存のSu b scrip tion 新たなレプリケーション対象テーブルを認識させるためにALTER SU B SCRIPTIO N文を実行します。再びpg_su b scription _relを確認するとテー
ブルdata2が新た認識さいることが確認できます。
PostgreSQL Enterprise Consortium
Page 193 of 285
(サーバ2において実施)
subdb_all_table=# ALTER SUBSCRIPTION sub_all_table REFRESH PUBLICATION;
ALTER SUBSCRIPTION
subdb_all_table=# select a3.subname, a2.relname, a1.srsubstate, a1.srsublsn from
pg_subscription_rel as a1 left outer join pg_class as a2 on a1.srrelid = a2.oid left outer join
pg_stat_subscription as a3 on a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
---------------+---------+------------+------------
sub_all_table | data1 | r | 0/5602B818
sub_all_table | data2 | d |
6.4.3.3. ( Publication)
ーブル単位のPu b lication が作成さたデータベースに対して、テーブルを追加する手順を説明します。
Pu blish erのデータベースp u b db テーブルdata1CREATEした後、レプリーション対象とするPu b lication pu b 1作成します。
(サーバ1において実施)
pubdb=# CREATE TABLE data1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
pubdb=> CREATE PUBLICATION pub1 FOR TABLE data1;
CREATE PUBLICATION
pubdb=# \dRp+
Publication pub1
Owner | All tables | Inserts | Updates | Deletes
---------+------------+---------+---------+---------
pubusr1 | f | t | t | t
Tables:
"public.data1"
Subscrib erのデータベースsu b db Su b scription を作成し、レプリケーションを開始します。
(サーバ2において実施)
subdb=# CREATE TABLE data1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
subdb=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub1;
NOTICE: created replication slot "sub1" on publisher
CREATE SUBSCRIPTION
初期状態からPu lish erのデータースpu b d b テーブルd ata1_1を作成しますFO R ALL TAB LES句を付けずにCRATEしたPu b licatio n め、作成したーブル
data1_1がレプリーション対象と認識さいないことがわかります
(サーバ1において実施)
pubdb=# CREATE TABLE data1_1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
pubdb=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
----------+------------+-----------
pub1 | public | data1
ーブルdata1_1既存のPu b lication p u b 1にレプリーシン対象として追加するには、ALTER PUB LICATIO N文を実行します。
PostgreSQL Enterprise Consortium
Page 194 of 285
(サーバ1において実施)
pubdb=# ALTER PUBLICATION pub1 ADD TABLE data1_1;
ALTER PUBLICATION
pubdb=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------+------------+-----------
pub1 | public | data1
pub1 | public | data1_1
次にSu b scrib erのデータベースsubd b ーブルd ata 1_1を作成します。この時点ではSu bscrip tion sub 1にテーブルdata1_1認識されません。
(サーバ2において実施)
subdb=# CREATE TABLE data1_1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
subdb=# select a3.subname, a2.relname, a1.srsubstate, a1.srsublsn from pg_subscription_rel as a1
left outer join pg_class as a2 on a1.srrelid = a2.oid left outer join pg_stat_subscription as a3 on
a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
---------+---------+------------+------------
sub1 | data1 | r | 0/55FB63D0
既存のSu b scrip tion 新たなレプリケーション対象テーブルを認識させるためにALTER SU B SCRIPTIO N文を実行しますpg_su b scription _relを確認するーブル
data1_1が新たに認識されいることが確認できます。
(サーバ2において実施)
subdb=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION;
ALTER SUBSCRIPTION
subdb=# select a3.subname, a2.relname, a1.srsubstate, a1.srsublsn from pg_subscription_rel as a1
left outer join pg_class as a2 on a1.srrelid = a2.oid left outer join pg_stat_subscription as a3 on
a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
---------+---------+------------+------------
sub1 | data1_1 | r | 0/56068D38
sub1 | data1 | r | 0/55FB63D0
6.4.3.4.
レプーションが実行さいるテーブルに新たな列を追加する手順を説明します
前述のPu b lication p u b 1, Sub scrip tion sub 1を利用し、テーブd ata1のデータPu blish er,Su b scrib er間でレプリーションさてい状態とします。まテーブ
d ata 1にはそれぞ1件のデータが存在する状態とします
(サーバ1において実施)
pubdb=# SELECT * FROM data1;
c1 | c2
----+------
1 | pub1
(サーバ2において実施)
subdb=# SELECT * FROM data1;
c1 | c2
----+------
1 | pub1
レプーション対象のテーブル定義に不一致があると更新競合が発生し、ロジカルレプリーシンの停止につながります。意図しないエーを起こようあらかじめALTER
SUBSCR IPTIO N文でSu b scrip tion を一時停止しておとよいでしょ
PostgreSQL Enterprise Consortium
Page 195 of 285
(サーバ2において実施)
subdb=# ALTER SUBSCRIPTION sub1 DISABLE;
ALTER SUBSCRIPTION
subdb=# SELECT * FROM pg_stat_subscription;
subid | subname | pid | relid | received_lsn | last_msg_send_time |
last_msg_receipt_time | latest_end_lsn | latest_end_time
-------+---------------+-------+-------+--------------+-------------------------------+------------
-------------------+----------------+-------------------------------
16463 | sub1 | | | | |
| |
の時、Su b scriberのログには以下の様なメッセージが出力さます
(サーバ2のサーバログ)
2018-01-17 14:51:52.437 JST [31708] LOG: logical replication apply worker for subscription "sub1"
will stop because the subscription was disabled
ロジカルレプリーションを停止した後、Pu b lish erのテーブd ata1ALTER TAB LE文で列を追加します。また、こで確認のた1件レコードを挿入しておきます。
(サーバ1において実施)
pubdb=# ALTER TABLE data1 ADD COLUMN c3 VARCHAR(5);
ALTER TABLE
pubdb=# INSERT INTO data1 VALUES (2, 'pub2', 'pub2');
INSERT 0 1
pubdb=# SELECT * FROM data1;
c1 | c2 | c3
----+------+------
1 | pub1 |
2 | pub2 | pub2
次にSubscrib erのテーブルdata1にもALTER TABLE文で同じ定義の列を追加します。Subscrip tio n を停止しているため2件目のードはまだ転送さいません。
(サーバ2において実施)
subdb=# ALTER TABLE data1 ADD COLUMN c3 VARCHAR(5);
ALTER TABLE
subdb=# SELECT * FROM data1;
c1 | c2 | c3
----+------+----
1 | pub1 |
Subscrib erSu b scrip tion を再度有効化しロジカルレプーションを再開するの時点で2件目のレコードが転送されます。
(サーバ2において実施)
subdb=# ALTER SUBSCRIPTION sub1 ENABLE;
ALTER SUBSCRIPTION
subdb=# SELECT * FROM data1;
c1 | c2 | c3
----+------+------
1 | pub1 |
2 | pub2 | pub2
Subscrib erpg _stat_su b scritp ion ログを再度確認すると、正常にレプリケーシンが再開さいることがわかります。
PostgreSQL Enterprise Consortium
Page 196 of 285
(サーバ2において実施)
subdb=# SELECT * FROM pg_stat_subscription;
subid | subname | pid | relid | received_lsn | last_msg_send_time |
last_msg_receipt_time | latest_end_lsn | latest_end_time
-------+---------------+-------+-------+--------------+-------------------------------+------------
-------------------+----------------+-------------------------------
16463 | sub1 | 32626 | | 0/56073298 | 2018-01-17 15:02:10.817291+09 | 2018-01-17
15:02:10.650377+09 | 0/56073298 | 2018-01-17 15:02:10.817291+09
(サーバ2のサーバログ)
2018-01-17 15:01:47.266 JST [32626] LOG: logical replication apply worker for subscription "sub1"
has started
6.4.3.5.
レプーションが実行さいるテーブルにインデックスを追加する手順を説明します
前述のPu b lication p u b 1, Sub scrip tion sub 1およびテーブd ata 1そのまま利用しす。初期状態でPu blish er,Su bscrib erのテーブルdata1は以下の定義となっ
います
(サーバ1において実施)
pubdb=# \d data1
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
c3 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Publications:
"pub1"
(サーバ2において実施)
subdb=# \d data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
c3 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Publisher
初期状態からPu b lish erのテーブd ata1にのみインデックCR E ATEると、Su b scriberのテーブルdata1にはインデッスが追加さないことがわかります。
PostgreSQL Enterprise Consortium
Page 197 of 285
(サーバ1において実施)
pubdb=# CREATE INDEX data1_c2_idx ON data1 (c2);
CREATE INDEX
pubdb=# \d data1
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
c3 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
"data1_c2_idx" btree (c2)
Publications:
"pub1"
(サーバ2において実施)
subdb=# \d data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
c3 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Subscriber
次にSubscrib erのテーブルdata1にのみインデックスをCR EATEすると、Sub scrib erのテーブd ata1にのみインデックが追加さていとがわかります
(サーバ2において実施)
subdb=# CREATE INDEX data1_c3_idx ON data1 (c3);
CREATE INDEX
subdb=# \d data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
c3 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
"data1_c3_idx" btree (c3)
(サーバ1において実施)
pubdb=# \d data1
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
c3 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
"data1_c2_idx" btree (c2)
Publications:
"pub1"
ロジカルレプリーションにおいてインデックスはレプリーシン対象とならないため、インデックの追加、削除が既存のプリションに影響及ぼすとはありませんが、
Pu blish erで作成したインデッスがSub scrib erでも必要であれ同じCREATE INDEX文を発行する必要があります。
6.4.4.
ーミングレプーションがデータベースクラスタへの操作、オブジェクを全て複製すると違い、PostgreSQ L10のロジカルレプーションでは以下の様な操作、オ
PostgreSQL Enterprise Consortium
Page 198 of 285
ジェトが複製さません。そのためこ必要に応じPu b lish erSub scrib erで同じ操作行う等の対処を求められます。
6.6 ロジカルプリションで複製されない操作、オブジェク
CREATE TABLE, ALTER TAB LE, CREATE INDEX等のDDL
シーケンスの定義データ
TRUNCATE
Large O bject
VIEW , MATER IALIZED VIEW
FO R E IG N TAB LE
UNLO GGED TAB LE
パーティショニングの親ーブル
ではTRUNCATEとシーケンス対するロジカルレプーションの挙動確認しす。
6.4.4.1.
本章は以下の環境を利用した検証結果を元に解説します。
Po stg reSQ LサーバはロジカルプリーションのPu blish er1台、Subscrib er1台で構
ロジカルレプリーションのPu blish erサーバ1IPアドレス 19216812731では、新規に作成したデータベースp u b db を作成
データベースpu b d bは、レプリーション対象のテーブルを個別定義Pub licatio n pu b 1,p u b 3を作成
pu b 1,p u b3のレプリケーション対象として、それぞれテーブルdata1,data3設定
ロジカルレプリーションのSubscrib erサーバ2IPアドレス 19216812732では、新規に作成したデータベースsu b d b を作成
データベースsu b d b Pu b lish erpu b d bデータベース定義したPu b lication 変更データを受け取るSu b scriptio n sub1,su b 3よびテー
ブルdata1,data3作成
PostgreSQL Enterprise Consortium
Page 199 of 285
6.4.4.2. TRUN CATE
初期状態でテーブルdata1のデータPu b lish er,Su bscrib er間でレプリケーションさてい状態とします。まテーブd a ta1それぞ5件のデータが存在する状態
とします。
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
Pu blish erでテーブルdata1対してTRU NCATE TAB LEを実行します
(サーバ1において実施)
pubdb=# TRUNCATE TABLE data1;
TRUNCATE TABLE
pubdb=# select * from data1;
c1 | c2
----+----
の状態でSu bscrib erのテーブルdata1は変化していないことが確認できます
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
Subscrib erでもテーブd a ta1対してTRUNCATE TAB LEを実行するで、Pu b lish erと一致しす。
(サーバ2において実施)
subdb=# TRUNCATE TABLE data1;
TRUNCATE TABLE
subdb=# select * from data1;
c1 | c2
----+----
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+----
TRUNCATE TAB LEW ALも記録されるデータ更新操作であり、スングレプリーションで複製れる操作ですが、ロジカルレプリーションでは複製さないため
意が必要です。
PostgreSQL Enterprise Consortium
Page 200 of 285
6.4.4.3.
ではSERIAL列を含むテーブルをロジカルレプリケーションで複製した場合の挙動を確認します。
Pu blish erのデータベースp u b db Sub scrib erのデータベースsu b d b それぞれテーブルdata3を作成し、ロジカルプリションで複製される状態にします。 またテー
ブルdata3SERIAL列を定義しす。
(サーバ1において実施)
pubdb=# CREATE TABLE data3 (c1 SERIAL PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
pubdb=# CREATE PUBLICATION pub3 FOR TABLE data3;
CREATE PUBLICATION
(サーバ2において実施)
subdb=# CREATE TABLE data3 (c1 SERIAL PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
subdb=# CREATE SUBSCRIPTION sub3 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub3;
NOTICE: created replication slot "sub3" on publisher
CREATE SUBSCRIPTION
SERIAL
Pu blish erのテーブルdata3レコードを挿入します。挿入したレコードがSu b scriberのテーブルdata3にも転送さす。
(サーバ1において実施)
pubdb=# INSERT INTO data3 (c2) VALUES ('pub1');
INSERT 0 1
pubdb=# SELECT * FROM data3;
c1 | c2
----+------
1 | pub1
(サーバ2において実施)
subdb=# SELECT * FROM data3;
c1 | c2
----+------
1 | pub1
の時点でPublish er存在するシーケンスは現在値が1なっていすが、Sub scrib er存在するーケンスらは現在値が取得できません。 まり、SERIAL列の値自
体は複製されたものの、内部的に作成さたシーケンスのデータ複製さいません。
(サーバ1において実施)
pubdb=# SELECT currval('data3_c1_seq');
currval
---------
1
(サーバ2において実施)
subdb=# SELECT currval('data3_c1_seq');
ERROR: currval of sequence "data3_c1_seq" is not yet defined in this session
Su b scrib erのテーブルdata3対してレコードを挿入するとキー重複でエラーにります Sub scrib erのシーケンスにPu b lish erのシーケンスデーと関係なく
1を発行しためで
PostgreSQL Enterprise Consortium
Page 201 of 285
(サーバ2において実施)
subdb=# INSERT INTO data3 (c2) VALUES ('pub1');
ERROR: duplicate key value violates unique constraint "data3_pkey"
DETAIL: Key (c1)=(1) already exists.
subdb=# SELECT currval('data3_c1_seq');
currval
---------
1
の状態で再Su b scrib erのテーブルdata3レコードを挿入する成功します。は先ほINSER T失敗した際Su bscrib erのシーケンス1カウントアップれて
おり、今回のINSERT2を発行したためキー重複が発生せず挿入できたためで
(サーバ2において実施)
subdb=# INSERT INTO data3 (c2) VALUES ('pub1');
INSERT 0 1
subdb=# SELECT * FROM data3;
c1 | c2
----+------
1 | pub1
2 | pub1
subdb=# SELECT currval('data3_c1_seq');
currval
---------
2
の時点でPublish erのシーケンスは在値が1ためのままPu b lish erのテーブルdata3INSERTするSu b scriberのテルでキー重複が発生しす。 そこで
Pu blish erのシーケンスの現在値を2進めてからレコード挿入するとPu b lish erで挿入したレコードがSub scrib er複製さした
(サーバ1において実施)
pubdb=# SELECT * FROM data3;
c1 | c2
----+------
1 | pub1
pubdb=# SELECT currval('data3_c1_seq');
currval
---------
1
pubdb=# SELECT nextval('data3_c1_seq');
nextval
---------
2
pubdb=# INSERT INTO data3 (c2) VALUES ('pub1');
INSERT 0 1
pubdb=# SELECT * FROM data3;
c1 | c2
----+------
1 | pub1
3 | pub1
(サーバ1において実施)
subdb=# SELECT * FROM data3;
c1 | c2
----+------
1 | pub1
2 | pub1
3 | pub1
のようにPu blish erSERIAL列に付与れた値はSu b scrib erのテーブルに転送さますが、内部的に使用するシーケンスのデータは複製さいため、Su b scrib er
で独自にレコードを挿入するとシーケンスのデータ不整合が生じます。そのため、SERIAL列を含むテーブルでロジカルレプリケーションを行う場合はSu b scriberでのレコード
更新は抑制した方がよいでしょ
6.4.5.
マスしか更新できないストリーミングレプリーションに対し、ロジカルプリーションはSub scrib er更新することができます。ただし、Pu b lish erSu b scrib erのテーブル
PostgreSQL Enterprise Consortium
Page 202 of 285
間で以下の様な更新処理の競合が発生る可能性があります。
6.7 ロジカルプリションで発生する新処理の競合パター
( ) ( )
主キー違/一意キー違反
CHECK制約違
更新データが存在し
削除データが存在し
ーブルが存在しな
一部の列が存在しない
データ型変換
ーブルのロック
更新対象ードのロック
では競合が発生した時の挙動と対応方法にいて検証しす。
6.4.5.1.
本章は以下の環境を利用した検証結果を元に解説します。
Po stg reSQ LサーバはロジカルプリーションのPu blish er1台、Subscrib er1台で構
ロジカルレプリーションのPu blish erサーバ1IPアドレス 19216812731では、新規に作成したデータベースp u b db を作成
データベースpu b d bは、レプリーション対象のテーブルを個別定義Pub licatio n pu b 1作成
pu b 1のレプーション対象としてそれぞーブルdata1設定
ロジカルレプリーションのSubscrib erサーバ2IPアドレス 19216812732では、新規に作成したデータベースsu b d b を作成
PostgreSQL Enterprise Consortium
Page 203 of 285
データベースsu b d b Pu b lish erpu b d bデータベース定義したPu b lication 変更データを受け取るSu b scriptio n sub1およびテーブ
data1作成
6.4.5.2.
前述の環境において実際に競合が発生し時の挙動と競合を解消さるための方法を競合発生のパターン毎に紹介します
6.4.5.2.1. /
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします。ま、テーブルd ata1c1PRIM ARY KEYとし、そぞれ以下のデータ
が存在する状態とします
(サーバ1において実施)
pubdb=# \d data1
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Publications:
"pub1"
pubdb=# select * from data1;
c1 | c2
----+-------
1 | aaaaa
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+-------
1 | aaaaa
2 | sub
Pu blish erのテーブルdata1c1=2のレコードを挿入するPu b lish erINSERT成功します
(サーバ1において実施)
pubdb=# insert into data1 values (2, 'pub');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+-------
1 | aaaaa
2 | pub
の時Sub scrib erでは主キー違反による競合が発生し、レプリケーションが停止しす。 Pu b lish erSu b scrib erのログには競合が解消するまで5秒毎に以下のメセー
ジが繰り返し出力されます。
PostgreSQL Enterprise Consortium
Page 204 of 285
(サーバ1のサーバログ)
2018-01-10 13:37:55.149 JST [5859] LOG: starting logical decoding for slot "sub1"
2018-01-10 13:37:55.149 JST [5859] DETAIL: streaming transactions committing after 0/55F82E30,
reading WAL from 0/55F82DF8
2018-01-10 13:37:55.149 JST [5859] LOG: logical decoding found consistent point at 0/55F82DF8
2018-01-10 13:37:55.149 JST [5859] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-01-10 13:37:49.965 JST [2132] ERROR: duplicate key value violates unique constraint
"data1_pkey"
2018-01-10 13:37:49.965 JST [2132] DETAIL: Key (c1)=(2) already exists.
2018-01-10 13:37:49.968 JST [2131] WARNING: out of background worker slots
2018-01-10 13:37:49.968 JST [2131] HINT: You might need to increase max_worker_processes.
2018-01-10 13:37:49.968 JST [2123] LOG: worker process: logical replication worker for
subscription 16394 (PID 2132) exited with exit code 1
Subscrib erのテーブルでキーが重複るレードを削除すると競合が解消し、レプリーシンが再開されます またPu b lish erSub scrib erへのエラーメセージも出力
れなくります。
(サーバ2において実施)
subdb=# delete from data1 where c1 = 2;
DELETE 1
subdb=# select * from data1;
c1 | c2
----+-------
1 | aaaaa
2 | pub
6.4.5.2.2. CHECK
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします。まSu bscrib erのテーブルdata1c1列にCHECK制約を付与しす。
(サーバ2において実施)
subdb=# ALTER TABLE data1 ADD CONSTRAINT data1_c1_check CHECK (c1 < 10);
ALTER TABLE
subdb=# \d+ data1
Table "public.data1"
Column | Type | Collation | Nullable | Default | Storage | Stats target |
Description
--------+----------------------+-----------+----------+---------+----------+--------------+--------
-----
c1 | integer | | not null | | plain | |
c2 | character varying(5) | | | | extended | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Check constraints:
"data1_c1_check" CHECK (c1 < 10)
Pu blish erのテーブルdata1Su b scrib erのみに追加したCHECK制約に違反るレードを挿入すると、Pu blish erINSERT成功します。
PostgreSQL Enterprise Consortium
Page 205 of 285
(サーバ1において実施)
pubdb=# insert into data1 values (10, 'pub10');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+-------
1 | aaaaa
2 | pub
10 | pub10
の時Sub scrib erではCHECK制約違反による競合が発生し、レプリケーションが停止しす。 Pu b lish erSu b scrib erのログには競合が解消するまで5秒毎に以下
セージが繰り返し出力さます
(サーバ1のサーバログ)
2018-01-10 14:05:32.268 JST [6057] LOG: starting logical decoding for slot "sub1"
2018-01-10 14:05:32.268 JST [6057] DETAIL: streaming transactions committing after 0/55F833E8,
reading WAL from 0/55F833B0
2018-01-10 14:05:32.268 JST [6057] LOG: logical decoding found consistent point at 0/55F833B0
2018-01-10 14:05:32.268 JST [6057] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-01-10 14:05:32.097 JST [6020] LOG: logical replication apply worker for subscription "sub1"
has started
2018-01-10 14:05:32.102 JST [6020] ERROR: new row for relation "data1" violates check constraint
"data1_c1_check"
2018-01-10 14:05:32.102 JST [6020] DETAIL: Failing row contains (10, pub10).
2018-01-10 14:05:32.103 JST [2123] LOG: worker process: logical replication worker for
subscription 16394 (PID 6020) exited with exit code 1
Subscrib erのテーブルdata1CHE CK制約をDRO Pすると競合が解消し、レプリーションが再開されます。 また、Pu b lish erSu bscrib erへのーメッセージも出力さ
れなくります。
(サーバ2において実施)
subdb=# ALTER TABLE data1 DROP CONSTRAINT data1_c1_check;
ALTER TABLE
6.4.5.2.3.
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします。まPu b lish er,Su bscrib erのテーブルdata1はそれぞれ以下のレコード
が存在する状態とします
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+----
Pu blish erでレコードを更新するPu blish erU PDATE成功しますが、Su bscrib erのレコードには変化がありません。また、Pu b lish er,Su b scrib erのログにエラーメ
セージも出力されていません。
PostgreSQL Enterprise Consortium
Page 206 of 285
(サーバ1において実施)
pubdb=# update data1 set c2 = 'pub1a';
UPDATE 1
pubdb=# select * from data1;
c1 | c2
----+-------
1 | pub1a
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+----
キーが一致するレードが存在しない場合の競合は無視され、レプリーションも停止しいことがわかります
6.4.5.2.4.
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします。まPu b lish er,Su bscrib erのテーブルdata1はそれぞれ以下のレコード
が存在する状態とします
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+----
Pu blish erでレコードを削除するPu blish erDELETE成功しますが、Su bscrib erのレコードには変化がありません。また、Pu b lish er,Su bscrib erのログにエラーメ
セージも出力されていません。
(サーバ2において実施)
subdb=# delete from data1 where c1 = 1;
DELETE 1
subdb=# select * from data1;
c1 | c2
----+----
subdb=# select * from data1;
c1 | c2
----+----
キーが一致するレードが存在しない場合の競合は無視され、レプリーションも停止しいことがわかります
6.4.5.2.5.
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします
Subscrib erでテーブルdata1DRO Pした後、Pu b lish erでテーブルdata1レコードを挿入するPu b lish erINSERT功します
PostgreSQL Enterprise Consortium
Page 207 of 285
(サーバ2において実施)
subdb=# DROP TABLE data1;
DROP TABLE
(サーバ1において実施)
pubdb=# insert into data1 values (1, 'pub1');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
の時Sub scrib erではテル不一致にる競合が発生し、レプリケーションが停止します Pu b lish erSub scriberのログ競合が解消るま5秒毎に以下のメ
セージが繰り返し出力さす。
(サーバ1のサーバログ)
2018-01-10 15:09:10.872 JST [6331] LOG: starting logical decoding for slot "sub1"
2018-01-10 15:09:10.872 JST [6331] DETAIL: streaming transactions committing after 0/55F8B9E8,
reading WAL from 0/55F8B9B0
2018-01-10 15:09:10.872 JST [6331] LOG: logical decoding found consistent point at 0/55F8B9B0
2018-01-10 15:09:10.872 JST [6331] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-01-10 15:09:10.700 JST [6297] LOG: logical replication apply worker for subscription "sub1"
has started
2018-01-10 15:09:10.706 JST [6297] ERROR: logical replication target relation "public.data1" does
not exist
2018-01-10 15:09:10.708 JST [2123] LOG: worker process: logical replication worker for
subscription 16394 (PID 6297) exited with exit code 1
Subscrib erでテーブルdata1再作成するとログエラーは出力さなりますが、レプーションは再開されません。
(サーバ2において実施)
subdb=# CREATE TABLE data1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
subdb=# select * from data1;
c1 | c2
----+----
れは、再作成したーブルdata1Su bscrip tio n su b 1からレプリーシン対象として認識さいないためと考えられます
(サーバ2において実施)
subdb=# \dRs+
List of subscriptions
Name | Owner | Enabled | Publication | Synchronous commit | Conninfo
------+----------+---------+-------------+--------------------+------------------------------------
----------------------------
sub1 | postgres | t | {pub1} | off | host=192.168.127.31 dbname=pubdb
user=repusr1 password=repusr1
subdb=# select a3.subname, a2.relname, a1.srsubstate, a1.srsublsn from pg_subscription_rel as a1
left outer join pg_class as a2 on a1.srrelid = a2.oid left outer join pg_stat_subscription as a3 on
a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
---------+------------------+------------+------------
Subscrip tio n su b 1に対しALTER SUBSCRIPTIO N文を実行しsub 1プリーシン対象テーブルを再認識させるテーブd a ta1のレプーションが再開さ
れます。
PostgreSQL Enterprise Consortium
Page 208 of 285
(サーバ2において実施)
subdb=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION;
ALTER SUBSCRIPTION
subdb=# select a3.subname, a2.relname, a1.srsubstate, a1.srsublsn from pg_subscription_rel as a1
left outer join pg_class as a2 on a1.srrelid = a2.oid left outer join pg_stat_subscription as a3 on
a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
---------+------------------+------------+------------
sub1 | data1 | r | 0/55F8C298
6.4.5.2.6.
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします。まSu bscrib erでテーブルdata1c2列をDRO Pます
(サーバ2において実施)
subdb=# ALTER TABLE data1 DROP COLUMN c2;
ALTER TABLE
subdb=# \d+ data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+-------------
c1 | integer | | not null | | plain | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Pu blish erでテーブルdata1対してレコードを挿入すると、Pu b lish erINSERT功します
(サーバ1において実施)
pubdb=# insert into data1 values (1, 'pub1');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
の時Sub scrib erでは列の不一致による競合が発生し、レプリケーションが停止しす。 Pu b lish erSu b scrib erのログには競合が解消するまで5秒毎に以下のメセー
ジが繰り返し出力されます。
(サーバ1のサーバログ)
2018-01-10 15:53:11.464 JST [6480] LOG: starting logical decoding for slot "sub1"
2018-01-10 15:53:11.464 JST [6480] DETAIL: streaming transactions committing after 0/55F900C0,
reading WAL from 0/55F90088
2018-01-10 15:53:11.464 JST [6480] LOG: logical decoding found consistent point at 0/55F90088
2018-01-10 15:53:11.464 JST [6480] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-01-10 15:53:11.284 JST [6472] LOG: logical replication apply worker for subscription "sub1"
has started
2018-01-10 15:53:11.298 JST [6472] ERROR: logical replication target relation "public.data1" is
missing some replicated columns
2018-01-10 15:53:11.299 JST [6420] LOG: worker process: logical replication worker for
subscription 16394 (PID 6472) exited with exit code 1
Subscrib erでテーブルdata1c2列を再度追加るとレプリケーションが再開されます。 またPub lisherSu bscrib erへのーメッセージも出力さなります
PostgreSQL Enterprise Consortium
Page 209 of 285
(サーバ2において実施)
subdb=# ALTER TABLE data1 ADD COLUMN c2 VARCHAR(5);
ALTER TABLE
subdb=# \d+ data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default | Storage | Stats target |
Description
--------+----------------------+-----------+----------+---------+----------+--------------+--------
-----
c1 | integer | | not null | | plain | |
c2 | character varying(5) | | | | extended | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
Subscriber
前述のとおりSub scrib erのテーブルにPu b lish erのテーブルの列が存在しない場合は競合が発生します。 Pub lish erのテーブルに存在しない列がSu b scriberのテー
ブルに存在した場合、以下のとおり競合は発生しません。 このSu b scrib erのテーブルのみに定義さ列にNULLが設定されます
(サーバ1において実施)
pubdb=# \d data1
Table "public.data1"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | integer | | not null |
c2 | character varying(5) | | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Publications:
"pub1"
(サーバ2において実施)
subdb=# ALTER TABLE data1 ADD COLUMN c3 VARCHAR(5); <-- Publisherに存在しc3追加する
ALTER TABLE
subdb=# \d+ data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default | Storage | Stats target |
Description
--------+----------------------+-----------+----------+---------+----------+--------------+--------
-----
c1 | integer | | not null | | plain | |
c2 | character varying(5) | | | | extended | |
c3 | character varying(5) | | | | extended | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
(サーバ1において実施)
pubdb=# insert into data1 values (1, 'pub1');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2 | c3
----+------+------
1 | pub1 | NULL <-- c3(Publisher定義列)にはNULLが格納され
PostgreSQL Enterprise Consortium
Page 210 of 285
6.4.5.2.7.
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします。まSu bscrib erでテーブルdata1c2列を異なるータ型に変更します。
(サーバ2において実施)
subdb=# ALTER TABLE data1 ALTER COLUMN c2 TYPE integer USING c2::integer;
ALTER TABLE
subdb=# \d+ data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+-------------
c1 | integer | | not null | | plain | |
c2 | integer | | | | plain | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
Pu blish erでテーブルdata1対してレコードを挿入すると、Pu b lish erINSERT功します
(サーバ1において実施)
pubdb=# insert into data1 values (1, 'pub1');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
の時Sub scrib erでは型の不一致による競合が発生し、レプリケーションが停止しす。 Pu b lish erSu b scrib erのログには競合が解消するまで5秒毎に以下のメセー
ジが繰り返し出力されます。
(サーバ1のサーバログ)
2018-01-10 16:08:13.308 JST [6602] LOG: starting logical decoding for slot "sub1"
2018-01-10 16:08:13.308 JST [6602] DETAIL: streaming transactions committing after 0/55F943E8,
reading WAL from 0/55F943B0
2018-01-10 16:08:13.308 JST [6602] LOG: logical decoding found consistent point at 0/55F943B0
2018-01-10 16:08:13.308 JST [6602] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-01-10 16:08:13.136 JST [6597] LOG: logical replication apply worker for subscription "sub1"
has started
2018-01-10 16:08:13.142 JST [6597] ERROR: invalid input syntax for integer: "pub1"
2018-01-10 16:08:13.142 JST [6597] CONTEXT: processing remote data for replication target relation
"public.data1" column "c2", remote type character varying
, local type character varying
2018-01-10 16:08:13.143 JST [6420] LOG: worker process: logical replication worker for
subscription 16394 (PID 6597) exited with exit code 1
Subscrib erc2のデータ型を元に戻すとレプリーションが再開されます。 また、Pu b lish erSu bscrib erへのーメッセージも出力さなります
PostgreSQL Enterprise Consortium
Page 211 of 285
(サーバ2において実施)
subdb=# ALTER TABLE data1 ALTER COLUMN c2 TYPE VARCHAR(5);
ALTER TABLE
subdb=# \d+ data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default | Storage | Stats target |
Description
--------+----------------------+-----------+----------+---------+----------+--------------+--------
-----
c1 | integer | | not null | | plain | |
c2 | character varying(5) | | | | extended | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
Pu blish erSu b scriberのテーブルで列のデータ型が相違する場合で暗黙的な変換が可能であれば以下のとおり競合は発生しません。
(サーバ2において実施)
subdb=# ALTER TABLE data1 ALTER COLUMN c2 TYPE date;
ALTER TABLE
subdb=# \d+ data1;
Table "public.data1"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+-------------
c1 | integer | | not null | | plain | |
c2 | date | | | | plain | |
Indexes:
"data1_pkey" PRIMARY KEY, btree (c1)
(サーバ1において実施)
pubdb=# insert into data1 values (1, '2018/1/1');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+----------
1 | 2018/1/1
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------------
1 | 2018-01-01 <-- 暗黙的な型変換が可能なレコードはレプリケーションさ(TEXT -> DATE)
6.4.5.2.8.
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします
Subscrib erでレプーション対象のテーブルdata1を明示的にします
(サーバ2において実施)
subdb=# BEGIN;
BEGIN
subdb=# LOCK TABLE data1 IN EXCLUSIVE MODE;
LOCK TABLE
PostgreSQL Enterprise Consortium
Page 212 of 285
Pu blish erでテーブルdata1対してレコードを挿入すると、Pu b lish erINSERT功しますが、Su b scrib erのテーブルdata1には反映させん。 の時
Pu blish erSu b scrib erのログにはエラーメッセージは出力さおらず、レプリーションがロッ解放を待機した状態となっていす。
(サーバ1において実施)
pubdb=# insert into data1 values (1, 'pub1');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+----
Subscrib erでトランザクションを終了しロック解放すると、レプリケーションが再開さ、データが転送されます。
(サーバ2において実施)
subdb=# COMMIT;
COMMIT
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
6.4.5.2.9.
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします
Subscrib erでテーブルdata1のレードをSELECT F O R U PD ATEで明示的にロッします。
(サーバ2において実施)
subdb=# BEGIN;
BEGIN
subdb=# SELECT * FROM data1 WHERE c1 = 1 FOR UPDATE;
LOCK TABLE
Pu blish erで同一のレコード更新すると、Pu b lish erU PDATEは成功しますが、Su bscrib erのテーブルdata1には反映されません。 の時Pu b lisherSu bscrib er
ログにはエーメッセージは出力さてお、レプリーシンがロッ解放を待機した状態とっています。
(サーバ1において実施)
pubdb=# update data1 SET c2 = 'pub11' where c1 = 1;
UPDATE 1
pubdb=# select * from data1;
c1 | c2
----+-------
1 | pub11
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
PostgreSQL Enterprise Consortium
Page 213 of 285
Subscrib erでトランザクションを終了しロック解放すると、レプリケーションが再開さ、データが転送されます。
(サーバ2において実施)
subdb=# COMMIT;
COMMIT
subdb=# select * from data1;
c1 | c2
----+-------
1 | pub11
6.4.5.3.
ロジカルレプリーションの開始時に実行される初期データ同期処理において更新時と同様の競合が発生する可能があります。以下で初期データ同期時に競合が発
生した時の挙動と競合を解消させるめの方法パターン毎に紹介します。
6.4.5.3.1. /
Pu blish er,Su b scrib erのテーブd ata1にはc1PRIM ARY KEYとし、そぞれ以下のデータが存在する態とします。
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------
2 | pub2
Subscrib erSu b scrip tion su b 1を作成しロジカルレプリケーションを開始します。この時Su b scriberでは主キー違反による合が発生し、レプリケーションが停止しま
す。
(サーバ2において実施)
subdb=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub1;
NOTICE: created replication slot "sub1" on publisher
CREATE SUBSCRIPTION
Pu blish erSu b scrib erのログには競合が解消するまで5秒毎に以下のメッセージが繰り返し出力さます
PostgreSQL Enterprise Consortium
Page 214 of 285
(サーバ1のサーバログ)
2018-01-11 15:53:32.764 JST [10254] LOG: logical decoding found consistent point at 0/55FB4C50
2018-01-11 15:53:32.764 JST [10254] DETAIL: There are no running transactions.
2018-01-11 15:53:32.772 JST [10255] LOG: starting logical decoding for slot "sub1"
2018-01-11 15:53:32.772 JST [10255] DETAIL: streaming transactions committing after 0/55FB4C88,
reading WAL from 0/55FB4C50
2018-01-11 15:53:32.772 JST [10255] LOG: logical decoding found consistent point at 0/55FB4C50
2018-01-11 15:53:32.772 JST [10255] DETAIL: There are no running transactions.
2018-01-11 15:53:32.792 JST [10256] LOG: logical decoding found consistent point at 0/55FB4C88
2018-01-11 15:53:32.792 JST [10256] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-01-11 15:53:32.602 JST [10275] LOG: logical replication apply worker for subscription "sub1"
has started
2018-01-11 15:53:32.608 JST [10276] LOG: logical replication table synchronization worker for
subscription "sub1", table "data1" has started
2018-01-11 15:53:32.630 JST [10276] ERROR: duplicate key value violates unique constraint
"data1_pkey"
2018-01-11 15:53:32.630 JST [10276] DETAIL: Key (c1)=(2) already exists.
2018-01-11 15:53:32.630 JST [10276] CONTEXT: COPY data1, line 2
2018-01-11 15:53:32.631 JST [6420] LOG: worker process: logical replication worker for
subscription 16447 sync 16424 (PID 10276) exited with exit code 1
Subscrib erのテーブルでキーが重複るレードを削除すると競合が解消し、レプリーシンが再開されます またPu b lish erSub scrib erへのエラーメセージも出力
れなくります。
(サーバ2において実施)
subdb=# delete from data1 where c1 = 2;
DELETE 1
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
6.4.5.3.2. CHECK
主キー違/一意キー違反による競合と同じ挙動になる推測さめ割愛しす。
6.4.5.3.3.
初期データ同期では発生しないケースのため割愛します。
6.4.5.3.4.
初期データ同期では発生しないケースのため割愛します。
6.4.5.3.5.
Pu blish er,Su b scrib erのテーブd ata1にはc1PRIM ARY KEYとし、そぞれ以下のデータが存在する態とします。
PostgreSQL Enterprise Consortium
Page 215 of 285
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------
2 | pub2
Subscrib erでテーブルをDRO PしてからSu b scription を作成するとエラーとなりますSu b scrib erのデータベースにーブルが存在しない状態ではSu b scrip tion を作成
できないため、初期データ同期時発生しないケースとなります
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
(サーバ2において実施)
subdb=# drop table data1;
DROP TABLE
subdb=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub1;
ERROR: relation "public.data1" does not exist
6.4.5.3.6.
Pu blish erテーブd ata1を作成し、レコードが3件存在する状態にしますSub scrib er列が少ないテブルdata1を作成します。
(サーバ1において実施)
pubdb=# CREATE TABLE data1 (c1 INT PRIMARY KEY, c2 VARCHAR(5));
CREATE TABLE
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
(サーバ2において実施)
subdb=# CREATE TABLE data1 (c1 INT PRIMARY KEY);
CREATE TABLE
Subscrib erSu b scrip tion su b 1を作成しロジカルレプリケーションを開始します。この時Su b scriberでは列定義の相違による競合が発生しレプリケーシンが停止
します
(サーバ2において実施)
subdb=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub1;
NOTICE: created replication slot "sub1" on publisher
CREATE SUBSCRIPTION
PostgreSQL Enterprise Consortium
Page 216 of 285
Pu blish erSu b scrib erのログには5秒毎に以下のメセージが繰り返し出力さます
(サーバ1のサーバログ)
2018-01-11 16:04:15.836 JST [10365] LOG: starting logical decoding for slot "sub1"
2018-01-11 16:04:15.836 JST [10365] DETAIL: streaming transactions committing after 0/55FB5AC0,
reading WAL from 0/55FB5A88
2018-01-11 16:04:15.836 JST [10365] LOG: logical decoding found consistent point at 0/55FB5A88
2018-01-11 16:04:15.836 JST [10365] DETAIL: There are no running transactions.
2018-01-11 16:04:15.849 JST [10366] LOG: logical decoding found consistent point at 0/55FB5AC0
2018-01-11 16:04:15.849 JST [10366] DETAIL: There are no running transactions.
(サーバ2のサーバログ)
2018-01-11 16:04:15.666 JST [10385] LOG: logical replication apply worker for subscription "sub1"
has started
2018-01-11 16:04:15.673 JST [10386] LOG: logical replication table synchronization worker for
subscription "sub1", table "data1" has started
2018-01-11 16:04:15.686 JST [10386] ERROR: logical replication target relation "public.data1" is
missing some replicated columns
2018-01-11 16:04:15.688 JST [6420] LOG: worker process: logical replication worker for
subscription 16454 sync 16449 (PID 10386) exited with exit code 1
Subscrib erでテーブルdata1参照しても、初期データ同期さいません。
(サーバ2において実施)
subdb=# select * from data1;
c1
----
更新時の競合発生と同じくSu b scrib erでテーブルd ata 1c2列を追加するとレプリーシンが再開さます
6.4.5.3.7.
一部の列が存在しないパターンと同じ挙動になると推測されるため割愛します。
6.4.5.3.8.
Pu blish er,Su b scrib erのテーブd ata1にはそれぞれ以下のデータが存在する状態とします
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+----
Subscrib erでテーブルdata1LO CK TAB LE IN EXCLU SIVE M O DEで明示的にロックします。
PostgreSQL Enterprise Consortium
Page 217 of 285
(サーバ2において実施)
subdb=# BEGIN;
BEGIN
subdb=# LOCK TABLE data1 IN EXCLUSIVE MODE;
LOCK TABLE
Subscrib erで上記のトンザクションを実行したまま、別のコンソールでSu b scription を作成します。の時レプリーションはロッを待機するめ、テーブルdata1には初
期データが同期さいないことがわかります。
(サーバ2において実施)
subdb=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.127.31 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub1;
NOTICE: created replication slot "sub1" on publisher
CREATE SUBSCRIPTION
subdb=# select * from data1;
c1 | c2
----+----
Subscrib erでトランザクションを終了するとロッが解放さレプリケーションの初期データ同期が開始されます
(サーバ2において実施)
subdb=# COMMIT;
COMMIT
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
6.4.5.3.9.
初期データ同期では発生しないケースのため割愛します。
6.4.5.4. WAL
前述の様Su b scrib erで競合の原因となる要素を取り除方法とは別に競合が発生W ALSu bscrib erへの適用をスプする方法について下に紹介します
ーブルdata1のデータPu blish er,Su b scrib er間でレプリケーシンされいる状態とします。ま、テーブルd ata1レコード5件存在し、Pu b lish erW ALLSN
0/55FB 6948となっています
PostgreSQL Enterprise Consortium
Page 218 of 285
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
pubdb=# SELECT pg_current_wal_lsn() ;
pg_current_wal_lsn
--------------------
0/55FB6948
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
subdb=# SELECT oid, subname FROM pg_subscription ;
oid | subname
-------+---------
16463 | sub1
subdb=# SELECT * FROM pg_replication_origin_status;
local_id | external_id | remote_lsn | local_lsn
----------+-------------+------------+------------
1 | pg_16463 | 0/55FB6948 | 0/7360A120
Subscrib erでテーブルdata16件目のレコードを挿入した後、Pu b lish erで同一キーのレコード挿入し競合を発生させます
(サーバ2において実施)
subdb=# insert into data1 values (6, 'sub6');
INSERT 0 1
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
6 | sub6
(サーバ1において実施)
pubdb=# insert into data1 values (6, 'pub6');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
6 | pub6
競合が発生していめ、Pu b lish erLSNSu b scriberLSN(remote_lsn)が到達しいませ
PostgreSQL Enterprise Consortium
Page 219 of 285
(サーバ1において実施)
pubdb=# SELECT pg_current_wal_lsn() ;
pg_current_wal_lsn
--------------------
0/55FB6DB0
SUBSCRIPTION側てremote_lsnを確認
(サーバ2において実施)
subdb=# SELECT * FROM pg_replication_origin_status;
local_id | external_id | remote_lsn | local_lsn
----------+-------------+------------+------------
1 | pg_16463 | 0/55FB6910 | 0/7360A120
Subscrib erpg _replication _orig in _adva n ce関数を実行しLSNを進めることで競合が発生しているW ALをスキップせます。の時点でSu b scrib erのサーログ
レプリケーションが停止した際のエラーメッセージが出力さります。
(サーバ2において実施)
subdb=# SELECT pg_replication_origin_advance ('pg_16463', '0/55FB6DB0');
pg_replication_origin_advance
-------------------------------
Subscrib erLSN再度確認するとPu blish erLSNと一致していとがわかります。な競合発生直前に挿入したレコード(c1=6, c2= sub 6)そのまま残さ
ます
(サーバ2において実施)
subdb=# SELECT * FROM pg_replication_origin_status;
local_id | external_id | remote_lsn | local_lsn
----------+-------------+------------+------------
1 | pg_16463 | 0/55FB6DB0 | 0/7360A120
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
6 | sub6
の状態でPublish er新しいレコードを挿入すると、Su b scrib erc1=6レコード残されたままレプリーシンは再開れており、Pu b lish erでレコード
(c1=6,c2= pu b 6)を挿入したW ALのみがスプされとがわかります
PostgreSQL Enterprise Consortium
Page 220 of 285
(サーバ1において実施)
pubdb=# insert into data1 values (7, 'pub7');
INSERT 0 1
pubdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
6 | pub6
7 | pub7
(サーバ2において実施)
subdb=# select * from data1;
c1 | c2
----+------
1 | pub1
2 | pub2
3 | pub3
4 | pub4
5 | pub5
6 | sub6
7 | pub7
6.4.6.
では、ロジカルレプリーションとストリーミングレプリーションを併用する環境を想定し、以下の観点を確認します
ーミングレプーションを併用する境の構築手順
ーミングレプーションを併用する境で障害が発生し場合の運用手
6.4.6.1.
本章は以下の環境を利用した検証結果を元に解説します。
Po stg reSQ Lサーバは3構成
ロジカルレプリーションはPu b lish er1台(ーバ1IPアドレス 19216812731Sub scrib er1サーバ2IPアドレス 19216812732で構成
PostgreSQL Enterprise Consortium
Page 221 of 285
ーミングレプーションは、マスタ1台(Pu b lish erと同一)スタンバ1台(サーバ3IPアドレス 19216812733で構
ロジカルレプリーションのPu blish erでは、データベー内に2のデータベースを作成
pu b d b: レプリーシン対象のテーブルを個別定義するPu b licatio n を作成
pu b d b_all_tab le: デーベース内に存在する全テーブルをレプリケーション対象とするPu b lication を作成
ロジカルレプリーションのSubscrib erでは、データベースクラスタ内2のデータベースを作成
sub d b: Pu b lish erpu b d b デーベースに定義しPub licatio n から更データを受け取るSu b scrip tion を作成
sub d b_all_table: Pu b lish erpu b d b_all_tab leデータース定義したPu b lication から変更デー受け取Sub scrip tionを作成
6.4.6.2.
既にロジカルプリーシンが稼働している環境に対しトリーミングレプリーシンを働させる手順、新規でストリーミングレプリケーションを稼働させる手順と変
ません。(後で「SR環境の設定手順」への相互参照リンクを貼る)の手順にしたがってストリーミングレプリケーシンのマ、スレーブを構築して下さい。
6.4.6.3.
Pu blish erデータースpu b db pu bd b _all_tableが存在します。また、pu b d bデータースpu b d b _all_tableデータベースには、Pu b lication がそれぞれ21
存在します。
(サーバ1において実施)
pubdb=# \dRp+
Publication pub1
-[ RECORD 1 ]-------
Owner | pubusr1
All tables | f
Inserts | t
Updates | t
Deletes | t
Tables:
"public.data1"
"public.data1_1"
Publication pub2
-[ RECORD 1 ]-------
Owner | pubusr1
All tables | f
Inserts | t
Updates | t
Deletes | t
Tables:
"public.data2"
pubdb_all_table=# \dRp+
Publication pub_all_table
-[ RECORD 1 ]--------
Owner | postgres
All tables | t
Inserts | t
Updates | t
Deletes | t
ロジカルレプリーションのPu blish erとストリーミングレプリーシンのマスタを兼ねるサーバ1の動的統計情報ビューpg _stat_replication 、ロジカルレプリケーシンの
情報(R E CO R D 13)、スングレプリーションの情報(RECO R D 4)が確認できます。
(サーバ1において実施)
pubdb=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 2054
usesysid | 16385
usename | repusr1
application_name | sub_all_table
client_addr | 192.168.127.32
client_hostname |
PostgreSQL Enterprise Consortium
Page 222 of 285
client_port | 46604
backend_start | 2018-02-08 13:42:42.520503+09
backend_xmin |
state | streaming
sent_lsn | 0/580126B0
write_lsn | 0/580126B0
flush_lsn | 0/580126B0
replay_lsn | 0/580126B0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 2 ]----+------------------------------
pid | 1948
usesysid | 16385
usename | repusr1
application_name | sub2
client_addr | 192.168.127.32
client_hostname |
client_port | 46526
backend_start | 2018-02-08 13:36:25.199985+09
backend_xmin |
state | streaming
sent_lsn | 0/580126B0
write_lsn | 0/580126B0
flush_lsn | 0/580126B0
replay_lsn | 0/580126B0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 3 ]----+------------------------------
pid | 1850
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 46524
backend_start | 2018-02-08 13:15:08.479523+09
backend_xmin |
state | streaming
sent_lsn | 0/580126B0
write_lsn | 0/580126B0
flush_lsn | 0/580126B0
replay_lsn | 0/580126B0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 4 ]----+------------------------------
pid | 1846
usesysid | 16385
usename | repusr1
application_name | nk_PGECons3
client_addr | 192.168.127.33
client_hostname |
client_port | 55520
backend_start | 2018-02-08 13:14:36.673678+09
backend_xmin |
state | streaming
sent_lsn | 0/580126B0
write_lsn | 0/580126B0
flush_lsn | 0/580126B0
PostgreSQL Enterprise Consortium
Page 223 of 285
replay_lsn | 0/580126B0
write_lag | 00:00:00.00054
flush_lag | 00:00:00.000541
replay_lag | 00:00:00.000541
sync_priority | 0
sync_state | async
サーバ1のシムカログpg _replication _slotsでは、ロジカルレプリケーシンのSu b scrip tion 合わせ動作成さたレプリーシンストの情報が確認できま
す。
(サーバ1において実施)
pubdb=# select * from pg_replication_slots;
-[ RECORD 1 ]-------+----------------
slot_name | sub2
plugin | pgoutput
slot_type | logical
datoid | 16384
database | pubdb
temporary | f
active | t
active_pid | 1948
xmin |
catalog_xmin | 701
restart_lsn | 0/58017AA8
confirmed_flush_lsn | 0/58017AE0
-[ RECORD 2 ]-------+----------------
slot_name | sub1
plugin | pgoutput
slot_type | logical
datoid | 16384
database | pubdb
temporary | f
active | t
active_pid | 1850
xmin |
catalog_xmin | 701
restart_lsn | 0/58017AA8
confirmed_flush_lsn | 0/58017AE0
-[ RECORD 3 ]-------+----------------
slot_name | sub_all_table
plugin | pgoutput
slot_type | logical
datoid | 16474
database | pubdb_all_table
temporary | f
active | t
active_pid | 2054
xmin |
catalog_xmin | 701
restart_lsn | 0/58017AA8
confirmed_flush_lsn | 0/58017AE0
pu b d bデータベースpu bd b _all_tableデータベースそれぞれのd ata1ーブルにはあらかじめ1データINSERTしておきます
(サーバ1において実施)
pubdb=# select * from data1;
c1 | c2
----+-------
1 | pub1
pubdb_all_table=# select * from data1;
c1 | c2
----+------
1 | pub1
Subscrib ersubd b データベーsu b d b_all_tab leデータベースSu b scription がそれぞ21存在します。
PostgreSQL Enterprise Consortium
Page 224 of 285
(サーバ2において実施)
subdb=# \dRs+
List of subscriptions
Name | Owner | Enabled | Publication | Synchronous commit | Conninfo
------+----------+---------+-------------+--------------------+------------------------------------
----------------------------
sub1 | postgres | t | {pub1} | off | host=192.168.127.31 dbname=pubdb
user=repusr1 password=repusr1
sub2 | postgres | t | {pub2} | off | host=192.168.127.31 dbname=pubdb
user=repusr1 password=repusr1
subdb_all_table=# \dRs+
List of subscriptions
Name | Owner | Enabled | Publication | Synchronous commit |
Conninfo
---------------+----------+---------+-----------------+--------------------+-----------------------
---------------------------------------------------
sub_all_table | postgres | t | {pub_all_table} | off | host=192.168.127.31
dbname=pubdb_all_table user=repusr1 password=repusr1
ロジカルレプリーションのSubscrib erであるサーバ2の動的統計情報ビューp g_stat_su b scrip tion は、ロジカルレプリケーションの情報が3件確認できます。
(サーバ2において実施)
subdb_all_table=# select * from pg_stat_subscription;
subid | subname | pid | relid | received_lsn | last_msg_send_time |
last_msg_receipt_time | latest_end_lsn | latest_end_time
-------+---------------+-------+-------+--------------+-------------------------------+------------
-------------------+----------------+-------------------------------
16463 | sub1 | 11038 | | 0/58011F60 | 2018-02-08 13:42:47.590367+09 | 2018-02-08
13:42:47.423435+09 | 0/58011F60 | 2018-02-08 13:42:47.590367+09
24677 | sub2 | 11072 | | 0/58011F60 | 2018-02-08 13:42:47.59058+09 | 2018-02-08
13:42:47.42367+09 | 0/58011F60 | 2018-02-08 13:42:47.59058+09
24678 | sub_all_table | 11158 | | 0/58011F60 | 2018-02-08 13:42:47.590534+09 | 2018-02-08
13:42:47.423605+09 | 0/58011F60 | 2018-02-08 13:42:47.590534+09
ーミングレプーションのスレーブであるサーバ3では動的統計情報ビューpg_stat_w al_receiverでストリーミングレプリーションの情報が確認できます。
(サーバ3において実施)
pubdb=# select * from pg_stat_wal_receiver;
-[ RECORD 1 ]---------+----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-------------------------------------------------
pid | 26152
status | streaming
receive_start_lsn | 0/58000000
receive_start_tli | 1
received_lsn | 0/58016A78
received_tli | 1
last_msg_send_time | 2018-02-08 13:52:22.063552+09
last_msg_receipt_time | 2018-02-08 13:52:21.953994+09
latest_end_lsn | 0/58016A78
latest_end_time | 2018-02-08 13:52:22.063552+09
slot_name |
conninfo | user=repusr1 password=******** dbname=replication host=192.168.127.31
port=5432 application_name=nk_PGECons3 fallback_application_name=walreceiver sslmode=prefer
sslcompression=1 krbsrvname=postgres target_session_attrs=any
また、サーバ3はマであるサーバ1で定義されいるPu b lication がスングレプリーションで複製れています。
PostgreSQL Enterprise Consortium
Page 225 of 285
(サーバ3において実施)
pubdb=# \dRp+
Publication pub1
-[ RECORD 1 ]-------
Owner | pubusr1
All tables | f
Inserts | t
Updates | t
Deletes | t
Tables:
"public.data1"
"public.data1_1"
Publication pub2
-[ RECORD 1 ]-------
Owner | pubusr1
All tables | f
Inserts | t
Updates | t
Deletes | t
Tables:
"public.data2"
pubdb_all_table=# \dRp+
Publication pub_all_table
-[ RECORD 1 ]--------
Owner | postgres
All tables | t
Inserts | t
Updates | t
Deletes | t
し、サーバ3ーバ2とのロジカルレプリーシンは立していないためサーバ3動的統計情報ビューpg _stat_replication ,pg_replication _slotsを見て
サーバ1と同じ情報は存在しません。
(サーバ3において実施)
pubdb_all_table=# select * from pg_replication_slots;
(0 rows)
pubdb_all_table=# select * from pg_stat_replication;
(0 rows)
グレ
初期状態の構成でストリーミングレプリーシンのマスタに障害が発生し状態を想定し、昇格したスレブへロジカルレプリケーションを切り替える手順を説明します。切
替後の環境は以下の様にります
PostgreSQL Enterprise Consortium
Page 226 of 285
まず、スーミングレプリケーシンのマスタ(サー1)PostgreSQ Lサーを強制終了しす。
(サーバ1において実施)
-bash-4.2$ pg_ctl -m f stop
サーバ停止処理の完了を待っています....
サーバは停止しした
ーミングレプーションのスレーブ(サーバ3)p g _ctl p romoteマンドを実行しマス昇格します
(サーバ3において実施)
-bash-4.2$ pg_ctl promote
waiting for server to promote....完了
server promoted
サーバ3のロでマスして接続を受け付け始めことが確認でき、ストリーミングレプリケーシンのマスタ切替は完了します。
(サーバ3のサーバログ)
2018-02-08 15:16:34.693 JST [26148] LOG: received promote request
2018-02-08 15:16:34.693 JST [26148] LOG: redo done at 0/58020F38
2018-02-08 15:16:34.693 JST [26148] LOG: last completed transaction was at log time 2018-02-08
14:24:19.546571+09
2018-02-08 15:16:34.694 JST [26148] LOG: selected new timeline ID: 2
2018-02-08 15:16:34.734 JST [26148] LOG: archive recovery complete
2018-02-08 15:16:34.738 JST [26146] LOG: database system is ready to accept connections
次に、サーバ3を新たなPu b lish erとしたロジカルレプーションを開始させてみます
まず、サーバ2ALTER SU B SCR IPTIO N文を実行して既存のSub scrip tion 接続先を変更してした
(サーバ2において実施)
subdb=# ALTER SUBSCRIPTION sub1 CONNECTION 'host=192.168.127.33 dbname=pubdb user=repusr1
password=repusr1';
ALTER SUBSCRIPTION
Subscrib erのログをとサー3にレプリーションスロッ su b 1 が存在しないことが原因で失敗しています
PostgreSQL Enterprise Consortium
Page 227 of 285
(サーバ2のサーバログ)
2018-02-08 15:27:04.296 JST [11029] LOG: worker process: logical replication worker for
subscription 24678 (PID 12728) exited with exit code 1
2018-02-08 15:27:04.299 JST [12729] LOG: logical replication apply worker for subscription "sub1"
has started
2018-02-08 15:27:04.302 JST [12729] ERROR: could not start WAL streaming: ERROR: replication slot
"sub1" does not exist
また、既存のSu b scription を再作成しようとしても、レプリーシンスロット sub 1 が存在しないことで削除拒否さます
(サーバ2において実施)
subdb=# DROP SUBSCRIPTION sub1;
ERROR: could not drop the replication slot "sub1" on publisher
DETAIL: The error was: ERROR: replication slot "sub1" does not exist
Subscrip tio n D R O P時にレプリケーションスロッ合わせDRO Pようとしす。今回の様にプリーションスロットが存在しSub scrip tion が残存る場合は
Subscrip tio n を一時停止(D ISABLE)し、レプリケーションスロットとの対応を無効化(slot_n ame = NO NE)してからDRO Pる必要がありす。
(サーバ2において実施)
subdb=# ALTER SUBSCRIPTION sub1 DISABLE;
ALTER SUBSCRIPTION
subdb=# ALTER SUBSCRIPTION sub1 SET (slot_name = NONE);
ALTER SUBSCRIPTION
subdb=# DROP SUBSCRIPTION sub1;
DROP SUBSCRIPTION
subdb_all_table=# ALTER SUBSCRIPTION sub_all_table DISABLE;
ALTER SUBSCRIPTION
subdb_all_table=# ALTER SUBSCRIPTION sub_all_table SET (slot_name = NONE);
ALTER SUBSCRIPTION
subdb_all_table=# DROP SUBSCRIPTION sub_all_table;
DROP SUBSCRIPTION
Subscrip tio n DRO Pした後、新たSu b scrip tion を作り直すと、LR が開始れます。
(サーバ2において実施)
subdb=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.127.33 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub1 WITH (copy_data = false);
NOTICE: created replication slot "sub1" on publisher
CREATE SUBSCRIPTION
subdb=# CREATE SUBSCRIPTION sub2 CONNECTION 'host=192.168.127.33 dbname=pubdb user=repusr1
password=repusr1' PUBLICATION pub2 WITH (copy_data = false);
NOTICE: created replication slot "sub2" on publisher
CREATE SUBSCRIPTION
(サーバ2のサーバログ)
2018-02-08 15:53:08.879 JST [13210] LOG: logical replication apply worker for subscription "sub1"
has started
2018-02-08 15:57:37.386 JST [13231] LOG: logical replication apply worker for subscription "sub2"
has started
2018-02-08 15:57:37.393 JST [13232] LOG: logical replication table synchronization worker for
subscription "sub2", table "data2" has started
2018-02-08 15:57:37.405 JST [13232] LOG: logical replication table synchronization worker for
subscription "sub2", table "data2" has finished
お、CREATE SUB SCR IPTIO N文にW ITH (copy_d ata = false)を付与すると、ロジカルレプリーシン開始時の初期データコピーがスプされます。試しにW ITH
(co p y_d ata = false) 付けずに実行すると、初期データのコピー時に残存するータとキー重複起こし、ロジカルプリーシンが開始されません。
PostgreSQL Enterprise Consortium
Page 228 of 285
(サーバ2において実施)
subdb_all_table=# CREATE SUBSCRIPTION sub_all_table CONNECTION 'host=192.168.127.33
dbname=pubdb_all_table user=repusr1 password=repusr1' PUBLICATION pub_all_table;
NOTICE: created replication slot "sub_all_table" on publisher
CREATE SUBSCRIPTION
(サーバ2のサーバログ)
2018-02-08 16:00:04.913 JST [13245] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data1" has started
2018-02-08 16:00:04.923 JST [13246] LOG: logical replication table synchronization worker for
subscription "sub_all_table", table "data2" has started
2018-02-08 16:00:04.928 JST [13245] ERROR: duplicate key value violates unique constraint
"data1_pkey"
2018-02-08 16:00:04.928 JST [13245] DETAIL: Key (c1)=(1) already exists.
2018-02-08 16:00:04.928 JST [13245] CONTEXT: COPY data1, line 1
2018-02-08 16:00:04.929 JST [11029] LOG: worker process: logical replication worker for
subscription 24685 sync 16479 (PID 13245) exited with exit code 1
2018-02-08 16:00:04.939 JST [13246] ERROR: duplicate key value violates unique constraint
"data2_pkey"
2018-02-08 16:00:04.939 JST [13246] DETAIL: Key (c1)=(1) already exists.
2018-02-08 16:00:04.939 JST [13246] CONTEXT: COPY data2, line 1
SRの新マスとなったサーバ3の動的統計情報ビューpg _stat_replication を確認すると、サーバ3サーバ2のロジカルレプリケーションが確立していることがわかります。
PostgreSQL Enterprise Consortium
Page 229 of 285
(サーバ3において実施)
pubdb_all_table=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 26661
usesysid | 16385
usename | repusr1
application_name | sub_all_table
client_addr | 192.168.127.32
client_hostname |
client_port | 53059
backend_start | 2018-02-08 16:07:25.52522+09
backend_xmin |
state | catchup
sent_lsn | 0/58022DA0
write_lsn | 0/58022DA0
flush_lsn | 0/58022DA0
replay_lsn | 0/58022DA0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 2 ]----+------------------------------
pid | 26503
usesysid | 16385
usename | repusr1
application_name | sub2
client_addr | 192.168.127.32
client_hostname |
client_port | 52951
backend_start | 2018-02-08 15:57:37.444994+09
backend_xmin |
state | streaming
sent_lsn | 0/58022DA0
write_lsn | 0/58022DA0
flush_lsn | 0/58022DA0
replay_lsn | 0/58022DA0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 3 ]----+------------------------------
pid | 26486
usesysid | 16385
usename | repusr1
application_name | sub1
client_addr | 192.168.127.32
client_hostname |
client_port | 52949
backend_start | 2018-02-08 15:53:08.937385+09
backend_xmin |
state | streaming
sent_lsn | 0/58022DA0
write_lsn | 0/58022DA0
flush_lsn | 0/58022DA0
replay_lsn | 0/58022DA0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
6.4.6.4.
ロジカルレプリーションとストリーミングレプリケーションを併用する場合、更新対象を一元化しデータの整合性を担保しすくるため、ストリーミングレプリケーションのマス
PostgreSQL Enterprise Consortium
Page 230 of 285
とロジカルレプリケーションのPu blish erは同じサーバにした方がよいと考えます。
の場合、スングレプリーションのマスがスレーブに切り替わってもPu blica tion を再定義する必要はありません。
一方でSu b scrip tion は再作成が必要で、古いSub scriptio n はレプーションスロッとの対応を無効化してから削除する必要があります また新たSu b scrib er
作成する際は以下のいずれかの方法が選択できます
CREATE SUB SCR IPTIO N文にW ITH (copy_data = false)を付けて初期データピーを回避する
Subscrib erのテーブルをあらかじめTRU NCATE TAB LEで空にしてからCREATE SU B SCR IPTIO N実行し初期データコピーやり直す。
前者は初期データピーの処理が不要でロジカルプリーションを再開するまでの時間を短縮できますが、マスタの切替えからSu b scription 再作成までに発生する
新を複製できないデメリッがありますので、運用形態によって選択する要がありそうです。
6.5. まと
本章ではまずPostgreSQ Lのロジカルレプリケーションの特徴、アキテャ、ユースケース、制限事項を整理し、実際の構築例を交えてロジカルレプーションを設定す
る具体的な手順を説明しました。ストリーミングレプリーシンではマスのベースバッアップからデータベースク単位で一致るスレーブを作成しのに対し、ロジカル
レプーションではPu b lication /Su b scrip tion といっブジによって、テブル単位や更新種別単位での柔軟な複製形態でのレプリーシンを構成できることが
わかりました。
また、実行時パラータいて稼働するプロセス数との関係を検証した結果を踏ま妥当な値を算出する方法を提示しした。アーキテクチャがストリーミングレプ
ーションと共通な部分があるため一部の実行時パラメータはストリーミングレプリーシンで使用するプロセス数を考慮した設定が必要であとがわかりました
次に同期レプリーション、複数Sub scrip tion のレプリケーション、カスケード構成といった応用的な使い方を検証し、ロジカルプリーションでもスーミングレプリケー
ションと同様の構成がとれとが確認できましたまた、パーティショニングを組み合わせることで複数サーバのデータ1のサー集約するデータ統合の用途にも応用で
きるが確認できました
にロジカルレプリーションを実際に運用するシーンを想定し、監視方法や障害発生時の挙動、レプーション開始後のーブル追加、定義変更の手順について検
証しました。スーミングレプリケーシンと違いロジカルプリションではSubscrib er更新でる代わりに整合性をユーザが担保しなければなないため、更新時の競
合が発生した場合ユーザ側で検知、解消する必要があります。ただし、現状では競合が発生した際の対応方法は限られており運用も容易ではないため、基本的に
競合が発生しい設計、運用を心がけるべきです。つまり、Su b scrib er検索用のインデッスを与する度に留めてデータの更新は行わないのが望ましいと考えま
す。また、スングレプリーションとロジカルレプリケーションを併用する環境での障害を想定した検証では、Su bscrip tio n を新しいPu b lication ぎ直してロジカ
ルレプリケーションを再開するまでの具体的な手順を確認できました。
ロジカルレプリーションは、アーキテクチャの面でストリーミングレプリーションと共通する分がありますが、データベースクラスタ単位で複製さストリーミングレプリケーショ
ンよりも柔軟にテーブル単位、更新種別単位で複製でるより、レプーションの活用範囲が広がったといえます。その一方で、運用面ではロジカルレプリーションの
対象とならい操作やオブジェクトが存在するとや、更新時の競合が発生し時の運用が全てユーザに任さいる点など現状では制約事項も多く、運用面の負荷が
軽減さ機能強化が今後求めらます
PostgreSQL Enterprise Consortium
Page 231 of 285
7. Bi-Directional Replication (BDR)
7.1. じめに
7.1.1. BDR
7.1.1.1. BDR
B D R (B i-D irection al Replication )2n dQ u a d ran t社によって開発さオープンソースPo stgreSQ L Licen se)のルチマスレプーションシステです。
方向の非同期論理レプリーションを使用し、地理的に分散しクラスタで使用するめに設計さていす。
マルチマスタにいて
一般的なRDB M Sの冗長化構成(マスタスレーブ構成)おいては、更新処理実行可能なサーバをマスタと呼称します マルチマスとは、同一のデータを保持している
複数のD B 間(クラスタ)おいて 更新処理を実施可能なサーバが複数台存在する構成を指します。 BD R 双方向にレプリーションを実施するとで、複数のサー
への更新可能にしています。
7.1.1.2.
B D R 以下のなケースで有用です。
1. 遠隔地や高レイテンシ環境でクスタを構成してい場合。
2. 各ノードが書き込み処理を実施する場合。
3. 間でデータが非同期であること許容でる場合。
例としては以下のようスポンスを向上させるめに各地でアプリーション及びDB を動作させるようなケースが考えらます
7.1 B D Rユースケー
7.1.1.3.
B D R では「Lo gical Decodin g より、W ALから論理的変更点を抽出し 各ノードで適用することで双方向レプリーションを実現しています。 Lo g ical Decodin g
及びW ALの送受信バッグラウンドワーカープロセスが実施します
従来のトーを用いた双方向レプリケーシンの場合、 下図のよう書き込みが余分に発生(変更記録、変更反映)してしまいます
7.2 トリガベーカニズム
一方、BD R 余分な書き込みが発生せずパフォーマンス的に有利となっていす。
7.3 B D Rカニズム
利用さいるPo stg reSQ Lメカニズムの一覧で
PostgreSQL Enterprise Consortium
Page 232 of 285
7.1 利用メニズムの一覧
No.
1 Event Trig gers 一つのテーブルに接続さDMLイベントのみを補足する通常のトとは異なり、特定データベースのDDLイベント
捉可能。
2 Lo gical Decodin g SQ Lを介して実行さ更新処理を外部コンシューマへストリーミングするための機能。更新結果はロジカルレプリケー
ションスロットで識別れ、ストリームに送出さ
3 Rep lica tion Slots マスのデータースの変更をスレーブ側に同じ順序で適用するめの機能。
4 Backgro u n d W orkers ユーザ提供のコード別プロセスで実行するように拡張る機能。Backgro u n d W o rk erプロセスはp o stg resプロセス
よって起動、終了、監視さる。
5 Co mmit Timestamps ンザクションがいつされかを確認するめの機能。
6 Rep lica tion O rig in s レプーションの進行状況を追跡するめの機能。双方向レプーションにループの防止などが可能。
7 DDL even t captu re 実行されるDDLンドを返す機能。
8 generic W AL messag es for
lo g ical d ecod ing
キストあるいはバイナリのメセージをW AL挿入できる仕組みAPILogical Decod ing 能にって読み出さ
ることを想定してい
7.1.1.4.
マルチマスタ構成取る場合、各ノードが持つ情報に不整合が発生しいように管理る仕組みが必要となります。 BDR 結果整合性eventually con sisten t
呼ばれる一貫性モデルを採用し、整合性を確保します
デフォルトでは競合が発生した場合、最後の更新処理が適用されます。last_up date_w ins
競合結果ーブル「b d r.bdr_co n flict_histo ryで確認可能です。
7.4 結果整合
7.1.1.5.
B D R では一意な値を払い出すためにグローバルシーケンス ップ/オフセットシーケンス」という2の手法紹介しています
1. ローバルシーケンス
ローバルシーケンスでは、各ノードに予め値の塊(ch u n kを一定数ずつ割り振ることで値の重複を回避しています
ch u n kを消費するvo ting処理下記参照)を行い、新たch u n k を割り振ります
ローバルシーケンスは廃止予定です。(下記のステッ/オフセットシーケンスを奨)
voting処理
"ch u n k"と呼ばれるシーケンス番号のまとまりをノードに割り当てる処理をvo tin g 処理と呼びます "ch u n k"が複数のノードに割り当ていことを確認するめ、ノード
間で投票処理が行われており、正常に機能させるめには奇数台のノードが必要です。 過半数のノードが停止している場合は、票処理に過半数に到達しななる
め、新しい"ch u n k "がノードにり当てれません。 そして、"ch u n k "が枯渇した場合、n extval実行に失敗してしまいます
7.5 ローバルシーケンス
2. テッ/オフセットシーケンス
テッ/オフセットシーケンスでは、各ノードで通常Postg reSQ Lシーケンスを使用します 各シーケンスを同じ量だけ増分されるようにし、値が重複し
いよう設定します。
PostgreSQL Enterprise Consortium
Page 233 of 285
設計時には注意が必要です。
増分する値をある程度大きく取らないとノードの追加に対応できません。(例 10の増分であれノード数の追加10台まで)
7.6 テッ/オフセットシーケンス
7.1.1.6.
類似機能及び製品との机上比較の結果です。
7.2 類似機能及び製品との机上比較
No. BDR SR(Hot Standby) Slo ny
1 チマスタ × × ×
2 選択的レプーショ ×
3 競合検知 × ×
4 カスーディング ×
5 W ALベースレプーショ ×
6 DDLレプリーショ × ×
7 自動レプリカ新テーブル × ×
8 シーケンスレプリーシ ×
9 リキー更新 ×
10 同期コット ×
11 外部デーン不使用 ×
12 レプカへの書き込み ×
h ttps://2n d q u adran t.co m/en/resou rces/bdr/
7.1.1.7.
サポートいて以下が存在します
7.3 サポート
No.
1 無償サポート B D R ュニティへのメール、B D RG o o g leループが存在。
email: b d r-list@ 2nd Q u adran t.co m
Go og leグループ: h ttp s://g ro u p s.g o o g le.co m/a/2n d Q u adra n t.co m/foru m/#!fo rum/bd r-list
2 有償サポート 2n d Q u ad ran t社によるサポートを受けることが可能です。
2n d Q u ad ran t社につい
B D R の製造元で、Po stgreSQ Lの専門家(ー等)が多数在籍する業です。
Po stg reSQ Lのコンサルティングービス等を提供しています
h ttps://2n d q u adran t.co m/en/
7.2. 調査、検証の目的
机上の情報整理および検証にいて、以下を主な目的としています。
情報整理
B D R を使用したマルチマスタ環境を構築、運用するあたり、各種機能やパラータの理解に必要な情報の提供
検証
B D R の動作(合時等)や障害発生時の対処法を調査
更新性能の検証
PostgreSQL Enterprise Consortium
Page 234 of 285
7.3. 調査、検証の前提
7.4 調査、検証の前提
Po stg reSQ Lバージョン 9.4.10
調査時点でB D R 9.6に対応していなかった
B D R バージョン 1.0.2
ソースード:h ttps://g ith u b .co m/2n d Q u ad ran t/b d r
O S Cen tO S 7.1
構成 2ノード構
ダウンロードモジュールは以下になります
po stg resq l-b d r94-bdr.x86_64 0:1.0.2-1_2n d Q uad ran t.el7.cen tos
po stg resq l-b d r94.x86_64 0:9.4.10_bdr1-1_2n d Q u adran t.el7.centos
po stg resq l-b d r94-con trib.x86_64 0:9.4.10_bdr1-1_2ndQ uadran t.el7.cento s
po stg resq l-b d r94-lib s.x86_64 0:9.4.10_bdr1-1_2ndQ uadran t.el7.centos
po stg resq l-b d r94-server.x86_64 0:9.4.10_bdr1-1_2ndQ uadran t.el7.centos
以下は構成図になります。
7.7 調査、検証環境構成図
7.4. BDR環境構築時の設定と設定手順
7.4.1. BDR
7.4.1.1.
Po stg reSQ L B D R (B i-Directio n al Replication )利用しルチマス環境の構築手順にいて確認します。
また、マルチマス環境構築後、各ノードにして更新が実行可能か確認します
h ttp://b dr-pro ject.o rg/d o cs/n ext/in stalla tion -p ackages.html#INSTALLATIO N-PACKAG E S-REDHAT
の環境 で検証を実施しました。
7.4.1.2.
PostgreSQL Enterprise Consortium
Page 235 of 285
7.5 対象試験サーバ
IP
n od e1 192.168.0.10
n od e2 192.168.0.12
7.4.1.3.
1. yu mが利用可能な状態であること
パッージを入手するyu mを使用
設定手順
指定がない部分は、n o d e1n o de2両方で実施します。
1. 検証環境準備
B D R 検証を実施するめの環境を準備しす。
ssh接続を用いて、該当環境へ接続
ユーザ: root
パスワード: xxxxxxx
2. h ostsの設定
DNSの名前解決のために各サーバのホスト名を設定します。
# vi /etc/hosts
[下記をファイル末尾に追加]
192.168.0.10 node1
192.168.0.12 node2
3. 関連ポートの開放
Po stg reSQ L間のB DR接続のため5432ポートの開放をします。
# firewall-cmd --permanent --add-port=5432/tcp
# firewall-cmd --reload
以下のコマンドで確認しす。
# firewall-cmd --list-ports
5432/tcp
4. B D R レポジトリの登録
B D R レポジトリ用のRPMをインスールしす。
# RHEL/CentOS users only:
# yum install http://packages.2ndquadrant.com/postgresql-bdr94-2ndquadrant/yum-repo-
rpms/postgresql-bdr94-2ndquadrant-redhat-latest.noarch.rpm
以下のコマンドでインスール済み一覧を確認します。
PostgreSQL Enterprise Consortium
Page 236 of 285
# yum list installed postgresql-bdr94-2ndquadrant-redhat.noarch 0:1.0-3
[省略]
インスール済みパッージ
postgresql-bdr94-2ndquadrant-redhat.noarch 1.0-3 installed
5. B D R インスール
登録したB DRレポジトリからBD R をインストールします。
# yum install postgresql-bdr94-bdr
[省略]
インスール:
postgresql-bdr94-bdr.x86_64 0:1.0.2-1_2ndQuadrant.el7.centos
依存性関連をインスールしました:
postgresql-bdr94.x86_64 0:9.4.10_bdr1-1_2ndQuadrant.el7.centos
postgresql-bdr94-contrib.x86_64 0:9.4.10_bdr1-1_2ndQuadrant.el7.centos
postgresql-bdr94-libs.x86_64 0:9.4.10_bdr1-1_2ndQuadrant.el7.centos
postgresql-bdr94-server.x86_64 0:9.4.10_bdr1-1_2ndQuadrant.el7.centos
完了しました!
以下のコマンドでインスール済み一覧を確認します。
# yum list installed postgresql-bdr94-bdr.x86_64 0:1.0.2-1_2ndQuadrant.el7.centos
[省略]
インスール済みパッージ
postgresql-bdr94-bdr.x86_64 1.0.2-1_2ndQuadrant.el7.centos
@postgresql-bdr94-2ndquadrant-redhat
6. 環境変数設定
データベースクンド実行ファイルに環境変数の設定をします
$ vi ~/.bash_profile
[下記の修正を加え]
#PGDATA=/var/lib/pgsql/9.4-bdr/data
PGDATA=/var/lib/pgsql/2ndquadrant_bdr/data/
[下記をファイル末尾に追加]
export PATH=/usr/pgsql-9.4/bin:$PATH
以下のコマンドで設定した環境変数を確認します。
$ exit
ログアウト
# su - postgres
$ echo $PATH
/usr/pgsql-9.4/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
$ echo $PGDATA
/var/lib/pgsql/2ndquadrant_bdr/data/
7. データベースク
B D R 検証用に新規でデータベースクラスタ作成しす。
PostgreSQL Enterprise Consortium
Page 237 of 285
$ mkdir -p $HOME/2ndquadrant_bdr/
$ initdb -D $HOME/2ndquadrant_bdr/data -A trust -U postgres --no-locale
8. B D R のパラータ設定(p o stgresql.con f)
B D R のパラータ設定(p o stgresql.con f)します。
$ vi /var/lib/pgsql/2ndquadrant_bdr/data/postgresql.conf
[下記の修正を加え]
listen_addresses = '*'
shared_preload_libraries = 'bdr'
wal_level = 'logical'
track_commit_timestamp = on
max_connections = 100
max_wal_senders = 10
max_replication_slots = 10
# Make sure there are enough background worker slots for BDR to run
max_worker_processes = 10
log_line_prefix = '%m d=%d p=%p a=%a%q '
# These aren't required, but are useful for diagnosing problems
#log_error_verbosity = verbose
#log_min_messages = debug1
# Useful options for playing with conflicts
#bdr.default_apply_delay=2000 # milliseconds
#bdr.log_conflicts_to_table=on
9. B D R のクイアント認証設定(pg_h ba.co n f)
B D R のクイアント認証設定(pg_h ba.co n f)をします。
$ vi /var/lib/pgsql/2ndquadrant_bdr/data/pg_hba.conf
[下記の修正を加え]
host all all 192.168.0.10/32 trust
host all all 192.168.0.12/32 trust
local replication postgres trust
host replication postgres 0.0.0.0/0 trust
host replication postgres ::1/128 trust
10. Po stgreSQ L起動
設定が環境ししたPo stg reSQ Lを起動します。
起動時にB DRのバックグランドワーカの登録メセージが出力さる事を確認しす。
$ pg_ctl start
サーバは起動中で
-bash-4.2$ < 2016-10-19 01:47:01.891 JST >LOG: バッウンドワーカ"bdr supervisor"を登録してい
< 2016-10-19 01:47:02.041 JST >LOG: ログ出力をログ集プロセスダイレクトし います
< 2016-10-19 01:47:02.041 JST >ヒント: からのロ力はディレクト"pg_log"に現れます。
以下のコマンドでPo stg reSQ Lの起動状況を確認します
$ pg_ctl status
pg_ctl: サーが動作中で(PID: 10948)
/usr/pgsql-9.4/bin/postgres
11. ータベース作成
PostgreSQL Enterprise Consortium
Page 238 of 285
B D R の動作確認用のデータベーを作成します
$ createdb bdrtest
以下のコマンドで作成したデータベースへの接続を確認します
$ psql bdrtest
psql (9.4.9)
"help" でヘルプを表示します.
bdrtest=# \q
-bash-4.2$
12. B D R モジュール登録
B D R 必要な拡張モジュールを登録します
$ psql -U postgres bdrtest
=# CREATE EXTENSION btree_gist;
=# CREATE EXTENSION bdr;
以下のコマンドでインスール済みの拡張モジュールを確認します
=# \dx
インスール済みの拡張の一覧
名前 | バージョン | スキーマ | 説明
------------+------------+------------+-----------------------------------------------
bdr | 1.0.1.0 | pg_catalog | Bi-directional replication for PostgreSQL
btree_gist | 1.0 | public | support for indexing common datatypes in GiST
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(3 )
13. B D R グループ作成
n od e1BD R グループを作成するため、「bd r.b d r_gro u p_create」関数を実行します
$ psql -U postgres bdrtest
=# SELECT bdr.bdr_group_create(
local_node_name := 'node1',
node_external_dsn := 'host=node1 port=5432 dbname=bdrtest');
ループが作成さたこ確認するため、「bd r.bdr_n od e_join_w a it_fo r_ready関数実行しす。
=# SELECT bdr.bdr_node_join_wait_for_ready();
bdr_node_join_wait_for_ready
------------------------------
(1 )
14. ノード登
n od e2ノード登録するめにb d r.bd r_g rou p _join 数を実行します
PostgreSQL Enterprise Consortium
Page 239 of 285
$ psql -U postgres bdrtest
=# SELECT bdr.bdr_group_join(
local_node_name := 'node2',
node_external_dsn := 'host=node2 port=5432 dbname=bdrtest',
join_using_dsn := 'host=node1 port=5432 dbname=bdrtest'
);
ノードが登録さたこ確認するため、「bd r.b d r_n od e_join _w ait_for_ready関数実行しす。
=# SELECT bdr.bdr_node_join_wait_for_ready();
bdr_node_join_wait_for_ready
------------------------------
(1 )
15. ノード状態の確認
ノードの状態を「b d r.bdr_n od esテーブルの情報から確認します。
$ psql -U postgres bdrtest
=# \x
=# SELECT * FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_sysid | 6369044607312522907
node_timeline | 1
node_dboid | 16385
node_status | r
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_init_from_dsn |
node_read_only | f
-[ RECORD 2 ]------+------------------------------------
node_sysid | 6369045470046586386
node_timeline | 1
node_dboid | 16385
node_status | r
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest
node_read_only | f
16. 易動作検証(no de1)
n od e1BD R 簡易動作検証実施しす。
n od e1作成さたテーブルとデータn od e2にレプリーションさていとを確認します。
$ psql -U postgres bdrtest
=# CREATE TABLE t1bdr (c1 INT, PRIMARY KEY (c1));
=# INSERT INTO t1bdr VALUES (1);
=# INSERT INTO t1bdr VALUES (2);
17. 易動作検証(no de2)
n od e2BD R 簡易動作検証の結果を確認します。
n od e1同じテーブルとデータが表示できていれば、構築したBDR 環境問題はありせん。
n od e1同様の簡易動作検証をn od e2実施して下さい。
PostgreSQL Enterprise Consortium
Page 240 of 285
$ psql -U postgres bdrtest
=# SELECT * FROM t1bdr;
c1
----
1
2
(2 )
=# INSERT INTO t1bdr VALUES (3);
7.5. BDR動作検証
7.5.1.
7.5.1.1.
ノードの追加/切り離しオンイン(DB 停止)なしで実行できるか否かを確認します
7.5.1.2.
本検証で2台で構成されB D R対して、下記を実施しました。
1. ノード切り離し
2. ノード追加
ノード切り離し」および「ノード追加」時に他ノード(上図n o d e1)ンザクションを実行し、トランザクションにエラーが発生するか否か確認しました。
7.5.1.3.
の環境 で検証を実施しました。
7.5.1.4.
7.5.1.4.1.
1. B D R の各ノード状態確認
B D R の各ノード間のプリションが正常に動作していることb d r.bdr_n o d esテーブルを用いて確認します
PostgreSQL Enterprise Consortium
Page 241 of 285
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であるとを確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であるとを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest <-- node1から作成れていることを確認
2. 検証用テーブルとデータの作成
pg b ebch を利用して、検証時に利用するーブルとデータを作成しす。
(node1実施)
$ pgbench -i -s 10 bdrtest
3. トランザクション実行
pg b ench を利用して、ノード1ンザションを継続的に実行します。 ノード2を切り離した発生した場合にノード1に対して実行したトランザクショ
ンにエラーが発生するか否か確認します
$ pgbench -h node1 -c 10 -t 100000 bdrtest
starting vacuum...end.
4. ノード切り離し
ノード2を切り離しするめ、「bd r.b d r_part_b y_n o d e_n ames」関数を実行します
(node1のデータベース接続)
=# SELECT bdr.bdr_part_by_node_names(ARRAY['node2']);
bdr_part_by_node_names
------------------------
(1 row)
5. ノードの切り離し結果確認
ノードの切り離し結果を「bd r.b d r_n o d es」テーブルを用いて確認します
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | k <-- k(削除)であるとを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest
6. システムカログの残データ削除
PostgreSQL Enterprise Consortium
Page 242 of 285
本手順は推奨さ手順ではありませんが、除状態のノードが「b dr.bd r_n o desテーブルに残っていると削除したノードの追加が実行できなため
暫定的な対処です。 B D RIssu esbdr.bd r_co n n ectio n sのデータも削除する事が提案さいたので、こちら暫定的手順ですが実行しま
す。 細は下記をご参照下さい。
h ttps://githu b .com/2n d Q u ad ran t/bd r/issu es/97
h ttps://githu b .com/2n d Q u ad ran t/bd r/issu es/126
(node1のデータベース接続)
=# DELETE FROM bdr.bdr_connections USING bdr.bdr_nodes WHERE node_status = 'k' AND
(node_sysid, node_timeline, node_dboid) = (conn_sysid, conn_timeline, conn_dboid);
=# DELETE FROM bdr.bdr_nodes where node_status = 'k';
7. ノードの切り離し結果確認
ノードの切り離し結果を「bd r.b d r_n o d es」テーブルを用いて確認します
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r
node_init_from_dsn |
8. B D R の無効化
ノード2データベースから「bdr.remove_b d r_from_lo cal_n o d e関数を用いてB D R を削除しB DR拡張機能を削除します
(node2のデータベース接続)
=# SELECT bdr.remove_bdr_from_local_node(true);
WARNING: forcing deletion of possibly active BDR node
NOTICE: removing BDR from node
NOTICE: BDR removed from this node. You can now DROP EXTENSION bdr and,
if this is the last BDR node on this PostgreSQL instance, remove bdr from
shared_preload_libraries.
remove_bdr_from_local_node
----------------------------
=# DROP EXTENSION bdr;
DROP EXTENSION
9. トランザクション状態実行状態確認
手順1で実行したp g ben ch エラーが発生してないことを確認します。本検証ではエーは発生しませんでした
7.5.1.4.2.
切り離しBDRノードを再度追加する場合、既存ノードのデータベースと追加するノードのデータベースのスキーマおよびデータを同期させる要があります ノード間のデー
ピーに、論理コピーと物理コピーの2つの手法があります。
h ttp://b dr-pro ject.o rg/d o cs/stable/fu n ction s-n od e-mg mt.h tml#FU NCTIO N-BD R -GRO U P-JO IN
7.6 ピー取得方法
1 bd r.b d r_gro u p_jo in
数実行
ユーザが指定したノード内データベースのスキーマとデータダンプを取得 pg _d u mpコマンドに相当
2 bd r_init_co pyマン ユーザが指定したノード上の全てのデータベーピーを取得 pg _b aseb acku pマンド
相当
論理コピーによるノド追加
PostgreSQL Enterprise Consortium
Page 243 of 285
1. トランザクション実行
pg b ench を利用して、ノード1ンザションを継続的に実行します。 ノード2復旧するに、ノード1に対して行したトランザクションの停止が必
要か否か確認しす。
$ pgbench -h node1 -c 10 -t 100000 bdrtest
starting vacuum...end.
2. ノード2PostgreSQ L起動
ノード2で動作するPo stg reSQ Lを起動さます
$ pg_ctl start
3. データベース削除
B D R で利用したデータベースを削除します。
(node2のデータベース接続)
=# DROP DATABASE bdrtest ; 接続が残っており、削除できない場合PostgreSQLを再起動
DROP DATABASE
4. データベースの再作成
B D R で利用するデータべースを再度作成しす。
(node2のデータベース接続)
=# CREATE DATABASE bdrtest;
5. B D R 有効化
無効化しB D R を再度有効化します
(node2のデータベース接続)
=# CREATE EXTENSION btree_gist;
CREATE EXTENSION
=# CREATE EXTENSION bdr;
CREATE EXTENSION
6. ノードの追加
ノードを追加(復旧)せるめ、「bdr.bd r_gro u p _join関数を実行します。
(node2のデータベース接続)
=# SELECT bdr.bdr_group_join(
local_node_name := 'node2',
node_external_dsn := 'host=node2 port=5432 dbname=bdrtest',
join_using_dsn := 'host=node1 port=5432 dbname=bdrtest'
);
bdr_group_join
----------------
(1 )
PostgreSQL Enterprise Consortium
Page 244 of 285
7. ノード追加の確認待ち
ノードが追加さたこ確認するため、「bd r.b d r_n od e_join _w ait_for_ready関数実行しす。
(node2のデータベース接続)
=# SELECT bdr.bdr_node_join_wait_for_ready();
トランザクションが実行中の場合、上記関数の結果が戻りません。
n od e1PostgreSQ Lファイルに下記メッセージが出力さた後復旧の処理が開始さませ
(node1のログメセージ抜粋)
LOG: logical decoding found initial starting point at 0/BB399BF0
DETAIL: 10 transactions need to finish.
pg b ench マンドで実行中のトンザクシンを停止すると、下記ログメッセージが出力さ、復旧処理が開始さます
(node1のログメセージ抜粋)
LOG: logical decoding found consistent point at 0/B2895648
DETAIL: There are no running transactions.
LOG: exported logical decoding snapshot: "00046FE0-1" with 0 transaction IDs
8. B D R の各ノード状態確認
ノード2が追加されとを「bdr.bd r_n o des」テーブルの情報から確認します
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest <-- node1から作
成さていとを確認
物理コピーによるノード追加
1. トランザクション実行
pg b ench を利用して、ノード1ンザションを継続的に実行します。 ノード2追加するに、ノード1に対して行したトランザクションの停止が必
要か否か確認しす。
$ pgbench -h node1 -c 10 -t 100000 bdrtest
starting vacuum...end.
2. ノード2PostgreSQ L停止確認
ノード2で動作するPo stg reSQ Lが停止していることを確認します
PostgreSQL Enterprise Consortium
Page 245 of 285
(node2実施)
$ pg_ctl status
pg_ctl: no server running
3. 物理コピーの取
ノード2で「bd r_in it_co p yマンドを実行し、ノード1上のコピー取得しす。
(node2実施)
$ rm -rf $PGDATA/*
$ bdr_init_copy -D $PGDATA -n node2 -h node1 -p 5432 -d bdrtest
--local-host=node2 --local-port=5432 --local-dbname=bdrtest
bdr_init_copy: starting ...
Getting remote server identification ...
Detected 1 BDR database(s) on remote server
Updating BDR configuration on the remote node:
bdrtest: creating replication slot ...
bdrtest: creating node entry for local node ...
Creating base backup of the remote node...
50357/50357 kB (100%), 1/1 tablespace
Creating restore point on remote node ...
Bringing local node to the restore point ...
トランザクションログをリセットしす。
Initializing BDR on the local node:
bdrtest: adding the database to BDR cluster ...
All done
n od e1PostgreSQ Lファイルに下記メッセージが出力さた後追加の処理が開始さませ
(node1のログメセージ抜粋)
LOG: logical decoding found initial starting point at 0/BB399BF0
DETAIL: 10 transactions need to finish.
pg b ench マンドで実行中のトンザクシンを停止すると、下記ログメッセージが出力さ、復旧処理が開始さます
(node1のログメセージ抜粋
LOG: logical decoding found consistent point at 0/B2895648
DETAIL: There are no running transactions.
STATEMENT: SELECT
pg_create_logical_replication_slot('bdr_25434_6369931070716042622_2_25434__', 'bdr');
4. B D R の各ノード状態確認
ノード2が追加されとを「bdr.bd r_n o des」テーブルの情報から確認します
PostgreSQL Enterprise Consortium
Page 246 of 285
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest <-- node1から作
成さていとを確認
7.5.1.5.
切り離しードの情報がシステムカログ残ってしまうめ、データ操作が禁止さいるシステムカタログのデータ削除が必要でした
システムカログのデータ操作は禁止されていますが、切り離したノードの情報がシステムカタログに残って場合、 ノード追加時に下記のメッセージが出力され、ノードが
追加が実施でないため本検証では暫定対処としてシステカタログのデータ削除を実施しておりす。
ERROR: System identification mismatch between connection and slot
詳細: Connection for bdr (6369029438929838565,1,16385,) resulted in slot on node bdr
(6369034270871134883,2,16385,) instead of expected node
LOG: ワーカプロセス: bdr db: bdrtest (PID 17232)は終了コード1で終了しました
ノード追加にはプロセスの再起動は必要ありませんが、トランザクションの停止が必要でした
7.5.2.
7.5.2.1.
B D R 実装さたグローバルシーケンスの利用方法について確認します グルーバルシーケンスを利用するとでノード毎に払い出されるシーケンス番号を独立させ、ノード
間のシーケンス番号の競合を防ぐことができるか否かを確認します
7.5.2.2.
の環境 で検証を実施しました。
7.5.2.3.
1. 初期状態
B D R の各ノード間のプリションが正常に動作していることb d r.bdr_n o d esテーブルを用いて確認します
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であるとを確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であるとを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest <-- node1から作成れていることを確認
2. ローバルシーケンス動作確認
n od e1データベースに接続し、serial列に持つg stestーブルを作成します serial型を持つテーブルを作成すると、自動的にシーケンスが作成
PostgreSQL Enterprise Consortium
Page 247 of 285
れます。 ーバルシーケンス成のため、テブル作成時にSE T LO CAL defa u lt_sequ enceam = 'b dr';を指定する必要があります
(node1のデータベース接続)
=#
BEGIN;
SET LOCAL default_sequenceam = 'bdr'; <-- グローバルシーケンス成用の設定
CREATE TABLE gstest (
id serial primary key,
hogehoge text
);
COMMIT;
参考. DDL実行時にnode1に出力されるログッセージ
LOG: DDL LOCK TRACE: attempting to acquire in mode <ddl_lock> for (bdr (xxxxxxxx))
--------
STATEMENT: CREATE TABLE gstest (
id serial primary key,
hogehoge text
);
LOG: DDL LOCK TRACE: attempting to acquire in mode <write_lock> (upgrading from
<ddl_lock>) for (bdr (xxxxxxxxx,))
>STATEMENT: CREATE TABLE gstest (
id serial primary key,
hogehoge text
);
--------
3. ルーバルシーケンス作成確認
n od e1よびn o d e2のデータベー接続し、グローバルシーケンスが作成さとを確認します
(node1のデータベース接続)
=# \ds
List of relations
-[ RECORD 1 ]---------
Schema | public
Name | gstest_id_seq
Type | sequence
Owner | postgres
(node2のデータベース接続)
=# \ds
List of relations
-[ RECORD 1 ]---------
Schema | public
Name | gstest_id_seq
Type | sequence
Owner | postgres
下記のSQ Lで詳細情(pg _class情報)を確認可能です。
=# SELECT * FROM pg_class
INNER JOIN pg_seqam ON (pg_class.relam = pg_seqam.oid)
WHERE pg_seqam.seqamname = 'bdr' AND relkind = 'S';
4. ローバルシーケンス利用
n od e1データベースに接続し、1件のデー投入しす。
(node1のデータベース接続)
=# INSERT INTO gstest(hogehoge) VALUES ('test1');
INSERT 0 1
n od e2データベースに接続し、1件のデー投入しす。
PostgreSQL Enterprise Consortium
Page 248 of 285
(node2のデータベース接続)
=# INSERT INTO gstest(hogehoge) VALUES ('test2');
INSERT 0 1
5. シーケンス値の競合有無確認
n od e1よびn o d e2のシーケンスの値に競合が発生していないことを確認します 本検証では、n o d e12が割り当てれ、n o d e2100001が割
り当てました。
(node1のデータベース接続)
=# SELECT * FROM gstest;
id | hogehoge
--------+----------
2 | test1 <-- node12のシーケンスが割り当てれる
100001 | test2 <-- node2100001のシーケンスが割り当てれる
(2 rows)
6. ローバルシーケンス利用
n od e1200,000のデータを投入し、シーケンス値が100,000を超えた場合、n o d e2100,001と競合しないか否かを確認しました
(node1おいて実施)
$ cat /tmp/gs.sh
#!/bin/sh
for i in `seq 1 200000`
do
psql -d bdrtest -c "INSERT into gstest(hogehoge) VALUES ('test${i}');"
done
$ sh /tmp/gs.sh
INSERT 0 1
[省略]
7. ローバルの状態確認
n od e1シーケンス100,000を利用したのち、n o de1割り振られた値を確認しました
(node1のデータベース接続)
=# SELECT * FROM gstest WHERE 99999 <= id;
id | hogehoge
--------+------------
99999 | test99997
100000 | test99998
100001 | test2
150001 | test99999 -< 100,000を超えると、node1のシーケンス150,001に割り振られる。
150002 | test100000
150003 | test100001
150004 | test100002
150005 | test100003
150006 | test100004
7.5.2.4.
ローバルシーケンスを用いることでノード間のシーケンス番号の競合を抑止できることが確認できました グルーバルシーケンスいてはいくつかの制限事項がマニュアルに
記載さおりますので、注意して下さ
1. 1ォルト値)INCREM ENTけがサポートさいます
PostgreSQL Enterprise Consortium
Page 249 of 285
2. MINVALU EM AXVALU E はデフォルトでロッており、変更することできませ
3. CACHE指令はサポートさいませ
h ttp://b dr-pro ject.o rg/d o cs/1.0/glo bal-sequ en ce-limitation s.h tml
7.5.3.
選択的レプリーシンについて記載しす。
7.5.3.1.
ーブル単位での選択的レプリーションの可否を確認します 選択的レプリションの可否は互いのデータベース間での任意のテーブルのデータ状態元に判断します
また、選択的レプリーションを実現する際の変更手順を明確にする事を目的とします
7.5.3.2.
Replication Set : レプリケーション対象とするテーブルの論理集合を表し、ノード毎に設定可能
h ttp://b dr-pro ject.o rg/d o cs/stable/replication -sets.h tml
選択的レプリーシン検証内容
双方向レプリーシンの動作確認
選択的レプリーシ(no d e1)の動作確認
選択的レプリーシ(no d e2)の動作確認
7.5.3.3.
の環境 で検証を実施しました。
7.5.3.4.
1. 選択的レプリーシン環境構築
選択的レプリーシンの動作確認の為に、下記の検証環境を構築します。
(1)データベース作成
ストを実施するのデータベースを作成します
(node1,node2において実)
=# CREATE DATABASE rep_test;
(2)BDRの有効
作成したデーベース上でB D R 能の有効化を実施しす。
(node1,node2のデータベースにおいて実)
=# CREATE EXTENSION btree_gist;
=# CREATE EXTENSION bdr;
PostgreSQL Enterprise Consortium
Page 250 of 285
(3)BDRグループの作成
B D R ノードのクbd r.b d r_gro u p_create」を利用して最初のノードを作成します
(node1のデータベース接続)
=# SELECT bdr.bdr_group_create(
local_node_name := 'node1',
node_external_dsn := 'host=node1 port=5432 dbname=rep_test',
replication_sets:= ARRAY['default','node1']); replications_ret
node1を追加
(4)ード登録(n od e2)
既存のB D R ノードのクラスタにb dr.bd r_gro u p _joinを利用してノードを登録します り、全てのノード間でレプリーシンが開始されます
(node2のデータベース接続)
=# SELECT bdr.bdr_group_join(
local_node_name := 'node2',
node_external_dsn := 'host=node2 port=5432 dbname=rep_test',
join_using_dsn := 'host=node1 port=5432 dbname=rep_test',
replication_sets:= ARRAY['default','node2']); replications_ret
node2を追加
(5)ードの状態確認
B D R ループ内のノードのメンバシップをb d r.bd r_n o d esを利用して確認します
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+-------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=rep_test
node_status | r <-- r(正常)であることを確認
node_init_from_dsn |
-[ RECORD 2 ]------+-------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=rep_test
node_status | r <-- r(正常)であることを確認
node_init_from_dsn | host=node1 port=5432 dbname=rep_test <-- node1から作成さいるとを確
(6)プリーシンセッの確認
指定したノードのレプリーシンセットを「b d r.con n ection _get_replication _setsを利用して確認します
(node1のデータベース接続)
=# SELECT bdr.connection_get_replication_sets('node1');
-[ RECORD 1 ]-------------------+----------------
connection_get_replication_sets | {default,node1} <-- node1追加さいること
=# SELECT bdr.connection_get_replication_sets('node2');
-[ RECORD 1 ]-------------------+----------------
connection_get_replication_sets | {default,node2} <-- node2追加さいること
2. 双方向レプリーシン対象テーブルの動作確認
まず、通常の双方向レプリケーション動作を確認します 片方のテーブルにデータを挿入した時にもう一方のテーブルにデータが挿入されいます
(1)(all_rep )作成
PostgreSQL Enterprise Consortium
Page 251 of 285
ストを実施するのテーブル(all_rep)を作成します。
(node1のデータベース接続)
=# CREATE TABLE all_rep(id int, PRIMARY KEY(id));
CREATE TABLE
(2)プリーシンセッ確認
指定したテーブルのレプリーションセットを「b d r.co n n ection _get_replication _setsを利用して確認します。
(node1のデータベース接続)
=# SELECT bdr.table_get_replication_sets('all_rep');
-[ RECORD 1 ]--------------+--------------
table_get_replication_sets | {default,all} <-- defaultが含まいる
(3)データ追加
n od e1ーブルにデータを挿入します
(node1のデータベース接続)
=# INSERT INTO all_rep VALUES (1);
INSERT 0 1
(4)プリーシン確認
n od e2ーブルにデータがレプリケーションさいる事を確認します。
(node2のデータベース接続)
=# SELECT id FROM all_rep;
id
----
1 <-- データがレプリーシンされいる
(1 row)
3. レプーション対象外テーブルの作成(n o de1のみ)
次に、選択的レプーション動作を確認します。 指定したテーブルではレプーション動作が行われなくりますので、任意のーブルのみプリショ
ンさせる事が出来ます
(1)(n o de1_on ly)の作
ストを実施するのテーブル(n o d e1_on ly)を作成します
(node1のデータベース接続)
=# CREATE TABLE node1_only(id int, PRIMARY KEY(id));
CREATE TABLE
(2)プリーシンセッ変更
指定したテーブルのレプリーションセットを「b d r.tab le_set_replication _setsを利用して'no de1'に設定し、レプリーション対象'nod e1'みに
します 設定したレプリケーションセッを確認するには、b d r.table_get_rep lication _setsを利用します
PostgreSQL Enterprise Consortium
Page 252 of 285
(node1のデータベース接続)
=# SELECT bdr.table_set_replication_sets('node1_only', ARRAY['node1']);
-[ RECORD 1 ]--------------+-
table_set_replication_sets |
=# SELECT bdr.table_get_replication_sets('node1_only');
-[ RECORD 1 ]--------------+------------
table_get_replication_sets | {node1,all} <-- node1追加さいること
(3)データ追加
n od e1ーブルにデータを挿入します
(node1のデータベース接続)
=# INSERT INTO node1_only VALUES (1);
INSERT 0 1
(4)プリーシン確認
n od e2ーブルにデータがレプリケーションさいない事を確認します。
(node2のデータベース接続)
=# SELECT id FROM node1_only;
id
---- <-- レプリーションさいないこ
(0 )
4. レプーション対象外テーブルの作成(n o de2のみ)
同様に、も一方からの選択的レプーション動作も確認します。
(1)(n o de2_on ly)の作
ストを実施するのテーブル(n o d e2_on ly)を作成します
(node2のデータベース接続)
=# CREATE TABLE node2_only(id int, PRIMARY KEY(id));
CREATE TABLE
(2)プリーシンセッ変更
指定したテーブルのレプリーションセットを「b d r.tab le_set_replication _setsを利用して'no de2'に設定し、レプリーション対象'nod e2'みに
します 設定したレプリケーションセッを確認するには、b d r.table_get_rep lication _setsを利用します
(node2のデータベース接続)
=# SELECT bdr.table_set_replication_sets('node2_only', ARRAY['node2']);
-[ RECORD 1 ]--------------+-
table_set_replication_sets |
=# SELECT bdr.table_get_replication_sets('node2_only');
-[ RECORD 1 ]--------------+------------
table_get_replication_sets | {node2,all} <-- node2追加さいること
(3)データ追加
n od e2ーブルにデータを挿入します
PostgreSQL Enterprise Consortium
Page 253 of 285
(node2のデータベース接続)
=# INSERT INTO node2_only VALUES (1);
INSERT 0 1
(4)プリーシン確認
n od e1ーブルにデータがレプリケーションさいない事を確認します。
(node1のデータベース接続)
=# SELECT id FROM node2_only;
id
---- <-- レプリーションさいないこ
(0 )
7.5.3.5.
今回の検証結果では、レプリケーションセットに任意のノードを指定する事で選択的レプリーションが実現さる事が確認出来ました また、選択的レプリーション実現
の為の設定変更手順にいても確認出来ました
し、レプリーションセットにテーブルを追加する場合は、過去のデータまで反映しないので、手動で同期が必要です。
選択的レプリーシンの主な注意事項下記になります
h ttp://b dr-pro ject.o rg/d o cs/1.0/replica tion -sets-con cepts.h tml
h ttp://b dr-pro ject.o rg/d o cs/1.0/replica tion -sets-tables.h tml
1. DDLはレプリケーションセットの設定に関係なく常にすべてのノードに影響します。
2. TRUNCATEは常にレプートされます。望ましくい場合は、DELETEを利用する要があります
3. レプーションセットの設定、初期ノード追加(結合)テーブルデータのコピーに影響を与えません。
4. レプーションセットにテーブルを追加した場合も以前のデー内容はノドに同期させん。 通常、管理者は、テーブルをレプーションセットに追加した後、
手動で同期する必要があります
7.5.4.
7.5.4.1.
B D R マルチマス構成する各ノードに対し参照処理と更新処理実行することが可能です。 複数ノードに対して同時に更新処理が実施さた場合、各ノードに
して実行さ更新処理が競合る事象が発生する合があります
B D R 競合が発生した場合、最後の更新処理が適用されます(last_u p date_w ins)。ま、競合結果はテーブル「b d r.bdr_co n flict_histo ryで確認可能です。
bd r.b d r_con flict_h istory納される情報にいて下記をご参照下さ
h ttp://b dr-pro ject.o rg/d o cs/stable/co n flicts-typ es.h tml
下記を明らかにするめ検証を実施しました
1. 更新処理が競合した場合の挙動
2. 競合発生時にシステムカタログ記録さる情報
7.5.4.2.
B D R 動作検証概要図
PostgreSQL Enterprise Consortium
Page 254 of 285
下表の競合発生時の動作を検証しました。
7.7 検証した競合のパターン
1 PRIMARY KEYまたはUNIQ UE制約 2の操作が同じU NIQ U E KEY持つ行に影響を及ぼす
行の競合検証しす。
2 外部キー制約 外部キー制約が定義さたテーブルにおいて
制約に違反するデータ削除によって引起こ競合を検証します。
3 排他制約 B D R では排他制約をサポートしていないために
排他制約において競合が発生した場合検証しす。
4 ローバルなデータ ドのグローバル(PostgreSQ Lシステム全体)
データ(ロールな)が異なる場合での競合を検証します
5 ロックの競合とデッドロックの中断 BDR適用ロセスとロックの競合にいて検証します。
6 その他 自動的に解決出来ないデータの相違が発生した場合に
手動で調整を行う方法を検証します
7.5.4.3.
の環境 で検証を実施しました。
7.5.4.4.
1. 競合ログオプションの有効化確認
競合発生時にーブル「bd r.b d r_con flict_h isto ry情報を記録するめ、bdr.log _co n flicts_to _tableパラメータがo n 設定さていとを
確認します。
offになっていたら、p o stgresql.co n fに「b d r.lo g_con flicts_to _ta b le=o n を追記し再読み込みを実行して下さい。
n od e1/n od e2のデータベースに接続し、パータを確認するめに下記コマンドを実行します
(node1実施)
=# SHOW bdr.log_conflicts_to_table;
bdr.log_conflicts_to_table
----------------------------
on
(1 )
(node2実施)
=# SHOW bdr.log_conflicts_to_table;
bdr.log_conflicts_to_table
----------------------------
on
(1 )
2. レプーション反映時間の設定
ネットワーク遅延などの実際の環境を想定して検証を行うめ、bdr.defau lt_apply_delayパラータを設定します のパラータを設定する事で
プリーションの反映を設定した時間(リ秒)遅らせる事が出来ます
今回の検証では、競合の発生を確認しすくするために"2s"を設定しています
n od e1/n od e2のデータベースに接続し、パータを確認するめに下記コマンドを実行します
(node1実施)
=# SHOW bdr.default_apply_delay;
bdr.default_apply_delay
----------------------------
2s
(1 )
(node2実施)
=# SHOW bdr.default_apply_delay;
bdr.default_apply_delay
----------------------------
2s
(1 )
3. B D R の各ノード状態確認
B D R の各ノード間のプリションが正常に動作していることb d r.bdr_n o d esを利用して確認します
PostgreSQL Enterprise Consortium
Page 255 of 285
(node1実施)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest <-- node1作成されていることを確認
4. 検証用テーブルとデータの作成
pg b ebch を利用して、検証時に利用するーブルとデータを作成しす。
(node1実施)
$ pgbench -i -s 10 bdrtest
$ psql -h node1 -d bdrtest
=# INSERT INTO pgbench_accounts (aid, bid, abalance) VALUES (1000001, 1, 0);
7.5.4.4.1. PRIMARY KEY UNIQUE
1. INSERT vs INSERT
競合概要
最も一般的な競合として2の異なるノードのINSERTが同じPRIMAR Y KEYの値(または、単一のUNIQ E制約の値)を持つデータを挿入するースを
検証しました
検証結果
イムスタンプに従い、最後にデータが作成された方が保持れました
競合発生手順
各ノードからそれぞINSER Tを実行し、INSERT vs INSERT の競合を発生させます
(node1のデータベースSQLを投入)
=# INSERT INTO pgbench_accounts (aid, bid, abalance) VALUES (1000002, 2, 0);
(node2のデータベースSQLを投入)
=# INSERT INTO pgbench_accounts (aid, bid, abalance) VALUES (1000002, 3, 0);
競合ログを「b dr.bd r_co n flict_h isto ryを利用して確認し競合の発生を確認します
競合履歴テーブルでは競合ロが出力されて側のサーをローカル、反対側リモトとし表示します よって、それぞれのサーで実行され
トランザクションをローカルトンザクション、リモートトランザクションとして説明します。
PostgreSQL Enterprise Consortium
Page 256 of 285
(node1またはnode2の競合履歴ーブルに競合ログが出力)
=# \x
=# SELECT * FROM bdr.bdr_conflict_history ORDER BY conflict_id DESC LIMIT 1;
-[ RECORD 1 ]------------+---------------------------------------------------
conflict_id | 48
local_node_sysid | 6371561413984311673
local_conflict_xid | 3944663
local_conflict_lsn | 3/765949B8
local_conflict_time | 2017-01-25 10:36:03.787698+09
object_schema | public
object_name | pgbench_accounts
remote_node_sysid | 6371553825031594764
remote_txid | 3960113
remote_commit_time | 2017-01-25 10:32:48.772254+09
remote_commit_lsn | 2/CA1AD950
conflict_type | insert_insert
conflict_resolution | last_update_wins_keep_local
local_tuple | {"aid":1000002,"bid":3,"abalance":0,"filler":null}
remote_tuple | {"aid":1000002,"bid":2,"abalance":0,"filler":null}
local_tuple_xmin | 3944662
local_tuple_origin_sysid |
error_message |
error_sqlstate |
error_querystring |
error_cursorpos |
error_detail |
error_hint |
error_context |
error_columnname |
error_typename |
error_constraintname |
error_filename |
error_lineno |
error_funcname |
それぞれのーブルの状態を確認し、競合発生時の処理を確認します。
後にデータが作成さローカルトンザクシンが保持さいます
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
--------+-----+----------+--------
1000001 | 1 | 0 |
1000002 | 3 | 0 |
(2 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
--------+-----+----------+--------
1000001 | 1 | 0 |
1000002 | 3 | 0 |
(2 )
last_update_wins_keep_local : 新のタイムスタンプであるローカル側の更新が適用
2. INSERT vs U PDATE
競合概要
一つのノードでINSERTしたデータともう片方のノードでU PDATEしたデータが同じPRIMAR Y KEYの値を持つースを検証しました
PostgreSQL Enterprise Consortium
Page 257 of 285
検証結果
INSERT/UPD ATE競合が発生した場合競合を解消するめオペレータ側でのデータ操作が必要とり、注意が必要で
競合発生手順
下記テーブルを初期状態とします
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
--------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
--------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
各ノードからそれぞINSER T/UPDATEを実行し、INSERT vs UPDATE の競合を発生させます。
(node1のデータベースSQLを投入)
=# INSERT INTO pgbench_accounts (aid, bid, abalance) VALUES (1000002, 4, 0);
(node2のデータベースSQLを投入)
=# UPDATE pgbench_accounts SET aid = 1000002 WHERE aid = 1000001;
競合ログを「b dr.bd r_co n flict_h isto ryを利用して確認し競合の発生を確認します
PostgreSQL Enterprise Consortium
Page 258 of 285
(node1またはnode2の競合履歴ーブルに競合ログが出力)
=# \x
=# SELECT * FROM bdr.bdr_conflict_history ORDER BY conflict_id DESC LIMIT 1;
-[ RECORD 1 ]------------+---------------------------------------------------
conflict_id | 49
local_node_sysid | 6371561413984311673
local_conflict_xid | 3944715
local_conflict_lsn | 3/81295CF8
local_conflict_time | 2017-01-25 10:36:46.780822+09
object_schema | public
object_name | pgbench_accounts
remote_node_sysid | 6371553825031594764
remote_txid | 3960133
remote_commit_time | 2017-01-25 10:33:31.640126+09
remote_commit_lsn | 2/D1CE6F00
conflict_type | insert_insert
conflict_resolution | last_update_wins_keep_local
local_tuple | {"aid":1000002,"bid":1,"abalance":0,"filler":null}
remote_tuple | {"aid":1000002,"bid":4,"abalance":0,"filler":null}
local_tuple_xmin | 3944714
local_tuple_origin_sysid |
error_message |
error_sqlstate |
error_querystring |
error_cursorpos |
error_detail |
error_hint |
error_context |
error_columnname |
error_typename |
error_constraintname |
error_filename |
error_lineno |
error_funcname |
それぞれのーブルの状態を確認し、競合発生時の処理を確認します。
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
1000002 | 4 | 0 |
(2 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000002 | 1 | 0 |
(1 )
PRIMARY KEYU PDATEで発生した競合でモート側では一意制約違反のために適用プロセスがデータ反映できず ローカル側で論理レプリ
ション中に接続が切断さ、データの整合性がとれなくなる状態が確認されました
PostgreSQL Enterprise Consortium
Page 259 of 285
(node1のデータベースログ)
LOG: starting background worker process "bdr (6371553825031594764,1,43905,)->bdr
(6371561413984311673,2,"
ERROR: duplicate key value violates unique constraint "pgbench_accounts_pkey"
DETAIL: Key (aid)=(1000002) already exists.
CONTEXT: apply UPDATE from remote relation public.pgbench_accounts in commit
1/2F279190, xid 3941360 commited at 2017-01-10 11:00:22.736985+09 (action #2) from node
(6371561413984311673,2,43865)
LOG: worker process: bdr (6371553825031594764,1,43905,)->bdr (6371561413984311673,2,
(PID 21287) exited with exit code 1
(node2のデータベースログ)
bdr (6371553825031594764,1,43905,):receive LOG: starting logical decoding for slot
"bdr_43865_6371553825031594764_1_43905__"
bdr (6371553825031594764,1,43905,):receive DETAIL: streaming transactions committing
after 1/2F279190, reading WAL from 1/2F279068
bdr (6371553825031594764,1,43905,):receive LOG: logical decoding found consistent point
at 1/2F279068
bdr (6371553825031594764,1,43905,):receive DETAIL: There are no running transactions.
bdr (6371553825031594764,1,43905,):receive LOG: could not receive data from client:
Connection reset by peer
bdr (6371553825031594764,1,43905,):receive LOG: unexpected EOF on standby connection
競合するタプルをローカル側から手動で削除するか、新しいモートプルと競合しなくようUPDATEする必要がある
上記状態では、ローカル側からのレプーションが実施さい状態が続くため解消するために、ローカル側のデータUPD ATEます
(node1のデータベースSQLを投入)
=# UPDATE pgbench_accounts SET aid = 1000003 WHERE aid = 1000002;
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
1000003 | 4 | 0 |
(2 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000002 | 1 | 0 |
(1 )
競合は解消さ、次のデータからレプリケーションが始まるがデータの整合性で問題あ
3. UPD ATE vs DELETE
競合概要
一つのノードでU PDATEしたデータともう片方のノードでD ELETEデータが同じPRIM ARY KEYの値を持つケースを検証しました。
検証結果
UPD ATE/DELETEが競合した場合、UPDATEが破棄さました。
競合発生手順
下記テーブルを初期状態とします
PostgreSQL Enterprise Consortium
Page 260 of 285
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
各ノードからそれぞUPDATE/DELETEを実行しU PDATE vs DELETE の競合を発生させます
(node1のデータベースSQLを投入)
=# UPDATE pgbench_accounts SET bid = 4 WHERE aid = 1000001;
(node2のデータベースSQLを投入)
=# DELETE FROM pgbench_accounts WHERE aid = 1000001;
競合ログを「b dr.bd r_co n flict_h isto ryを利用して確認し競合の発生を確認します
(node1またはnode2の競合履歴ーブルに競合ログが出力)
=# \x
=# SELECT * FROM bdr.bdr_conflict_history ORDER BY conflict_id DESC LIMIT 1;
-[ RECORD 1 ]------------+---------------------------------------------------
conflict_id | 51
local_node_sysid | 6371561413984311673
local_conflict_xid | 0
local_conflict_lsn | 3/8BF7BA38
local_conflict_time | 2017-01-25 10:37:45.561678+09
object_schema | public
object_name | pgbench_accounts
remote_node_sysid | 6371553825031594764
remote_txid | 3960157
remote_commit_time | 2017-01-25 10:34:30.564936+09
remote_commit_lsn | 2/D9831CC0
conflict_type | update_delete
conflict_resolution | skip_change
local_tuple |
remote_tuple | {"aid":1000001,"bid":4,"abalance":0,"filler":null}
local_tuple_xmin |
local_tuple_origin_sysid |
error_message |
error_sqlstate |
error_querystring |
error_cursorpos |
error_detail |
error_hint |
error_context |
error_columnname |
error_typename |
error_constraintname |
error_filename |
error_lineno |
error_funcname |
PostgreSQL Enterprise Consortium
Page 261 of 285
それぞれのーブルの状態を確認し、競合発生時の処理を確認します。
DELETEUPD ATEが破棄れています。
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
-----+-----+----------+--------
(0 )
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
-----+-----+----------+--------
(0 )
skip_change : 変更を無視し、破棄さ
4. INSERT vs DELETE
競合概要
一つのノードでINSERTしたデータがもう片方のノードでDELETEされデータと同じPRIMAR Y KEYの値を持つースを検証しました
検証結果
DELETEの処理が破棄されました。競合発生の状態にいてシステムカログから確認ることができませんでした。
競合発生手順
下記テーブルを初期状態とします
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
各ノードからそれぞINSER T/DELETEを実行し、INSERT vs DELE TE の競合を発生させます。
(node1のデータベースSQLを投入)
=# INSERT INTO pgbench_accounts (aid, bid, abalance) VALUES (1000002, 5, 0);
(node2のデータベースSQLを投入)
=# DELETE FROM pgbench_accounts WHERE aid = 1000002;
競合ログを「b dr.bd r_co n flict_h isto ryを利用して確認し競合の発生を確認します
競合は確認出来ませんでした。
PostgreSQL Enterprise Consortium
Page 262 of 285
(node1またはnode2の競合履歴ーブルに競合ログが出力されない)
=# \x
=# SELECT * FROM bdr.bdr_conflict_history ORDER BY conflict_id DESC LIMIT 1;
それぞれのーブルの状態を確認します。
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
1000002 | 5 | 0 |
(2 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
1000002 | 5 | 0 |
(2 )
5. DELETE vs DELETE
競合概要
2の異るノドで実行さDELETEが同じPRIMAR Y KE Yの値を持つデータを削除するースを検証しした
検証結果
DELETE/DELETEが競合した場合、片方のDELETEが無視され処理を完了しした
競合発生手順
下記テーブルを初期状態とします
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
---------+-----+----------+--------
1000001 | 1 | 0 |
(1 )
各ノードからそれぞDELE TEを実行し、DELETE vs DELETE の競合発生させます
(node1のデータベースSQLを投入)
=# DELETE FROM pgbench_accounts WHERE aid = 1000001;
(node2のデータベースSQLを投入)
=# DELETE FROM pgbench_accounts WHERE aid = 1000001;
競合ログを「b dr.bd r_co n flict_h isto ryを利用して確認し競合の発生を確認します
PostgreSQL Enterprise Consortium
Page 263 of 285
(node1またはnode2の競合履歴ーブルに競合ログが出力)
=# \x
=# SELECT * FROM bdr.bdr_conflict_history ORDER BY conflict_id DESC LIMIT 1;
-[ RECORD 1 ]------------+---------------------------------------------------------
conflict_id | 52
local_node_sysid | 6371561413984311673
local_conflict_xid | 0
local_conflict_lsn | 3/A193CA88
local_conflict_time | 2017-01-25 10:39:07.794699+09
object_schema | public
object_name | pgbench_accounts
remote_node_sysid | 6371553825031594764
remote_txid | 3960197
remote_commit_time | 2017-01-25 10:35:52.78243+09
remote_commit_lsn | 2/E8E9A388
conflict_type | delete_delete
conflict_resolution | skip_change
local_tuple |
remote_tuple | {"aid":1000001,"bid":null,"abalance":null,"filler":null}
local_tuple_xmin |
local_tuple_origin_sysid |
error_message |
error_sqlstate |
error_querystring |
error_cursorpos |
error_detail |
error_hint |
error_context |
error_columnname |
error_typename |
error_constraintname |
error_filename |
error_lineno |
error_funcname |
それぞれのーブルの状態を確認し、競合発生時の処理を確認します。
ローカル側のノードからD ELETEが無視されています。
(node1のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
-----+-----+----------+--------
(0 )
(node2のデータベースを確認)
=# SELECT * FROM pgbench_accounts WHERE aid >= 1000001;
aid | bid | abalance | filler
-----+-----+----------+--------
(0 )
skip_change : 変更を無視し、破棄さ
7.5.4.4.2.
1. 外部キー制約の競合
競合概要
1のノードで外部キー制約が定義されたテーブルに対してデータ挿入し、上記データ挿入がもう片方のノードに反映さ前に もう片方のノードに
おいて外部キーの参照先であるテーブルのデータを削除することで、外部キー制約が定義さーブルへのデータ挿入と、外部キー参照先テーブルに
対するデータ削除を競合させます
PostgreSQL Enterprise Consortium
Page 264 of 285
検証結果
外部キー制約に違反する処理が実施さ場合でもBD R エラーになら、データが外部キー制約違反の状態になりました
競合発生手順
下記の親子関係を持つーブルを作成します
(node1のデータベース接続)
=# CREATE TABLE parent(id integer primary key);
=# CREATE TABLE child(id integer primary key, parent_id integer not null references
parent(id));
=# INSERT INTO parent(id) VALUES (1), (2);
=# INSERT INTO child(id, parent_id) VALUES (11, 1), (12, 2);
各ノードからそれぞINSER T/DELETEを実行し、外部キー制約の競合を発生させます。
n o de1からINSERTno d e2では、子テーブルで参照されている親が存在せず n o de2D E LETEn o d e1で参照してい親データを削除し
としているので、それぞれ適用出来ななります
(node1のデータベースSQLを投入)
=# INSERT INTO child(id, parent_id) VALUES (21, 2);
(node2のデータベースSQLを投入)
=# DELETE FROM child WHERE parent_id = 2;
=# DELETE FROM parent WHERE id = 2;
それぞれのーブルの状態を確認し、競合発生時の処理を確認します。
(node1のデータベースを確認)
=# SELECT * FROM child;
id | parent_id
----+-----------
11 | 1
21 | 2
(2 )
=# SELECT * FROM parent;
id
----
1
(1 )
(node2のデータベースを確認)
=# SELECT * FROM child;
id | parent_id
----+-----------
11 | 1
21 | 2
(2 )
=# SELECT * FROM parent;
id
----
1
(1 )
外部キー制約違反のデータchildーブルに存在する
7.5.4.4.3.
1. 排他制約の競合
競合概要
排他な関係である2のデータを異なるノードから同時にテーブルにINSERTし、ノド間のデータに競合が発生するースを検証します
検証結果
一つのノードでINSERTれたデータをもう片方のノードに反映させる際に他制約違反が発生し、ノード間の接続が切断さます 競合を解消する
めにはオペレータでのデータ操作が必要となるめ注意が必要です。
競合発生手順
下記の排他制約を持つーブルを作成します
PostgreSQL Enterprise Consortium
Page 265 of 285
(node1のデータベースSQLを投入)
=# CREATE TABLE sample (aid integer primary key, range daterange, price integer);
=# ALTER TABLE sample ADD EXCLUDE USING gist (price WITH =, range WITH &&);
各ノードからそれぞINSER Tを実行し、排他制約の競合を発生させます。
[2012-04-18 2012-04/20]の期間が競合しているめに排他制約違反を起こしています
(node1のデータベースSQLを投入)
=# INSERT INTO sample VALUES(1, '[2012-04-16, 2012-04-20]', 10000);
(node2のデータベースSQLを投入)
=# INSERT INTO sample VALUES(2, '[2012-04-18, 2012-04-23]', 10000);
(node1またはnode2の競合履歴ーブルに競合ログが出力されない)
=# \x
=# SELECT * FROM bdr.bdr_conflict_history ORDER BY conflict_id DESC LIMIT 1;
それぞれのーブルの状態を確認し、競合発生時の処理を確認します。
他のノードで実行されデータ更新反映する際に、制約違反が発生し、BDRよるノード間の接続が切断されます。
(node1のデータベースを確認)
=# SELECT * FROM sample;
aid | range | price
-----+-------------------------+-------
1 | [2012-04-16,2012-04-21) | 10000
(1 )
(node2のデータベースを確認)
=# SELECT * FROM sample;
aid | range | price
-----+-------------------------+-------
2 | [2012-04-18,2012-04-24) | 10000
(1 )
PostgreSQL Enterprise Consortium
Page 266 of 285
(node1のデータベースログ)
bdr (6371561413984311673,2,42879,):receive LOG: starting logical decoding for slot
"bdr_42892_6371561413984311673_2_42879__"
bdr (6371561413984311673,2,42879,):receive DETAIL: streaming transactions committing
after 1/15D41640, reading WAL from 1/15D413B0
bdr (6371561413984311673,2,42879,):receive LOG: logical decoding found consistent point
at 1/15D413B0
bdr (6371561413984311673,2,42879,):receive DETAIL: There are no running transactions.
bdr (6371561413984311673,2,42879,):receive LOG: unexpected EOF on standby connection
LOG: starting background worker process "bdr (6371553825031594764,1,42892,)->bdr
(6371561413984311673,2,"
ERROR: conflicting key value violates exclusion constraint "sample_price_range_excl"
DETAIL: Key (price, range)=(10000, [2012-04-18,2012-04-24)) conflicts with existing key
(price, range)=(10000, [2012-04-16,2012-04-21)).
CONTEXT: apply INSERT from remote relation public.sample in commit 1/194FBC20, xid
3940666 commited at 2017-01-06 16:12:28.275376+09 (action #2) from node
(6371561413984311673,2,42879)
LOG: worker process: bdr (6371553825031594764,1,42892,)->bdr (6371561413984311673,2,
(PID 27843) exited with exit code 1
(node2のデータベースログ)
LOG: starting background worker process "bdr (6371561413984311673,2,42879,)->bdr
(6371553825031594764,1,"
ERROR: conflicting key value violates exclusion constraint "sample_price_range_excl"
DETAIL: Key (price, range)=(10000, [2012-04-16,2012-04-21)) conflicts with existing key
(price, range)=(10000, [2012-04-18,2012-04-24)).
CONTEXT: apply INSERT from remote relation public.sample in commit 1/15D41640, xid
3957701 commited at 2017-01-06 16:09:10.299493+09 (action #2) from node
(6371553825031594764,1,42892)
LOG: worker process: bdr (6371561413984311673,2,42879,)->bdr (6371553825031594764,1,
(PID 29311) exited with exit code 1
bdr (6371553825031594764,1,42892,):receive LOG: starting logical decoding for slot
"bdr_42879_6371553825031594764_1_42892__"
bdr (6371553825031594764,1,42892,):receive DETAIL: streaming transactions committing
after 1/194FB9D0, reading WAL from 1/194FB700
bdr (6371553825031594764,1,42892,):receive LOG: logical decoding found consistent point
at 1/194FB700
bdr (6371553825031594764,1,42892,):receive DETAIL: There are no running transactions.
bdr (6371553825031594764,1,42892,):receive LOG: unexpected EOF on standby connection
各ノードで制約違反が発生しBDRよる接続が切断されてしまう。解消のためリモートタプルが競合するローカルタプルを削除また変更する
制約違反の状態を解消するめに両側のデータUPDATEします。
(node1のデータベースSQLを投入)
=# UPDATE sample SET range = '[2012-04-11,2012-04-16]' WHERE aid = 1;
(node2のデータベースSQLを投入)
=# UPDATE sample SET range = '[2012-04-23,2012-04-29]' WHERE aid = 2;
PostgreSQL Enterprise Consortium
Page 267 of 285
(node1のデータベースを確認)
=# SELECT * FROM sample;
aid | range | price
-----+-------------------------+-------
1 | [2012-04-11,2012-04-17) | 10000
2 | [2012-04-23,2012-04-30) | 10000
(2 )
(node2のデータベースを確認)
=# SELECT * FROM sample;
aid | range | price
-----+-------------------------+-------
2 | [2012-04-23,2012-04-30) | 10000
1 | [2012-04-11,2012-04-17) | 10000
(2 )
7.5.4.4.4.
1. ローバルなデータの競合
競合概要
ロール(ーバルデータ)の情報がノード間で異なる状態で、他のノードに存在しないロールを利用した合に発生する合のケースを検証しました
検証結果
レプーション先のノードに同名のロールが存在しい場合、エラーになります エラーを解消するは、オペレータ側での操作が必要となるめ注意が
必要です。
競合発生手順
新規に作成したロールでテーブルを作成します。
(node1のデータベースSQLを投入)
=# CREATE ROLE testuser SUPERUSER LOGIN;
=# \c testuser
=# CREATE TABLE test01 (id integer primary key);
=# \d
レーションの一覧
スキーマ | 名前 | | 所有者
----------+--------+----------+----------
public | test01 | テーブ | testuser
(1 )
(node2のデータベースSQLを投入)
=# \d
レーションがありません。
ロールなどはレプリーシン対象となないので、そのロールで作成さーブルもレプリケーション対象とない
データベースログを確認し、ERRO Rが継続して出力されていれば競合が発生しています
PostgreSQL Enterprise Consortium
Page 268 of 285
(node2のデータベースログ)
LOG: starting background worker process "bdr (6371561413984311673,2,42879,)->bdr
(6371553825031594764,1,"
ERROR: role "testuser" does not exist
CONTEXT: during DDL replay of ddl statement: CREATE TABLE public.test01 (id
pg_catalog.int4 , CONSTRAINT test01_pkey PRIMARY KEY (id) ) WITH (oids=OFF)
apply QUEUED_DDL in commit 1/15DD2278, xid 3958054 commited at 2017-01-06
17:37:58.608995+09 (action #2) from node (6371553825031594764,1,42892)
LOG: worker process: bdr (6371561413984311673,2,42879,)->bdr (6371553825031594764,1,
(PID 30136) exited with exit code 1
権限は関係なく同名のロールが作成されば、競合は解決する
レプーションを再開させるめにロールなどのグローバルデータを作成します
(node2のデータベースSQLを投入)
=# CREATE ROLE testuser LOGIN;
=# \d
レーションの一覧
スキーマ | 名前 | | 所有者
----------+--------+----------+----------
public | test01 | テーブ | testuser
(1 )
7.5.4.4.5.
1. ロックの競合とデッドロックの中断
競合概要
一つのノードで取得したロックともう片方のノードで取得したロックが、デッドロッ状態となるケースを検証しした
検証結果
異なるノードで実行されたンザクションでデッドロック状態が発生した場合ロックが解除れるまでロック待ちが発生しす。 Postg reSQ Lおいて
デッドロックが発生した場合、デッロックを引き起こランザクションが自動でロールバッますが、 異なるノード間で発生したデッドロックにいて
検出できないため、ロック待状態が続きます
競合発生手順
下記テーブルを初期状態とします
(node1のデータベースSQLを投入)
=# CREATE TABLE sample (aid integer primary key, range daterange, price integer);
=# ALTER TABLE sample ADD EXCLUDE USING gist (price WITH =, range WITH &&);
=# INSERT INTO sample VALUES(1, '[2012-04-16, 2012-04-20]', 10000);
=# INSERT INTO sample VALUES(2, '[2012-04-21, 2012-04-30]', 12000);
PostgreSQL Enterprise Consortium
Page 269 of 285
(node1のデータベースを確認)
=# SELECT * FROM sample;
aid | range | price
-----+-------------------------+-------
1 | [2012-04-16,2012-04-21) | 10000
2 | [2012-04-21,2012-05-01) | 12000
(2 )
(node2のデータベースを確認)
=# SELECT * FROM sample;
aid | range | price
-----+-------------------------+-------
1 | [2012-04-16,2012-04-21) | 10000
2 | [2012-04-21,2012-05-01) | 12000
(2 )
1のノードからテーブルをロッもう片方のノードからUPDATEを実行し、ロック待ちの影響を受ける事を確認します ロックが解除されるまで、B D R
適用プロセスは待ちが発生します
(node1のデータベースSQLを投入)
=# BEGIN;
=# LOCK TABLE sample IN ACCESS EXCLUSIVE MODE;
=# SELECT pg_sleep(10);
=# END;
(node2のデータベースSQLを投入)
=# UPDATE sample SET price = 14000 WHERE aid = 2;
(ロック待ちなので競合ログが出力されない)
=# \x
=# SELECT * FROM bdr.bdr_conflict_history ORDER BY conflict_id DESC LIMIT 1;
7.5.4.4.6.
自動的には解決出来ないデータの相違が発生した場合は、以下設定使用して手動で調整する必要があります
レプリケーション環境を破壊するが可能であるため使用するには注意が必要で
1 b dr.do _n o t_rep licate(bo o lean) このパラータセットを持つトランザクションで行われた変更は、
他ノードへのレプリーシンのためにーに格納さない。
=# CREATE TABLE test (id int primary key, name text);
=# \q
PostgreSQL Enterprise Consortium
Page 270 of 285
(node1対してのみレコード追加を実行)
$ export PGOPTIONS='-c bdr.do_not_replicate=on'
$ psql -h node1 bdrtest
=# INSERT INTO test values(1, 'test');
=# SELECT * from test;
id | name
----+------
1 | test
(1 )
(node2は反映されいないことを確認)
=# SELECT * from test;
id | name
----+------
(0 )
2 b d r.sk ip_ddl_replica tion (b o o lean ) D D Lよる変更のレプリションをキップする。
一部のノードのみにDDLを実行したい場合に有効。
ーパーユーザのみが設定可能。
(node1のみーブルを作成)
=# BEGIN;
=# SET LOCAL bdr.skip_ddl_replication = true;
=# CREATE TABLE skip (id int primary key, name text);
=# END;
=# \d
レーションの一覧
スキーマ | 名前 | | 所有者
----------+--------+----------+----------
public | sample | テーブ | postgres
public | skip | テーブ | postgres
public | test | テーブ | postgres
(3 )
(node2は反映されいないことを確認)
=# \d
レーションの一覧
スキーマ | 名前 | | 所有者
----------+--------+----------+----------
public | sample | テーブ | postgres
public | test | テーブ | postgres
(2 )
3 b d r.permit_u n safe_ddl_co mman d s(boo lean ) 安全にレプリションできないスキーマの変更を許可する
ーパーユーザのみが設定可能。
以下のようデフォルトでは実行が許可されていないクエリを実行可能
* CREATE TAB LE AS
* ALTER TAB LE ... ADD CO LUM N ... DEFAU LT
* CREATE MATERIALIZED VIEW
* REF R E SH M ATERIALIZED VIEW
PostgreSQL Enterprise Consortium
Page 271 of 285
(デフォルトではエーとなる)
=# CREATE TABLE test2 AS SELECT * from test;
ERROR: CREATE TABLE AS is not supported when bdr is active
(エラーが出ないことを確認)
=# BEGIN;
=# SET LOCAL bdr.permit_unsafe_ddl_commands = true;
=# CREATE TABLE test2 AS SELECT * from test;
=# END;
7.5.4.5.
一部の競合パターンにて、意図しない動作が発生するめ、現段階では競合が発生しないパターンで利用すべきと考えす。
7.5.5.
7.5.5.1.
複数ノードで構成されるクラスタ環境内の1ードに障害が発生した場合でも、他ノードで継続利用可能か否かを確認します。 また、障害が発生したノードをクラスタ環
復旧させる順を確認します
7.5.5.2.
本検証で2で構成さB D R スタに対して、下記を実施しました
1. ノード障害
2. ノード復旧
7.5.5.3.
の環境 で検証を実施しました。
7.5.5.4.
7.5.5.4.1.
1. B D R の各ノード状態確認
B D R の各ノード間のプリションが正常に動作していることb d r.bdr_n o d esテーブルを用いて確認します
PostgreSQL Enterprise Consortium
Page 272 of 285
(node1実施)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r
<-- r(正常)であること確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r
<-- r(正常)であること確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest
<-- node1から作成さていとを確認
2. 検証用テーブルとデータの作成
pg b ebch を利用して、検証時に利用するーブルとデータを作成しす。
(node1実施)
$ pgbench -i -s 10 bdrtest
3. トランザクション実行
pg b ench を利用して、ノード1ンザションを継続的に実行します。 ノード2障害が発生した場合に、ノード1対して実行したトランザクションに
エラーが発生るか否かを確認します。
$ pgbench -h node1 -c 10 -t 100000 bdrtest
starting vacuum...end.
4. ノード障害
ノード2動作するPostgreSQ Lを停止させます。
(node2実施)
$ pg_ctl stop -m i
waiting for server to shut down..... done
server stopped
5. ノード1ログ確認
ノード2害時に出力さログメッセージを確認します 下記メッセージは出力されますがpgb en ch のトンザションは継続し実行可能です。
$ tail -f [PostgreSQLのログフイル]
LOG: starting background worker process "bdr (6367633348875313343,1,34478,)->bdr
(6369931070716042622,2,"
ERROR: establish BDR: could not connect to server: Connection refused
Is the server running on host "node2" (192.168.1.3) and accepting
TCP/IP connections on port 5432?
6. B D R の各ノード状態確認
ノード2害後、ノード状態が変化する否かを「bdr.bd r_n o desテーブルを用いて確認します
PostgreSQL Enterprise Consortium
Page 273 of 285
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)の状態のまま
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest
状態変化は確認できませんでした
7. ノードの切り離
障害が発生したノード2を切り離しするめ、「bdr.bd r_p a rt_by_n o d e_names」関数を実行します
(node1のデータベース接続)
=# SELECT bdr.bdr_part_by_node_names(ARRAY['node2']);
bdr_part_by_node_names
------------------------
(1 row)
8. ノードの切り離し結果確認
ノードの切り離し結果を「bd r.b d r_n o d es」テーブルを用いて確認します
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn , node_status, node_init_from_dsn FROM
bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | k <-- k(削除)であることを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest
9. システムカログの残データ削除
本手順は推奨さ手順ではありませんが、除状態のノードが「b dr.bd r_n o desテーブルに残っているとノード復旧が実行できないため暫定的な
対処です。 B DRIssu esで「bdr.bd r_co n n ection sのデータも削除する事が提案されていたので、こちらも暫定的な手順ですが実行します 詳細
下記をご参照下さい。
h ttps://githu b .com/2n d Q u ad ran t/bd r/issu es/97
h ttps://githu b .com/2n d Q u ad ran t/bd r/issu es/126
(node1のデータベース接続)
=# DELETE FROM bdr.bdr_connections USING bdr.bdr_nodes WHERE node_status = 'k' AND"
(node_sysid, node_timeline, node_dboid) = (conn_sysid, conn_timeline, conn_dboid);
=# DELETE FROM bdr.bdr_nodes where node_status = 'k';
10. ンザクション状態実行状態確認
PostgreSQL Enterprise Consortium
Page 274 of 285
手順1で実行したp g ben ch エラーが発生してないことを確認します。本検証ではエーは発生しませんでした
7.5.5.4.2.
B D R ノードの復旧方(ノード追加)する場合、既存ノードのデータベースと復旧させるノードのデータベースのスキーマおよびデータを同期させる必要があります ノード間の
データピーには、理コピーと物理コピーの2の手法があります。
h ttp://b dr-pro ject.o rg/d o cs/stable/fu n ction s-n od e-mg mt.h tml#FU NCTIO N-BD R -GRO U P-JO IN
7.8 ピー取得方法
1 bd r.b d r_gro u p_jo in
数実行
ユーザが指定したノード内データベースのスキーマとデータダンプを取得 pg _d u mpコマンドに相当
2 bd r_init_co pyマン ユーザが指定したノード上の全てのデータベーピーを取得 pg _b aseb acku pマンド
相当
論理コピーによる復旧
1. トランザクション実行
pg b ench を利用して、ノード1ンザションを継続的に実行します。 ノード2復旧するに、ノード1に対して行したトランザクションの停止が必
要か否か確認しす。
$ pgbench -h node1 -c 10 -t 100000 bdrtest
starting vacuum...end.
2. ノード2PostgreSQ L起動
ノード2で動作するPo stg reSQ Lを起動さます
$ pg_ctl start
3. B D R の無効化
ノード2データベースからB D R を削除しB DR拡張機能を削除します
(node2のデータベース接続)
=# SELECT bdr.remove_bdr_from_local_node(true);
WARNING: forcing deletion of possibly active BDR node
NOTICE: removing BDR from node
NOTICE: BDR removed from this node. You can now DROP EXTENSION bdr and,
if this is the last BDR node on this PostgreSQL instance, remove bdr from
shared_preload_libraries.
remove_bdr_from_local_node
----------------------------
=# DROP EXTENSION bdr;
DROP EXTENSION
4. データベース削除
B D R で利用したデータベースを削除します。
(node2のデータベース接続)
=# DROP DATABASE bdrtest ; 接続が残っており、削除できない場合PostgreSQLを再起動
DROP DATABASE
5. データベースの再作成
PostgreSQL Enterprise Consortium
Page 275 of 285
B D R で利用するデータべースを再度作成しす。
(node2のデータベース接続)
=# CREATE DATABASE bdrtest;
6. B D R 有効化
無効化しB D R を再度有効化します
(node2のデータベース接続)
=# CREATE EXTENSION btree_gist;
CREATE EXTENSION
=# CREATE EXTENSION bdr;
CREATE EXTENSION
7. ノードの追加
ノードを追加(復旧)せるめ、「bdr.bd r_gro u p _join関数を実行します。
(node2のデータベース接続)
=# SELECT bdr.bdr_group_join(
local_node_name := 'node2',
node_external_dsn := 'host=node2 port=5432 dbname=bdrtest',
join_using_dsn := 'host=node1 port=5432 dbname=bdrtest'
);
bdr_group_join
----------------
(1 )
8. ノード追加の確認待ち
ノードが追加さたこ確認するため、「bd r.b d r_n od e_join _w ait_for_ready関数実行しす。
(node2のデータベース接続)
=# SELECT bdr.bdr_node_join_wait_for_ready();
トランザクションが実行中の場合、上記関数の結果が戻りません。
n od e1PostgreSQ Lファイルに下記メッセージが出力さた後復旧の処理が開始さませ
(node1のログメセージ抜粋)
LOG: logical decoding found initial starting point at 0/BB399BF0
DETAIL: 10 transactions need to finish.
pg b ench マンドで実行中のトンザクシンを停止すると、下記ログメッセージが出力さ、復旧処理が開始さます
(node1のログメセージ抜粋)
LOG: logical decoding found consistent point at 0/B2895648
DETAIL: There are no running transactions.
LOG: exported logical decoding snapshot: "00046FE0-1" with 0 transaction IDs
9. B D R の各ノード状態確認
ノード2が追加されとを「bdr.bd r_n o des」テーブルの情報から確認します
PostgreSQL Enterprise Consortium
Page 276 of 285
(node1のデータベース接続)
=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest <-- node1から作
成さていとを確認
物理コピーによる復旧
1. トランザクション実行
pg b ench を利用して、ノード1ンザションを継続的に実行します。 ノード2復旧するに、ノード1に対して行したトランザクションの停止が必
要か否か確認しす。
$ pgbench -h node1 -c 10 -t 100000 bdrtest
starting vacuum...end.
2. ノード2PostgreSQ L停止確認
ノード2で動作するPo stg reSQ Lが停止していることを確認します
(node2実施)
$ pg_ctl status
pg_ctl: no server running
3. 物理コピーの取
ノード2で「bd r_in it_co p yマンドを実行し、n o d e1上のコピーを取得します。
(node2実施)
$ rm -rf $PGDATA/*
$ bdr_init_copy -D $PGDATA -n node2 -h node1 -p 5432 -d bdrtest
--local-host=node2 --local-port=5432 --local-dbname=bdrtest
bdr_init_copy: starting ...
Getting remote server identification ...
Detected 1 BDR database(s) on remote server
Updating BDR configuration on the remote node:
bdrtest: creating replication slot ...
bdrtest: creating node entry for local node ...
Creating base backup of the remote node...
50357/50357 kB (100%), 1/1 tablespace
Creating restore point on remote node ...
Bringing local node to the restore point ...
トランザクションログをリセットしす。
Initializing BDR on the local node:
bdrtest: adding the database to BDR cluster ...
All done
n od e1PostgreSQ Lファイルに下記メッセージが出力さた後復旧の処理が開始さませ
PostgreSQL Enterprise Consortium
Page 277 of 285
(node1のログメセージ抜粋)
LOG: logical decoding found initial starting point at 0/BB399BF0
DETAIL: 10 transactions need to finish.
pg b ench マンドで実行中のトンザクシンを停止すると、下記ログメッセージが出力さ 復旧処理が開始されます。
(node1のログメセージ抜粋
LOG: logical decoding found consistent point at 0/B2895648
DETAIL: There are no running transactions.
STATEMENT: SELECT
pg_create_logical_replication_slot('bdr_25434_6369931070716042622_2_25434__', 'bdr');
4. B D R の各ノード状態確認
ノード2が追加されとを「bdr.bd r_n o des」テーブルの情報から確認します
(node1のデータベース接続)
bdrtest=# SELECT node_name, node_local_dsn, node_status, node_init_from_dsn FROM
bdr.bdr_nodes;
-[ RECORD 1 ]------+------------------------------------
node_name | node1
node_local_dsn | host=node1 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn |
-[ RECORD 2 ]------+------------------------------------
node_name | node2
node_local_dsn | host=node2 port=5432 dbname=bdrtest
node_status | r <-- r(正常)であることを確認
node_init_from_dsn | host=node1 port=5432 dbname=bdrtest <-- node1から作
成さていとを確認
7.5.5.5.
ノード障害が発生した際にも、他のノードではトランザクションを継続実行するとが可能でした 障害ノードを復旧させるめにデータ操作が禁止されているシステムカタ
ログのデータ削除が必要でし
7.5.5.6.
ノード障害後おび復旧中にD D Lを実行すると下記のエラーが出力されます
=# CREATE TABLE test2(id int);
ERROR: No peer nodes or peer node count unknown, cannot acquire global lock
HINT: BDR is probably still starting up, wait a while
7.6. BDR性能検証
7.6.1.
7.6.1.1.
本試験はBD R 本来のユースケースである、 高レイテンシ環境との双方向レプリーシン環境における更新クエリのレスポンス改善とそれに伴う性能改善を確認した
です。
7.6.1.1.1.
PostgreSQL Enterprise Consortium
Page 278 of 285
今回は 2014年度検証報告書 可用性編) 記載さ東京-シンガポール間の回線情報(答速度76.95ms、帯域幅0.16Gb its/s)をもとに、 以下のよう環境
を構築しpg ben ch を実行しました
通常のストリーミングレプリーションであれば、 更新クエリを実行したい場合はシンガポールのマスノードに更新要求を実施する必要がありますが、 BDRでは最寄りの
ドに対して更新要求を実施するとが可能です。
7.6.1.1.2.
の環境 で検証を実施しました。
7.6.1.1.3.
1. 環境構築
pg b ench を実行する準備を行います。BDR, SR環境両方)
# pgbench -i test -U postgres -s 10
NOTICE: table "pgbench_history" does not exist, skipping
NOTICE: table "pgbench_tellers" does not exist, skipping
NOTICE: table "pgbench_accounts" does not exist, skipping
NOTICE: table "pgbench_branches" does not exist, skipping
creating tables...
100000 of 100000 tuples (100%) done (elapsed 0.25 s, remaining 0.00 s).
vacuum...
set primary keys...
done.
n od e1, n o de2ーブルが作成さていとを確認します。
# psql -U postgres test -c "\d"
リレションの一覧
スキーマ | | | 有者
----------+------------------+----------+----------
public | pgbench_accounts | ーブル | postgres
public | pgbench_branches | ーブル | postgres
public | pgbench_history | ーブル | postgres
public | pgbench_tellers | ーブル | postgres
(4 )
# /usr/pgsql-9.4/bin/psql -U postgres -h node2 test -c "\d"
リレションの一覧
スキーマ | | | 有者
----------+------------------+----------+----------
public | pgbench_accounts | ーブル | postgres
public | pgbench_branches | ーブル | postgres
public | pgbench_history | ーブル | postgres
public | pgbench_tellers | ーブル | postgres
(4 )
帯域制限及び遅延設定を行います。
PostgreSQL Enterprise Consortium
Page 279 of 285
clientnode2向け通信のみ制)
tc qdisc add dev eth0 root handle 1:0 htb
tc class add dev eth0 parent 1:0 classid 1:10 htb rate 160Mbit
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.0.12/32
flowid 1:10
tc qdisc add dev eth0 parent 1:10 handle 10:1 netem delay 38ms 1ms
node1node2向け通信のみ制限
tc qdisc add dev enp0s25 root handle 1:0 htb
tc class add dev enp0s25 parent 1:0 classid 1:10 htb rate 160Mbit
tc filter add dev enp0s25 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.0.12/32
flowid 1:10
tc qdisc add dev enp0s25 parent 1:10 handle 10:1 netem delay 38ms 1ms
node2両ノード向け通信とも制限)
tc qdisc add dev enp0s25 root handle 1:0 htb
tc class add dev enp0s25 parent 1:0 classid 1:0 htb rate 160Mbit
tc qdisc add dev enp0s25 parent 1:0 handle 10:1 netem delay 38ms 1ms
帯域制限の結果以下のな環境にります
7.9 帯域制限後のネットワーク情報
Client/Server client node1 n ode2
clien t 遅延:0.5 ms
帯域幅:934 M b its/s
遅延:76ms
帯域幅:160 M b its/s
n od e1 遅延:0.5 ms
帯域幅:934 M b its/s
遅延:76ms
帯域幅:160 M b its/s
n od e2 遅延:76ms
帯域幅:160 M b its/s
遅延:76ms
帯域幅:160 M b its/s
2. レスンスイム確認
更新クエリの応答速度を確認します
# time psql -h node1 -x -c "UPDATE pgbench_branches SET bbalance = bbalance + 100 WHERE
bid = 1" test
UPDATE 1
real 0m0.025s
user 0m0.001s
sys 0m0.001s
# time psql -h node2 -x -c "UPDATE pgbench_branches SET bbalance = bbalance + 100 WHERE
bid = 1" test
UPDATE 1
real 0m0.259s
user 0m0.001s
sys 0m0.000s
ネットワーク遅延に伴いレスポンスが低下していとを確認)
3. SR環境の性能試験
非同期SR構成のマスターに対しp gb en ch を実施します。
PostgreSQL Enterprise Consortium
Page 280 of 285
# pgbench -U postgres -p 5433 -h node2 -s 10 -c 10 test -T 180
scale option ignored, using count from pgbench_branches table (10)
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 10
query mode: simple
number of clients: 10
number of threads: 1
duration: 180 s
number of transactions actually processed: 3078
latency average: 584.795 ms
tps = 17.042442 (including connections establishing)
tps = 17.057455 (excluding connections establishing)
4. B D R 環境の性能試験
競合が発生していか確認するために、「bd r.b d r_con flict_h isto ryを参照し競合履歴数を確認します
# psql -h node1 -x -c "SELECT count(*) FROM bdr.bdr_conflict_history;" test
-[ RECORD 1 ]
count | 52265
# psql -h node2 -x -c "SELECT count(*) FROM bdr.bdr_conflict_history;" test
-[ RECORD 1 ]-
count | 132935
B D R 環境のノードにp g b en ch を実施します
# pgbench -U postgres -h node1 -s 10 -c 10 test -T 180
scale option ignored, using count from pgbench_branches table (10)
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 10
query mode: simple
number of clients: 10
number of threads: 1
duration: 180 s
number of transactions actually processed: 16677
latency average: 107.933 ms
tps = 92.598796 (including connections establishing)
tps = 92.602290 (excluding connections establishing)
競合が発生していいことを確認します。
# psql -h node1 -x -c "SELECT count(*) FROM bdr.bdr_conflict_history;" test
-[ RECORD 1 ]
count | 52265
# psql -h node2 -x -c "SELECT count(*) FROM bdr.bdr_conflict_history;" test
-[ RECORD 1 ]-
count | 132935
7.6.1.1.4.
本検証で以下を確認するとが出来ました
レスンスイムの低減
PostgreSQL Enterprise Consortium
Page 281 of 285
低レイテンシのサーバに更新クエリを実行可能であるため、レポンスタイムを低減することが出来した
TPS向上
レスンスイムが低減されため、TPSの向上が見られました
"17.057455" -> "92.602290"5.4倍)
し、本検証では片系のみに変更実施し競合が発生しないようにた試験だっため、このよう結果になったのと思ます
本検証で使用しているpgb en ch TCP-B イクな、現在の値に対して加算していくよう処理の場合、結果整合で競合解決することができないため 絶対に
合が発生しない構成が必要で
例)更新するテーブルを拠点ごとに分ける
7.7. まと
7.7.1. BDR
本検証でBDRの機能特徴おび主なユースースを上調査を実施した上でB D Rの動作検証および性能検証を実施しました 本検証で実施したB DRの動
作検証の結果は下表の通りです。
7.10 結果評価基準
問題なし。
用時に問題になるースがある
× 応していない。事実上使えない。
7.11 B DR検証結
1 ノード追/削除 ノード削除はオンラインで実行可能。ノード追加時にトランザクションの停止が必要。 また、削除したノード
を追加する場合システムカログの操作が必要。
2 グローバルシーケンス シーケンスの競合防ぐこが可能。ただし、マニュアルに記載さ制限事項にいては確認が必要。
3 択的レプリケーショ B DRを利用して任意のテーブルのデータ集約等を実現可能
4 新処理競合時の動作 更新が競合するパターンで意図しない動作が発生し、競合解消のため手動での操作が必要
5 ノード障害と復旧 ノード復旧時にはトランザクションの停止が必要。 また、障害が発生したード復旧させる際にシステムカ
ログの操作が必要。
本検証で利用したバージョン(1.0.2)では更新が競合するパターンで意図しない動作が発生するめ、B D R を適用する場合競合が発生しないようアプリケーシン設計
やテル設計が必要にります
) 更新するテーブルを拠点ごとに分ける
ノード障害時の運用においても、般的でないシステムカタログの操作を必要とするといった今後の改善が必要と思われる結果が確認されました
また、B D R 選択的レプリーションを用いることで、Po stgreSQ Lのストリーミングレプリーションでは実現できない、テーブル単位のレプリーシンが実現可能なとを確
認できました。 上記機能を用いて、システム間のデータ連携(ータ集約等)を柔軟に実現できる考えております
性能検証の結果より、ユースースで想定している「遠距離拠点間で双方向に更新する」場合にレスポンスイムの低減と処理向上につながるとが確認できました
机上で調査した通り、B D R を適用することで遠距離拠点間のトランザクション性能改善」や選択的レプリーシン機能を利用した柔軟なデータ連携」を実現できる
考えます
7.8. 参考文献
[B DR] Po stgres-BD R ドキュメント h ttp://b dr-pro ject.o rg/d o cs/stable/
7.8.1.
PostgreSQL Enterprise Consortium
Page 282 of 285
7.12 関数一
1 b dr.bd r_g ro u p _create fun ction s-n o de-mg mt.html
2 b dr.bd r_g ro u p _join fu n ction s-n o d e-mg mt.html
3 b dr.bd r_p art_by_no d e_n ames fu n ction s-n o d e-mg mt.h tml
4 b dr.remove_b dr_from_lo cal_n o d e fun ction s-n o de-mg mt.html
5 b dr.bd r_n o de_join _w ait_fo r_ready fun ction s-n o de-mg mt.html
6 b dr.tab le_set_replica tion _sets fun ction s-replicatio n -sets.h tml
7 b dr.tab le_get_replication _sets fu n ction s-replication -sets.h tml
8 b dr.con n ectio n _get_rep lication _sets fun ction s-rep licatio n -sets.html
7.8.2.
7.13 システムカタ
1 bd r.b d r_con flict_h isto ry catalo g -b dr-con flict-histo ry.html
2 bd r.b d r_n od es catalo g -b dr-n o des.h tml
3 bd r.b d r_con n ectio n s catalo g -b d r-co n n ectio n s.h tml
PostgreSQL Enterprise Consortium
Page 283 of 285
8.
本文書でPostg reSQ Lおけるレプリーション技術として標準機能として組み込まれているスリーミングレプリーションと ロジカルレプーションにいて取り上げまし
。さら、マルチマス構成に対応したB i-Directio n al Replication (B D R)いて取り上げました
ーミングレプーションは、20109月にリリースされPostgreSQ L9.0で標準機能として組み込まれ、徐々に実運用での利用される機会が増えるとともに、実運
用で必要となる機能改善がその後のバージョンアップで継続的に行ています
本文書でーミングレプーション構成を構築する基本的な手順を確認した上で、レプリケーションスロッ遅延レプリーシン、W AL圧縮といった新しい機能に
しても、定から実際の動作を確認するまでの具体的な手順を整理することができました障害発生時の運用にいてPostgreSQ L9.5から提供されるようになった
pg _rew in dマンドを使うとで、これまで必要とれていたフルバックアップ得を不要とする運用が可能になっていることを確認できました、複数台のスレーブが存
在するあるいはカスケードレプーションといったより複雑構成で障害が発生した場合の運用手順にいても確認しました
ロジカルレプリーションは201710月にリリPo stg reSQ L10.0で標準機能として組み込まれましたストリーミングレプリケーションと類似したアーキテャを
ちながら、テブル単位や更新種別単位で柔軟なレプリケーシン形態を取ったり複製先更新することができる等の特徴を有しています
本文書でロジカルレプリーシン構成を構築する基本的な手順、同期レプリーシン、複数Sub scriptionへのプリーション、カスード構成といった応用的使い
方、監視方法や障害発生時の挙動、レプリーション開始後のテーブル追加、定義変更の手順について検証しました検証結果より、現状のロジカルレプリーションは
柔軟にテーブル単位更新種別単位で複製できるとによりレプリーションの活用範囲が広がった一方で、更新競合解消する機能が貧弱なことやレプーションさ
SQ L、オブジェトが多数あといった制約事項もあるめ、現状では更新競合が発生しないよう複製先を参照用途に限定して利用するが現実的と考えます。
B D R 、現状のストリーミングレプリーションでは不可能なマルチマス構成に対応するとから、シングルマス構成に起因する課題解消が期待されます。今回の検証で
BDR 特徴、ユースース、ニズムを類似機能、製品と机上比較した上で、更新処理競合時の動作ノード障害時の動作、更新性能にいてそれぞれ検証し
ました。更新性能の検証結果り、ユースケースで想定してい遠距離拠点間で双方向に更新する合にレスポンスイムの低減とTPS向上につながるとがわかり
ました。
一方で、現時点のージョンでは更新が競合するパターンで意図しない動作が発生するめ、現段階で競合が発生しいパターンで利用すべきと考えます。そこで、
B D R の利用時競合が発生しにくーブル設計にするが望ましいです。また、ノード障害時の運用においても、一般的でないシステムカタログの操作必要とると
いった今後の改善が必要と思結果が確認されました
れらの結果からBDRいてユースケースと実際の利用用途が合致しているかを見極めた上で利用するかどうかを判断する要があるといえます。
今回の検証結果がストリーミングレプリケーション構成を実際に利用している方々の運用改善にながると、またロジカルレプリケーションやBD R を利用すべきかどうかを判
断する際の参考情報として活用いただけとを期待しています。
PostgreSQL Enterprise Consortium
Page 284 of 285
9.
企業・団体名順)
1.0
(2016年度W G3)
株式会社シスト データベース技術本部 竹内 尚也
株式会社シスト データベース技術本部 柘植 丈彦
株式会社ージス総研 プラットフォームサービス本部 IT基盤技術部 大西
TIS株式会社 IT基盤技術本部 IT基盤技術推進部 中西 剛紀
日本電信電話株式会社 ープンソースソフトウェセンタ 坂田 哲夫
株式会社富士通ソーシアルサイエンスボラ プラットフォームインテグレーション本部 第四システム部 小山田 政紀
株式会社富士通ソーシアルサイエンスボラ プラットフォームインテグレーション本部 第四システム部 高橋 勝平
株式会社富士通ソーシアルサイエンスボラ プラットフォームインテグレーション本部 第四システム部 香田 紗希
2.0
(2017年度W G3)
株式会社シスト サービ事業部 サポートセンタ 神谷 恵子
株式会社シスト データベース技術本部 技術統括部 竹内 尚也
株式会社シスト データベース技術本部 技術統括部 柘植 丈彦
株式会社ージス総研 プラットフォームサービス本部 IT基盤技術部 大西
TIS株式会社 IT基盤技術本部 中西 剛紀
株式会社富士通ソーシアルサイエンスボラ ソリューション開発センタ ソリューションビジネス 小山田 政紀
株式会社富士通ソーシアルサイエンスボラ 第二システ事業本部 第三システム部
PostgreSQL Enterprise Consortium
Page 285 of 285