PostgreSQL におけるデータ同期戦略
PostgreSQL 環境において、データの一貫性を保ちながら複数ノード間で情報を共有するには、用途に応じた同期メカニズムの選定が不可欠です。主に物理層での複製、論理層での变更転送、外部ミドルウェアの活用、およびバッチ処理の 4 つのアプローチが存在します。選定の際は、遅延許容度、プラットフォームの異種性、および運用コストを考慮する必要があります。
1. 物理レプリケーション(ストリーミング複製)
この方式は、主サーバーの WAL(Write-Ahead Log)をバイナリレベルで従サーバーに転送します。データベース全体の物理的な同一性を保つ必要がある場合に最適です。
適用ケース
高可用性(HA)構成、災害復旧(DR)、およびミリ秒単位の遅延しか許容されない環境。
設定手順
- 主サーバーの設定
postgresql.confにて WAL 送信を有効化します。wal_level = replica max_wal_senders = 5 wal_keep_size = 1GB # 旧バージョンでは wal_keep_segmentspg_hba.confで複製ユーザーの接続を許可します。host replication repl_svc 192.168.10.5/32 scram-sha-256 - 従サーバーの初期化
pg_basebackupを使用してベースバックアップを取得します。
PostgreSQL 12 以降では、pg_basebackup -h 192.168.10.5 -D /var/lib/pgsql/data -U repl_svc -P -v -Rstandby.signalファイルを作成し、postgresql.confに接続情報を記述します。primary_conninfo = 'host=192.168.10.5 port=5432 user=repl_svc password=secret' - 同期開始
従サーバーを起動すると、自動的に主サーバーへ接続し、WAL の適用を開始します。
特徴:ほぼリアルタイムで同期されますが、従サーバーは読み取り専用となり、特定のテーブルのみを除外するなどの細かな制御は困難です。
2. 論理レプリケーション
論理レプリケーションは、特定のテーブルに対する INSERT、UPDATE、DELETE 操作のみを抽出して転送します。出版(Publication)と購読(Subscription)のモデルを採用しています。
適用ケース
バージョン間の移行、異なる OS 環境への複製、特定のテーブルのみを同期したい場合。
設定手順
- 公開側(Publisher)設定
postgresql.confで論理複製を有効にします。
対象テーブルを公開します。wal_level = logical max_replication_slots = 4CREATE PUBLICATION transit_pub FOR TABLE accounts, transactions; - 購読側(Subscriber)設定
接続情報を指定して購読を作成します。CREATE SUBSCRIPTION transit_sub CONNECTION 'host=192.168.10.5 port=5432 user=sub_user password=secret dbname=source_db' PUBLICATION transit_pub; - 動作確認
公開側でデータを変更し、購読側で反映されたか検証します。
特徴:テーブル単位の柔軟な選択が可能ですが、物理複製に比べオーバーヘッドがあり、PostgreSQL 10 以降が必要です。
3. 拡張機能と外部ツールの活用
標準機能之外的な要件がある場合、拡張機能や CDC ツールを導入します。
主要ツール
- pglogical:論理複製を拡張し、マルチマスターや列レベルの过滤を可能にします。
- Debezium:Kafka と連携し、変更履歴をストリームとして出力します。
pglogical 設定例
両ノードに拡張機能をインストール後、ノード定義を行います。
-- 公開側
SELECT pglogical.create_node('provider_node', 'host=192.168.10.5 dbname=src');
SELECT pglogical.create_replication_set('set_core');
SELECT pglogical.replication_set_add_table('set_core', 'users');
-- 購読側
SELECT pglogical.create_node('subscriber_node', 'host=192.168.10.6 dbname=dst');
SELECT pglogical.create_subscription(
'sub_core',
'host=192.168.10.5 dbname=src',
ARRAY['set_core']
);
4. スクリプトによるバッチ同期
リアルタイム性が求められない場合、定期的なデータエクスポートとインポートで対応可能です。
実装方法
pg_dump で特定テーブルをダンプし、対象サーバーでリストアします。
# データ抽出
pg_dump -h 192.168.10.5 -U admin -t users -d src_db -f users_dump.sql
# データ反映
psql -h 192.168.10.6 -U admin -d dst_db -f users_dump.sql
あるいは、PL/pgSQL 内のトリガーを用いて変更をログテーブルに記録し、別プロセスで転送する方法もあります。
特徴:構成は単純ですが、リアルタイム性はなく、作業中にロックが発生する可能性があります。
5. 適用遅延の制御
誤ったデータ変更が即座に複製されるのを防ぐため、従サーバーでの WAL 適用に遅延を設けることができます。
設定
従サーバーの設定ファイルで以下を指定します。
recovery_min_apply_delay = 10min
これにより、主サーバーでのコミットから 10 分経過するまで変更が反映されません。ただし、synchronous_commit と組み合わせる場合、主サーバーの待ち時間が増加しスループットに影響する可能性があります。
6. 手法の比較と選定ガイド
| 手法 | 遅延 | 柔軟性 | 構成コスト | 推奨ユースケース |
|---|---|---|---|---|
| 物理複製 | ミリ秒級 | 低 | 中 | HA、DR、完全一致が必要な場合 |
| 論理複製 | 秒級 | 高 | 低 | 表単位同步、バージョンアップ移行 |
| 外部ツール | 秒級 | 非常に高 | 高 | マルチマスター、異種 DB 連携 |
| バッチ処理 | 分級以上 | 低 | 低 | 夜間バッチ、データウェアハウス連携 |
高可用性が最優先であれば物理複製、特定のテーブルのみを別システムへ連携したい場合は論理複製または pglogical、大規模なイベント駆動アーキテクチャには Debezium の導入を検討します。