Amazon Web Services ブログ
論理レプリケーションを使用してオンプレミスまたは Amazon EC2 から Amazon RDS に PostgreSQL を移行する
PostgreSQL は、オープンソースのリレーショナルデータベースの中でも最も人気のある先進的なシステムの 1 つです。30 年以上におよぶ開発作業を経ている PostgreSQL は、多数の複雑なデータワークロードを処理できる、信頼性が高く堅牢なデータベースであることが証明されています。PostgreSQL は、Oracle や Microsoft SQL Server などの商用データベースから移行する際に多くの人から選ばれるオープンソースデータベースです。クラウドの観点から、AWS は 2 つのマネージド PostgreSQL オプションを提供しています。それは、Amazon Relational Database Service (RDS) for PostgreSQL と Amazon Aurora for PostgreSQL です。
PostgreSQL データベースをオンプレミスから AWS マネージド PostgreSQL に移行またはアップグレードする場合、または AWS マネージドサービス内の PostgreSQL のメジャーバージョンにアップグレードする場合は、論理レプリケーションを使用して、ネイティブの PostgreSQL 機能を介して実行できます。pglogical
拡張機能は、バージョン 9.6.6 以降の Amazon RDS for PostgreSQL の一部で、コミュニティ PostgreSQL バージョン 9.4 以降で機能します。 pglogical
拡張機能は、バージョン 9.4 の環境から 9.6.6 以降の環境に移行する場合に適したオプションです。PostgreSQL は、バージョン 10 の組み込み機能としてネイティブ論理レプリケーションも導入しましたが、この記事では取り上げません。
AWS Database Migration Service (DMS) を使用すると、最小限のダウンタイムでオンプレミスの PostgreSQL を Amazon RDS for PostgreSQL に移行できます。AWS DMS には、セットアッププロセスが簡単など、いくつかの利点があります。また、プライマリキーを持たないテーブルを移行し、ソースデータベースとターゲットデータベース間でデータを検証することもできます。ただし、pglogical
が克服する必要がある 制限 もいくつかあります。
pglogical
は、次のシナリオで役立ちます。
- テーブルでより多くの bytea、jsonb、および enum データ型を使用する場合
- シーケンスをレプリケートする場合 (ターゲット DB でのシーケンスの自動インクリメント)
- データが切り捨てられてテーブルに頻繁に読み込まれる場合
- 独自のレプリケーションセットを作成する場合 (たとえば、ターゲットデータベースへの挿入と更新のみをレプリケートする場合)。これは AWS DMS の制限です
この記事では、論理レプリケーション (pglogical
拡張を使用)、pglogical
のユースケース、およびその制限について説明します。
論理レプリケーションの概要
論理レプリケーションは、レプリケーション ID (通常はプライマリキー) に基づいてデータオブジェクトとその変更をレプリケートする方法です。「論理」という用語は、正確なブロックアドレスとバイト単位のレプリケーションを使用する「物理」レプリケーションの対義語です。論理レプリケーションを使用すると、データベースからターゲットデータベースに変更をリアルタイムでストリーミングできます。
物理レプリケーションと論理レプリケーションの比較
物理レプリケーションは、バイナリ形式でレプリカにデータを送信します。バイナリレプリケーションは、全か無かの方法でクラスタ全体をレプリケーションします。バイナリレプリケーションを使って特定のテーブルまたはデータベースを取得する方法はありません。これは完全なクラスターレベルおよびインスタンスレベルのレプリケーションです。
論理レプリケーションは、データを論理形式でレプリカに送信します。さらに、論理レプリケーションは、1 つのテーブル、データベース、またはテーブル内の特定の列のデータを送信できます。
次の図は、論理レプリケーションのアーキテクチャを示しています
アーキテクチャには次の特長を備えています。
pglogical
は、物理ストリーミングレプリケーションのようにサーバーレベル全体ではなく、データベースレベルで機能します- プロバイダーは、追加のディスク書き込みオーバーヘッドを発生させることなく、複数のサブスクライバーに変更を送信できます
- あるサブスクライバーは、複数のデータベースからの変更を受け入れ、自動的に設定できる競合解決により変更間の競合を検出できます
- カスケードレプリケーションは、変更セットの転送の形式で実装されます
論理レプリケーションの仕組み
論理レプリケーションは、1 つ以上のサブスクライバーを備えたパブリッシュおよびサブスクライブメカニズムを使用します。これは、パブリッシャーノード上の 1 つ以上のパブリケーションにサブスクライブします。サブスクライバーはパブリケーションからデータをプルし、その後データを再パブリッシュして、カスケードレプリケーションまたはより複雑な設定が行えるようにします。
マスターノード (ソースデータベース) はパブリケーションを定義します。そのノードが publisher です。パブリッシャーは常に変更データ (DML) をサブスクライバーに送信し、データを複数のサブスクライバーに送信できます。
レプリカサーバー (ターゲットデータベース) はサブスクリプションを定義します。そのノードが subscriber です。サブスクライバーは、複数のパブリッシャーからのデータを受け入れ、変更をターゲットデータベースに適用します。
pglogical
は、論理デコードを使用して、データの変更点のみを非同期でレプリケートします。レプリケートされるのは違いのみであるため、これは非常に効率的です。また、障害の後で再開できるため、ネットワーク障害にも耐性があります。
Amazon RDS for PostgreSQL 9.6 以降のバージョンには、pglogical
が含まれています。これを使用して、マスターノード (パブリッシャー) とレプリカノード (サブスクライバー) 間の論理レプリケーションをセットアップできます。
次のシナリオで論理レプリケーションを使用できます。
- 単一のデータベースまたはデータベースのサブセットの増分変更が発生したときにサブスクライバーに送信する
- 複数のデータベースを単一のデータベースに統合する (たとえば、分析目的で)
- 複数のデータベース間でデータベースのサブセットを共有する
- あるメジャーバージョンから別のメジャーバージョンへデータベースをアップグレードする
- あるプラットフォームから別のプラットフォームへ移行する (オンプレミスまたは Amazon EC2 から Amazon RDS など)
pglogical の使用
この記事では、複数のデータベース (複数のパブリッシャー) から Amazon RDS for PostgreSQL (シングルスタンバイ) への論理レプリケーションをセットアップする方法を示します。この記事では、2 つの EC2 インスタンスを使用します。これらのインスタンス上のコミュニティ PostgreSQL には pglogical
拡張機能がインストールされています。Amazon RDS for PostgreSQL にはデフォルトで pglogical
拡張機能があります。これは、バージョン 9.6 以降に pglogical
サポートが含まれているためですが、コミュニティ PostgreSQL の場合、この拡張機能を個別にインストールして設定する必要があります。
この記事では、単一の RHEL-7 EC2 インスタンス (PostgreSQL 9.6 および PostgreSQL 10) で実行される 2 つの PostgreSQL メジャーバージョンを使用しています。
前提条件
始める前に、両方のバージョンの PostgreSQL の postgresql.conf
にリストされているパラメータを設定します。ソースデータベースとターゲットデータベースの pg_hba.conf
ファイルでレプリケーションユーザーがパラメータ rds.logical_replication
を有効にできるようにします。
ソースデータベースの設定
ソースデータベースを設定するには、次の手順を実行します。
- ソースデータベースの
postgresql.conf
で、次のパラメータを編集します。 - 最初のソースで、PostgreSQL インスタンスを再起動してこれらのパラメータを有効にします。
- 設定されたパラメータを表示するには、次のコードを入力してください。
次のスクリーンショットは、このクエリの出力を示します。
- 2 番目のソースで、PostgreSQL インスタンスを再起動してこれらのパラメータを有効にします。
- 設定されたパラメータを表示するには、次のコードを入力してください。
次のスクリーンショットは、このクエリの出力を示します。
pg_hba.conf
で、pg_hba.conf
のレプリケーションユーザーが PostgreSQL インスタンスに接続できるようにします。- PostgreSQL インスタンスをリロードします。
pg_hba.conf
で次の変更を確認できます。 - PostgreSQL インスタンス (
source-1
とsource-2
) をリロードします。次のコードを参照してください。
ターゲット DB パラメータグループの設定
Amazon RDS for PostgreSQL には、デフォルトで pglogical
拡張子が付属しています。ターゲット DB パラメータグループを設定するには、次の手順を実行します。
- 拡張機能を有効にするには、ターゲットデータベースで、データベースのパラメータグループに
rds.logical_replication = 1
およびshared_preload_libraries = 'pglogical'
を設定します。 - これらのパラメータを有効にするには、RDS インスタンスを再起動します。
- パラメータがターゲットデータベースに設定されているかどうかを確認するには、次のコードを入力します。
次のスクリーンショットは、このクエリの出力を示します。
Amazon RDS では、rds.logical_replication
を有効にするたびに、レプリケーションエントリがpg_hba
ルールに追加されます。これを確認するには、次のコードを入力します。次のスクリーンショットは、ターゲットデータベースのレプリケーションユーザーのための
pg_hba.conf
のルールを示しています。
論理レプリケーションのセットアップ
これで、EC2 ホスト上の複数のデータベース間の論理レプリケーションを設定する準備ができました。次の手順を実行します。
pglogical rpm
をダウンロードして、ソースデータベースにインストールします。
PostgreSQL 9.6 の場合、次のコードを入力します。PostgreSQL 10 の場合、次のコードを入力します。
これで、ソースデータベースとターゲットデータベースに
pglogical
拡張を作成できます。- ソースデータベースで、次のコードを使用して
pglogical
拡張を作成します。次のスクリーンショットは、
pglogical's
バージョンがソースデータベースにあることを示しています。
pglogical
スキーマおよびその他のオブジェクトは、pglogical
スキーマの下に作成されます。これは、レプリケーションの情報を維持するのに役立ちます。
次のコードは、ターゲットデータベースにpglogical
拡張を作成します。次のコードは、
pglogical
がターゲットデータベースにあることを示します。次のスクリーンショットは、
pglogical
がターゲットデータベースにあることを示しています。
- ソースデータベースにパブリケーションサーバーを作成し、テーブルとシーケンスをレプリケーションセットに追加します (ポイント 8 で説明)。
- PostgreSQL 9.6 の場合、次のコードで
source-1
のテーブルとシーケンスのリストを確認します。次のスクリーンショットは、
source-1
データベースに存在するシーケンスとテーブルのリストを示しています。
- PostgreSQL 10 の場合、次のコードで
source-2
のテーブルとシーケンスのリストを確認します。次のスクリーンショットは、source-2 データベースに存在するシーケンスとテーブルのリストを示しています。
- パブリケーションサーバーを作成する前に、PostgreSQL (バージョン 9.6 と 10) からスキーマダンプを取得し、それをターゲットの Amazon RDS for PostgreSQL に復元します。ダンプを使用してこれを行うことができ、ネイティブの PostgreSQL ユーティリティを使用して復元できます (
pgdump -s
がダンプを取得し、psql -f<file>
が復元する)。 - 次のコードを使用して、ソースデータベースにパブリッシャーを作成します。
次のスクリーンショットは、
source-1
およびsource-2
データベースでのパブリッシャーノードの作成を示しています。
次のpglogical.node_interface
テーブルのスクリーンショットは、追加されたノードのエントリを示しています。
- テーブルとシーケンスをデフォルトのレプリケーションセットに追加します。次のコードを参照してください。
次のスクリーンショットは、
source-1
およびsource-2
データベースのレプリケーションセットへシーケンスとテーブルを追加したことを示しています。
前のスクリーンショットでは、レプリケーションセットにシーケンスが追加されています。これにより、ターゲットのシーケンスカウンターが増加します。
これで、ソースデータベース (バージョン 9.6 と 10) からスキーマダンプを取得して、それをターゲットの Amazon RDS for PostgreSQL データベースに復元し、ターゲットデータベースにサブスクリプションサーバーを作成できます。 - ターゲットデータベースのテーブルとシーケンスを一覧表示するには、次のコードを入力します。
次のスクリーンショットは、ターゲットデータベースに存在するシーケンスとテーブルを一覧表示したものです。
- ターゲットデータベースに 1 つのサブスクライバーと 2 つのサブスクリプションを作成します。次のコードを参照してください。
次のスクリーンショットは、ターゲットデータベースに作成されたサブスクライバーを示しています。
- 次のコードを使用して、
source-1
とsource-2
のターゲットデータベースにサブスクリプションを作成します。次のスクリーンショットは、ターゲットデータベースで作成されたサブスクリプションを示しています。
- データをソースインスタンスにロードする前に、ソース PostgreSQL (9.6、10) とターゲット RDS PostgreSQL 11 のテーブルの行数を比較します。
次のスクリーンショットは、ソースデータベースとターゲットデータベースのテーブルの行数の比較を示しています。
次のスクリーンショットは、挿入ステートメントを含む小さな for ループスクリプトを示しています。これにより、データをソースデータベースにロードします。
次のスクリーンショットは、データのロード前後のソースデータベースとターゲットデータベース間のテーブル数を比較しています。
テーブルデータはソースデータベースとターゲットデータベース間でレプリケートされますが、シーケンスについてはどうでしょうか? レプリケーションセットに追加されたシーケンスの状態は、リアルタイムではなく定期的にレプリケートされます。
次のスクリーンショットは、シーケンスがレプリケーションセットに追加された場合の、ソースデータベースとターゲットデータベースでのシーケンスの動作を示しています。
シーケンスを使用して初期データをロードしている間に、シーケンス値はソースからターゲットデータベースにすぐにレプリケートされます。ただし、後のロードサイクル中に、シーケンスデータをレプリケートするのに時間がかかる場合があります。前述のように、シーケンスの同期は連続的でもリアルタイムでもありません。pglogical
は、ターゲットデータベースのシーケンスを定期的に同期します。
次のスクリーンショットは、ソースデータベースとターゲットデータベースのシーケンスの増分値を示しています。
この記事では、pglogical
がシーケンスをターゲットデータベースにレプリケートするのに時間がかかりました (3 分以上)。 - レプリカに切り替えるときに、
pglogical.synchronize_sequence
関数を実行して、ターゲットデータベースのすべてのシーケンスを同期します。現在のプライマリへのアプリケーション接続が切断された後に、これを実行する必要があります。次のコードを参照してください。次のスクリーンショットは、前述のコードを入力した後のソースデータベースとターゲットデータベースでのシーケンスの同期を示しています。
動的バッファーは、レプリケートされる値に使用します。これにより、サブスクライバーがシーケンスの将来の状態を受信できるようにします。こうすることで、サブスクライバーのシーケンスのlast_value
が遅れる可能性を最小限に抑えられますが、可能性を完全に排除するわけではありません。synchronize_sequence
を呼び出して、データベースの重要なイベント (データの読み込み中やオンラインアップグレード中など) の後で、すべてのサブスクライバーが特定のシーケンスに関する最新の情報を持っていることを確認できます。
pglogical の制限
pglogical
の使用には、次の制限があります。
- これを書いている時点では、
pglogical
のレプリケーションと管理にはスーパーユーザー権限が必要です。その後、より細かい権限に拡張される可能性があります。 UNLOGGED
テーブルとTEMPORARY
テーブルは、物理ストリーミングレプリケーションと同じ様に、レプリケートされず、さらにレプリケートすることもできません。これは、これらのテーブルの DML が WAL ログ (トランザクションログ) にエントリを持たず、論理ワーカープロセスがこれらのテーブルで発生する変更をキャプチャすることが難しいためです。- 複数のデータベースをレプリケートする場合は、それぞれに個別のプロバイダーとサブスクライバーの関係をセットアップする必要があります。PostgreSQL インストールのすべてのデータベースのレプリケーションを一度に設定することはできません。
- プライマリまたはその他の有効なレプリカ ID がないテーブルに対しては、
UPDATE
およびDELETE
関数をレプリケートすることはできません。たとえば、UNIQUE
レプリケーションは、一意の識別子がないため、更新または削除するテーブルを見つけることができません。Bucardo や slony などのトリガーベースのツールを含む、市場に出回っている他のツールと同様に、pglogical
では、DML をキャプチャするためにテーブルにプライマリキーまたは一意のキーが必要です。 - プロバイダーからサブスクライバーに DDL を自動的にレプリケートする方法はありません。
pglogical
は、pglogical.replicate_ddl_command
関数を提供して、DDL をプロバイダーとサブスクライバーで一貫したポイントで実行できるようにします。たとえば、[pglogical.replicate_ddl_command('alter table public.migration1 add column surname varchar(20)');
] を選択します。 TRUNCATE...CASCADE
を使用すると、プロバイダー側のCASCADE
オプションのみが適用されます。
まとめ
この記事では、論理レプリケーションと物理レプリケーションの違い、ユースケース、論理レプリケーションの利点、および pglogical
拡張機能と組み込みの論理レプリケーションを使用して、PostgreSQL の異なるバージョン間で論理レプリケーションを実装する方法について説明しました。論理レプリケーションは、標準のストリーミングレプリケーションメカニズムよりも実行しやすく簡単な方法でテーブルをレプリケートします。ただし、いくつかの制限があり、この制限がレプリケーションに使用するかどうかの決定に影響するかもしれません。
著者について
Rajesh Madiwale は、アマゾン ウェブ サービスのアソシエイトコンサルタントです。彼は、Amazon RDS for PostgreSQL、Aurora PostgreSQL、Redshift、MySQL、Greenplum データベースでのデータベース開発と管理に関する深い専門知識を持っています。彼は PostgreSQL コミュニティの熱心なメンバーであり、任期を通して PostgreSQL に取り組んできました。彼はまた、PostgreSQL カンファレンスの複数のセッションで講演しました。