PostgreSQL論理レプリケーションによるデータベース間のシームレスなデータ同期
Olivia Novak
Dev Intern · Leapcell

はじめに
今日のデータ中心の世界では、アプリケーションは複数のデータベースにまたがることが多く、データの整合性を保ち、ほぼリアルタイムの更新を提供する効率的なメカニズムが必要です。データウェアハウスの構築、マイクロサービスの通信の有効化、あるいは読み取りレプリカによる高可用性の確保のいずれであっても、異なるシステム間でデータを同期するという課題は普遍的です。バッチジョブやカスタムアプリケーションレベルのCDCのような従来のメカニズムは、複雑さ、遅延、および運用上のオーバーヘッドを招くことがよくあります。ここで、PostgreSQLの論理レプリケーションが強力でエレガントなソリューションとして登場します。ネイティブで堅牢、かつ高度に設定可能な方法で変更をキャプチャおよび適用でき、分散データ管理のアーキテクチャを大幅に簡素化します。この記事では、PostgreSQL論理レプリケーションの複雑さを探り、データベース間のシームレスなデータ同期と効率的な変更データキャプチャ(CDC)にどのように活用できるかを実証します。
論理レプリケーションの理解
PostgreSQL論理レプリケーションの能力を完全に理解するには、まずいくつかのコアコンセプトを理解することが不可欠です。
- 論理レプリケーション(Logical Replication): 物理的なストレージブロックではなく、論理的な表現(INSERT、UPDATE、DELETEステートメント)に基づいたデータオブジェクトとその変更のレプリケーション方法。これにより、異なるPostgreSQLメジャーバージョン間、あるいはカスタムデコーダーを使用してPostgreSQL以外のシステムへのレプリケーションが可能になります。
- 物理レプリケーション(Physical Replication): オペレーティングシステムファイルを含むデータベースクラスタ全体をブロックレベルでレプリケーションする従来のメソッド。これは主に、レプリカがプライマリの正確なコピーである障害復旧および読み取り専用レプリカのシナリオで使用されます。
- 先行書き込みログ(WAL): PostgreSQLのデータ整合性と耐久性を確保するためのコアメカニズム。データベースへのすべての変更は、実際のデータファイルに適用される前に、まずWALに書き込まれます。論理レプリケーションは、WALから直接データ変更を抽出します。
- パブリケーション(Publication): レプリケーションのためにマークされた、パブリッシャーデータベースのテーブル(またはオプションでスキーマ内のすべてのテーブル、あるいはデータベース内のすべてのテーブル)のセット。パブリッシャーは、送信するデータを定義します。
- サブスクリプション(Subscription): サブスクライバーデータベース上のパブリケーションへの接続。サブスクライバーは、パブリケーションから変更を受信して適用します。
- 論理デコーディング(Logical Decoding): バイナリWAL形式を、レプリケーションのために理解および処理しやすい論理形式(例:SQLステートメント、JSON、Avro)に変換するプロセス。
論理レプリケーションのメカニズム
PostgreSQL論理レプリケーションは、パブリッシャーのWALから変更をキャプチャし、それをサブスクライバーに送信することによって機能します。このプロセスは、いくつかのステップに分解できます。
- WAL生成: パブリッシャーデータベースでのDML操作(INSERT、UPDATE、DELETE)は、WALに対応するエントリを生成します。
- 論理デコーディング: 論理デコーディングプラグイン(組み込み論理レプリケーションのデフォルトである
pgoutput
など)が、これらのWALエントリを読み取り、変更の論理ストリームに変換します。 - パブリケーション: パブリッシャーは、レプリケートしたいテーブルまたはスキーマを指定するパブリケーションを作成します。これは、論理変更ストリームのフィルターとして機能します。
- サブスクリプション: サブスクライバーは、パブリッシャー上の特定のパブリケーションを指すサブスクリプションを作成します。
- データ転送: サブスクライバーはパブリッシャーに接続します。パブリッシャーは、サブスクライブされたテーブルの初期データのスナップショットをサブスクライバーに送信します。初期同期後、論理変更(INSERT、UPDATE、DELETE)をサブスクライバーに継続的にストリーミングします。
- 適用: サブスクライバーはこれらの論理変更を受信し、ローカルテーブルに適用して、データを効果的に同期します。
実装と例
2つのPostgreSQLインスタンス間で論理レプリケーションをセットアップする実践的な例を以下に示します。
前提条件:
2つのPostgreSQLインスタンス(例:pg1
とpg2
)が必要です。それらがネットワーク経由で通信できることを確認してください。この例では、pg1
がパブリッシャー、pg2
がサブスクライバーであると仮定します。
ステップ1:パブリッシャー (pg1
) 上でPostgreSQLを構成する
pg1
のpostgresql.conf
を編集し、以下のパラメータを設定します。
# /path/to/pg1/data/postgresql.conf wal_level = logical max_replication_slots = 10 # 必要に応じて調整 max_wal_senders = 10 # 必要に応じて調整
変更を有効にするためにpg1
インスタンスを再起動します。
次に、pg1
のpg_hba.conf
を開いて、サブスクライバーからの接続を許可します。次のような行を追加します(subscriber_ip
を実際のIPアドレスまたは範囲に置き換えてください)。
# /path/to/pg1/data/pg_hba.conf
host replication all subscriber_ip/32 md5
pg_hba.conf
を変更した場合は、pg1
を再度再起動します。
ステップ2:パブリッシャー (pg1
) 上でパブリケーションを作成する
スーパーユーザーまたはREPLICATION
権限を持つユーザーとしてpg1
に接続します。
-- pg1に接続 psql -h localhost -p 5432 -U postgres -- デモンストレーション用のデータベースとテーブルを作成 CREATE DATABASE publisher_db; \c publisher_db; CREATE TABLE products ( product_id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, price DECIMAL(10, 2) NOT NULL, last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 'products'テーブルのパブリケーションを作成 CREATE PUBLICATION my_publication FOR TABLE products; -- オプションで、現在のデータベースのすべてのテーブルをレプリケートするには: -- CREATE PUBLICATION my_all_tables_publication FOR ALL TABLES;
ステップ3:サブスクライバーデータベース (pg2
) を準備する
スーパーユーザーとしてpg2
に接続します。
-- pg2に接続 psql -h localhost -p 5433 -U postgres -- パブリッシャーと同じスキーマを持つデータベースとテーブルを作成します -- サブスクライバーテーブルのスキーマは互換性があることが(少なくとも同じ主キーと列名/型を持っていることが)重要です CREATE DATABASE subscriber_db; \c subscriber_db; CREATE TABLE products ( product_id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, price DECIMAL(10, 2) NOT NULL, last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
ステップ4:サブスクライバー (pg2
) 上でサブスクリプションを作成する
pg2
のsubscriber_db
から、サブスクリプションを作成します。
-- pg2のsubscriber_dbに接続 psql -h localhost -p 5433 -U postgres -d subscriber_db CREATE SUBSCRIPTION my_subscription CONNECTION 'host=localhost port=5432 user=postgres dbname=publisher_db password=your_pg1_password' PUBLICATION my_publication;
pg1
インスタンスの実際のホストとポート、およびpg1
のpostgres
ユーザーのパスワードをlocalhost
と5432
、your_pg1_password
に置き換えてください。
ステップ5:レプリケーションをテストする
次に、パブリッシャーにデータを挿入し、サブスクライバーで観察してみましょう。
pg1
( publisher_db
内) で:
INSERT INTO products (name, price) VALUES ('Laptop', 1200.00); INSERT INTO products (name, price) VALUES ('Mouse', 25.50); UPDATE products SET price = 1150.00 WHERE name = 'Laptop'; DELETE FROM products WHERE name = 'Mouse';
pg2
( subscriber_db
内) で:
SELECT * FROM products;
更新された価格のLaptop
エントリが表示され、Mouse
エントリは存在しないはずであり、レプリケーションが成功したことを示しています。
応用シナリオ
論理レプリケーションは非常に用途が広く、数多くのシナリオに応用できます。
- 変更データキャプチャ(CDC): 論理レプリケーションストリームを監視することにより、外部アプリケーションはデータベースの変更にリアルタイムで応答できます。これは、イベント駆動型アーキテクチャ、監査、またはストリーム処理の基本となります。
- データベース間データ同期: マイクロサービス、データマート、または地理的に分散されたアプリケーション間で一貫したデータを維持します。
- データウェアハウジングとETL: データウェアハウスにインクリメンタルに変更をフィードし、バルクデータロードの必要性を減らします。
- ゼロダウンタイムアップグレード: 古いPostgreSQLバージョンから新しいバージョンにデータをレプリケートし、メジャーバージョンアップグレード中のダウンタイムを最小限に抑えます。
- マルチマスター(アクティブ-アクティブ)レプリケーション(注意が必要): 通常、アプリケーションレイヤーでの追加の競合解決ロジックが必要ですが、論理レプリケーションはカスタムマルチマスターセットアップのバックボーンを形成できます。
- 選択的レプリケーション: 特定のテーブルまたはスキーマのみをレプリケートし、同期するデータに対するより詳細な制御を可能にします。これは物理レプリケーションでは不可能です。
- 外部システムとのデータ共有: カスタム論理デコーディングプラグインを使用すると、データをPostgreSQL以外のデータベースやメッセージキューにレプリケートでき、普遍的なデータ変更ストリームとして機能します。
結論
PostgreSQL論理レプリケーションは、データベース間のデータ同期や変更データキャプチャなどの重要なデータベース操作に対して、堅牢で効率的、かつネイティブなソリューションを提供します。WALとパブリケーション/サブスクリプションモデルを活用することで、データフローに対する詳細な制御を提供し、非常に回復力のある分散データアーキテクチャを可能にします。その汎用性により、最新のアプリケーション開発およびデータ管理にとって不可欠なツールとなり、開発者はエコシステム全体で一貫したデータを持つスケーラブルなシステムを構築できるようになります。