PostgreSQL データ同期の実装手法:レプリケーションと CDC

PostgreSQL におけるデータ同期戦略

PostgreSQL 環境において、データの一貫性を保ちながら複数ノード間で情報を共有するには、用途に応じた同期メカニズムの選定が不可欠です。主に物理層での複製、論理層での变更転送、外部ミドルウェアの活用、およびバッチ処理の 4 つのアプローチが存在します。選定の際は、遅延許容度、プラットフォームの異種性、および運用コストを考慮する必要があります。

1. 物理レプリケーション(ストリーミング複製)

この方式は、主サーバーの WAL(Write-Ahead Log)をバイナリレベルで従サーバーに転送します。データベース全体の物理的な同一性を保つ必要がある場合に最適です。

適用ケース

高可用性(HA)構成、災害復旧(DR)、およびミリ秒単位の遅延しか許容されない環境。

設定手順

  1. 主サーバーの設定
    postgresql.conf にて WAL 送信を有効化します。
    wal_level = replica
    max_wal_senders = 5
    wal_keep_size = 1GB  # 旧バージョンでは wal_keep_segments
    pg_hba.conf で複製ユーザーの接続を許可します。
    host    replication     repl_svc     192.168.10.5/32     scram-sha-256
  2. 従サーバーの初期化
    pg_basebackup を使用してベースバックアップを取得します。
    pg_basebackup -h 192.168.10.5 -D /var/lib/pgsql/data -U repl_svc -P -v -R
    PostgreSQL 12 以降では、standby.signal ファイルを作成し、postgresql.conf に接続情報を記述します。
    primary_conninfo = 'host=192.168.10.5 port=5432 user=repl_svc password=secret'
  3. 同期開始
    従サーバーを起動すると、自動的に主サーバーへ接続し、WAL の適用を開始します。

特徴:ほぼリアルタイムで同期されますが、従サーバーは読み取り専用となり、特定のテーブルのみを除外するなどの細かな制御は困難です。

2. 論理レプリケーション

論理レプリケーションは、特定のテーブルに対する INSERT、UPDATE、DELETE 操作のみを抽出して転送します。出版(Publication)と購読(Subscription)のモデルを採用しています。

適用ケース

バージョン間の移行、異なる OS 環境への複製、特定のテーブルのみを同期したい場合。

設定手順

  1. 公開側(Publisher)設定
    postgresql.conf で論理複製を有効にします。
    wal_level = logical
    max_replication_slots = 4
    対象テーブルを公開します。
    CREATE PUBLICATION transit_pub FOR TABLE accounts, transactions;
  2. 購読側(Subscriber)設定
    接続情報を指定して購読を作成します。
    CREATE SUBSCRIPTION transit_sub
    CONNECTION 'host=192.168.10.5 port=5432 user=sub_user password=secret dbname=source_db'
    PUBLICATION transit_pub;
  3. 動作確認
    公開側でデータを変更し、購読側で反映されたか検証します。

特徴:テーブル単位の柔軟な選択が可能ですが、物理複製に比べオーバーヘッドがあり、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 の導入を検討します。

タグ: PostgreSQL CDC レプリケーション,pglogical データベース同期

5月21日 01:47 投稿