バージョンごとのドキュメント一覧

29.2. サブスクリプション #

<title>Subscription</title>

A <firstterm>subscription</firstterm> is the downstream side of logical replication. The node where a subscription is defined is referred to as the <firstterm>subscriber</firstterm>. A subscription defines the connection to another database and set of publications (one or more) to which it wants to subscribe. サブスクリプションは論理レプリケーションの下流側です。 サブスクリプションが定義されたノードはサブスクライバーとして参照されます。 サブスクリプションは他のデータベースへの接続と、サブスクリプション対象の一つ以上のパブリケーションの集合を定義します。

The subscriber database behaves in the same way as any other PostgreSQL instance and can be used as a publisher for other databases by defining its own publications. サブスクライバーのデータベースは、他のPostgreSQLインスタンスと同様に振る舞い、自分用のパブリケーションを定義することにより、他のデータベースに対するパブリッシャーとして利用できます。

A subscriber node may have multiple subscriptions if desired. It is possible to define multiple subscriptions between a single publisher-subscriber pair, in which case care must be taken to ensure that the subscribed publication objects don't overlap. サブスクライバーノードは、必要ならば複数のサブスクリプションを持つことができます。 一組のパブリッシャーとサブスクライバーの間で複数のサブスクリプションを定義することもできますが、サブスクライブしたパブリケーションオブジェクトが重複しないように注意が必要です。

Each subscription will receive changes via one replication slot (see <xref linkend="streaming-replication-slots"/>). Additional replication slots may be required for the initial data synchronization of pre-existing table data and those will be dropped at the end of data synchronization. 各々のサブスクリプションは、一つのレプリケーションスロット(26.2.6を参照)を通じて更新が通知されます。 既存のテーブルデータを初期同期するために、追加でレプリケーションスロットが必要になることもあります。それらはデータ同期の終了時に削除されます。

A logical replication subscription can be a standby for synchronous replication (see <xref linkend="synchronous-replication"/>). The standby name is by default the subscription name. An alternative name can be specified as <literal>application_name</literal> in the connection information of the subscription. 論理レプリケーションのサブスクリプションは、同期レプリケーション(26.2.8参照)のスタンバイであっても構いません。 スタンバイ名称はデフォルトではサブスクリプション名となります。 サブスクリプションのコネクション情報の中のapplication_nameを別の名前として指定することもできます。

Subscriptions are dumped by <command>pg_dump</command> if the current user is a superuser. Otherwise a warning is written and subscriptions are skipped, because non-superusers cannot read all subscription information from the <structname>pg_subscription</structname> catalog. 現在のユーザがスーパーユーザならば、サブスクリプションはpg_dumpでダンプできます。 そうでない場合には、警告が出力され、サブスクリプションはスキップされます。 非スーパーユーザはすべてのサブスクリプション情報を、pg_subscriptionカタログから読み出せないからです。

The subscription is added using <link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link> and can be stopped/resumed at any time using the <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION</command></link> command and removed using <link linkend="sql-dropsubscription"><command>DROP SUBSCRIPTION</command></link>. サブスクリプションはCREATE SUBSCRIPTIONで追加し、ALTER SUBSCRIPTIONを使って、いつでも停止、再開でき、そしてDROP SUBSCRIPTIONで削除できます。

When a subscription is dropped and recreated, the synchronization information is lost. This means that the data has to be resynchronized afterwards. サブスクリプションが削除され、そして再作成されると、同期情報は失われます。 このことは、後でデータを再同期しなければならないことを意味します。

The schema definitions are not replicated, and the published tables must exist on the subscriber. Only regular tables may be the target of replication. For example, you can't replicate to a view. スキーマ定義情報はレプリケーションされないので、パブリッシュするテーブルはサブスクライバーに存在しなければなりません。 通常のテーブルだけがレプリケーションの対象です。 たとえば、ビューはレプリケーションできません。

The tables are matched between the publisher and the subscriber using the fully qualified table name. Replication to differently-named tables on the subscriber is not supported. パブリッシャーとサブスクライバーの間でのテーブルの照合は、完全修飾されたテーブル名に基づいて行われます。 サブスクライバーで異なる名前になっているテーブルに対するレプリケーションは、サポートされていません。

Columns of a table are also matched by name. The order of columns in the subscriber table does not need to match that of the publisher. The data types of the columns do not need to match, as long as the text representation of the data can be converted to the target type. For example, you can replicate from a column of type <type>integer</type> to a column of type <type>bigint</type>. The target table can also have additional columns not provided by the published table. Any such columns will be filled with the default value as specified in the definition of the target table. However, logical replication in binary format is more restrictive. See the <link linkend="sql-createsubscription-params-with-binary"><literal>binary</literal></link> option of <command>CREATE SUBSCRIPTION</command> for details. テーブルの列も名前で照合されます。 サブスクライバーのテーブルでの列の順序はパブリッシャーと一致している必要はありません。 データのテキスト表現列が対象の型に変換可能である限り、列のデータ型も一致している必要がありません。 例えば、integer型の列からbigint型の列にレプリケーションすることができます。 対象テーブルはパブリッシュされたテーブルにない追加の列を持つこともできます。 そうした列には対象テーブルの定義の指定に従ってデフォルト値が挿入されます。 しかしながら、バイナリ形式の論理レプリケーションはより制限的です。 詳細は、CREATE SUBSCRIPTIONbinaryオプションを参照してください。

29.2.1. レプリケーションスロットの管理 #

<title>Replication Slot Management</title>

As mentioned earlier, each (active) subscription receives changes from a replication slot on the remote (publishing) side. 前述のように、各々の(有効な)サブスクリプションは、リモート(パブリッシュしている)側のレプリケーションスロットに対する変更を受信します。

Additional table synchronization slots are normally transient, created internally to perform initial table synchronization and dropped automatically when they are no longer needed. These table synchronization slots have generated names: <quote><literal>pg_%u_sync_%u_%llu</literal></quote> (parameters: Subscription <parameter>oid</parameter>, Table <parameter>relid</parameter>, system identifier <parameter>sysid</parameter>) 追加的なテーブル同期スロットは通常一時的なもので、初期テーブル同期を実行するために内部的に作成され、不要になった時に自動的に削除されます。 これらのテーブル同期スロットにはpg_%u_sync_%u_%llu(パラメータは、サブスクリプションoid、テーブルrelid、システム識別子sysid)という名前が生成されます。

Normally, the remote replication slot is created automatically when the subscription is created using <link linkend="sql-createsubscription"> <command>CREATE SUBSCRIPTION</command></link> and it is dropped automatically when the subscription is dropped using <link linkend="sql-dropsubscription"><command>DROP SUBSCRIPTION</command></link>. In some situations, however, it can be useful or necessary to manipulate the subscription and the underlying replication slot separately. Here are some scenarios: 通常、リモートのレプリケーションスロットはCREATE SUBSCRIPTIONでサブスクリプションが作成されるときに自動的に作成され、サブスクリプションがDROP SUBSCRIPTIONで削除されるときに自動的に削除されます。 しかしながら、状況によっては、サブスクリプションとその下にあるレプリケーションスロットを別々に操作することが有用であったり必要であったりします。 以下にいくつかシナリオを示します。

  • When creating a subscription, the replication slot already exists. In that case, the subscription can be created using the <literal>create_slot = false</literal> option to associate with the existing slot. サブスクリプションを作る際、レプリケーションスロットがすでに存在しています。 この場合、create_slot = falseオプションを使ってサブスクリプションを作成し、既存のスロットと関連付けることができます。

  • When creating a subscription, the remote host is not reachable or in an unclear state. In that case, the subscription can be created using the <literal>connect = false</literal> option. The remote host will then not be contacted at all. This is what <application>pg_dump</application> uses. The remote replication slot will then have to be created manually before the subscription can be activated. サブスクリプションを作成する際に、リモートホストが接続できない状態にあるか、不明な状況にあります。 こうした時は、connect = falseを使ってサブスクリプションを作成することができます。 リモートホストにはまったく接続しません。 これは、pg_dumpが使っている方法です。 サブスクリプションを有効にする前に、リモートホストのレプリケーションスロットを手動で作成しなければなりません。

  • When dropping a subscription, the replication slot should be kept. This could be useful when the subscriber database is being moved to a different host and will be activated from there. In that case, disassociate the slot from the subscription using <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION</command></link> before attempting to drop the subscription. サブスクリプションを削除する際に、レプリケーションスロットを維持する必要があります。 サブスクライバーのデータベースが別のホストに移動中で、移動後にそこからデータベースを起動するときに有効です。 この場合、サブスクリプションを削除する前に、ALTER SUBSCRIPTIONでそのスロットを切り離します。

  • When dropping a subscription, the remote host is not reachable. In that case, disassociate the slot from the subscription using <command>ALTER SUBSCRIPTION</command> before attempting to drop the subscription. If the remote database instance no longer exists, no further action is then necessary. If, however, the remote database instance is just unreachable, the replication slot (and any still remaining table synchronization slots) should then be dropped manually; otherwise it/they would continue to reserve WAL and might eventually cause the disk to fill up. Such cases should be carefully investigated. サブスクリプションを削除する際に、リモートホストに接続できません。 この場合、サブスクリプションを削除する前に、ALTER SUBSCRIPTIONでそのスロットを切り離しを試みます。 リモートデータベースインスタンスが存在しない場合は、これ以上の操作は必要ありません。 しかし、単にリモートデータベースに接続できない状態ならば、レプリケーションスロット(および、未だ残っている全てのテーブル同期スロット)を手動で削除する必要があります。 そうでなければ、WALが保存され続け、いずれディスクを埋め尽くすかもしれません。 そのような状態は注意深く調査する必要があります。

29.2.2. 例: 論理レプリケーションの設定 #

<title>Examples: Set Up Logical Replication</title>

Create some test tables on the publisher. パブリッシャーでいくつかテストテーブルを作成します。

test_pub=# CREATE TABLE t1(a int, b text, PRIMARY KEY(a));
CREATE TABLE
test_pub=# CREATE TABLE t2(c int, d text, PRIMARY KEY(c));
CREATE TABLE
test_pub=# CREATE TABLE t3(e int, f text, PRIMARY KEY(e));
CREATE TABLE

Create the same tables on the subscriber. サブスクライバーに同じテーブルを作成します。

test_sub=# CREATE TABLE t1(a int, b text, PRIMARY KEY(a));
CREATE TABLE
test_sub=# CREATE TABLE t2(c int, d text, PRIMARY KEY(c));
CREATE TABLE
test_sub=# CREATE TABLE t3(e int, f text, PRIMARY KEY(e));
CREATE TABLE

Insert data to the tables at the publisher side. パブリッシャー側のテーブルにデータを挿入します。

test_pub=# INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
INSERT 0 3
test_pub=# INSERT INTO t2 VALUES (1, 'A'), (2, 'B'), (3, 'C');
INSERT 0 3
test_pub=# INSERT INTO t3 VALUES (1, 'i'), (2, 'ii'), (3, 'iii');
INSERT 0 3

Create publications for the tables. The publications <literal>pub2</literal> and <literal>pub3a</literal> disallow some <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link> operations. The publication <literal>pub3b</literal> has a row filter (see <xref linkend="logical-replication-row-filter"/>). テーブルのパブリケーションを作成します。 パブリケーションpub2pub3aでは、一部のパブリッシュ操作が許可されません。 パブリケーションpub3bには行フィルタがあります(29.4を参照)。

test_pub=# CREATE PUBLICATION pub1 FOR TABLE t1;
CREATE PUBLICATION
test_pub=# CREATE PUBLICATION pub2 FOR TABLE t2 WITH (publish = 'truncate');
CREATE PUBLICATION
test_pub=# CREATE PUBLICATION pub3a FOR TABLE t3 WITH (publish = 'truncate');
CREATE PUBLICATION
test_pub=# CREATE PUBLICATION pub3b FOR TABLE t3 WHERE (e > 5);
CREATE PUBLICATION

Create subscriptions for the publications. The subscription <literal>sub3</literal> subscribes to both <literal>pub3a</literal> and <literal>pub3b</literal>. All subscriptions will copy initial data by default. パブリケーションのサブスクリプションを作成します。 サブスクリプションsub3は、pub3apub3bの両方をサブスクライブします。 デフォルトでは、すべてのサブスクリプションによって初期データがコピーされます。

test_sub=# CREATE SUBSCRIPTION sub1
test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=sub1'
test_sub-# PUBLICATION pub1;
CREATE SUBSCRIPTION
test_sub=# CREATE SUBSCRIPTION sub2
test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=sub2'
test_sub-# PUBLICATION pub2;
CREATE SUBSCRIPTION
test_sub=# CREATE SUBSCRIPTION sub3
test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=sub3'
test_sub-# PUBLICATION pub3a, pub3b;
CREATE SUBSCRIPTION

Observe that initial table data is copied, regardless of the <literal>publish</literal> operation of the publication. パブリケーションのパブリッシュ操作に関係なく、初期テーブルデータがコピーされることに注意してください。

test_sub=# SELECT * FROM t1;
 a |   b
---+-------
 1 | one
 2 | two
 3 | three
(3 rows)

test_sub=# SELECT * FROM t2;
 c | d
---+---
 1 | A
 2 | B
 3 | C
(3 rows)

Furthermore, because the initial data copy ignores the <literal>publish</literal> operation, and because publication <literal>pub3a</literal> has no row filter, it means the copied table <literal>t3</literal> contains all rows even when they do not match the row filter of publication <literal>pub3b</literal>. さらに、最初のデータコピーではパブリッシュ操作が無視され、パブリケーションpub3aには行フィルタがないため、コピーされたテーブルt3には、パブリケーションpub3bの行フィルタに一致しない場合でもすべての行が含まれていることになります。

test_sub=# SELECT * FROM t3;
 e |  f
---+-----
 1 | i
 2 | ii
 3 | iii
(3 rows)

Insert more data to the tables at the publisher side. パブリッシャー側のテーブルにさらにデータを挿入します。

test_pub=# INSERT INTO t1 VALUES (4, 'four'), (5, 'five'), (6, 'six');
INSERT 0 3
test_pub=# INSERT INTO t2 VALUES (4, 'D'), (5, 'E'), (6, 'F');
INSERT 0 3
test_pub=# INSERT INTO t3 VALUES (4, 'iv'), (5, 'v'), (6, 'vi');
INSERT 0 3

Now the publisher side data looks like: パブリッシャー側のデータは次のようになります。

test_pub=# SELECT * FROM t1;
 a |   b
---+-------
 1 | one
 2 | two
 3 | three
 4 | four
 5 | five
 6 | six
(6 rows)

test_pub=# SELECT * FROM t2;
 c | d
---+---
 1 | A
 2 | B
 3 | C
 4 | D
 5 | E
 6 | F
(6 rows)

test_pub=# SELECT * FROM t3;
 e |  f
---+-----
 1 | i
 2 | ii
 3 | iii
 4 | iv
 5 | v
 6 | vi
(6 rows)

Observe that during normal replication the appropriate <literal>publish</literal> operations are used. This means publications <literal>pub2</literal> and <literal>pub3a</literal> will not replicate the <literal>INSERT</literal>. Also, publication <literal>pub3b</literal> will only replicate data that matches the row filter of <literal>pub3b</literal>. Now the subscriber side data looks like: 通常のレプリケーションでは、適切なパブリッシュ操作が使用されていることに注意してください。 これは、パブリケーションpub2およびpub3aINSERTをレプリケーションしないことを意味します。 また、パブリケーションpub3bpub3bの行フィルタに一致するデータのみをレプリケーションします。 サブスクライバー側のデータは次のようになります:

test_sub=# SELECT * FROM t1;
 a |   b
---+-------
 1 | one
 2 | two
 3 | three
 4 | four
 5 | five
 6 | six
(6 rows)

test_sub=# SELECT * FROM t2;
 c | d
---+---
 1 | A
 2 | B
 3 | C
(3 rows)

test_sub=# SELECT * FROM t3;
 e |  f
---+-----
 1 | i
 2 | ii
 3 | iii
 6 | vi
(4 rows)

29.2.3. 例: レプリケーションスロットの遅延作成 #

<title>Examples: Deferred Replication Slot Creation</title>

There are some cases (e.g. <xref linkend="logical-replication-subscription-slot"/>) where, if the remote replication slot was not created automatically, the user must create it manually before the subscription can be activated. The steps to create the slot and activate the subscription are shown in the following examples. These examples specify the standard logical decoding output plugin (<literal>pgoutput</literal>), which is what the built-in logical replication uses. リモートレプリケーションスロットが自動的に作成されない場合(例えば29.2.1)があり、その場合、サブスクリプションをアクティブにする前に、ユーザが手動で作成しなければなりません。 スロットを作成してサブスクリプションをアクティブにする手順を、次の例に示します。 これらの例では、標準のロジカルデコード出力プラグイン(pgoutput)を指定しています。これは、組み込みの論理レプリケーションが使用するものです。

First, create a publication for the examples to use. まず、サンプルで使用するパブリケーションを作成します。

test_pub=# CREATE PUBLICATION pub1 FOR ALL TABLES;
CREATE PUBLICATION

Example 1: Where the subscription says <literal>connect = false</literal> 例1: サブスクリプションがconnect = falseと記述されている場合

  • Create the subscription. サブスクリプションを作成します。

    test_sub=# CREATE SUBSCRIPTION sub1
    test_sub-# CONNECTION 'host=localhost dbname=test_pub'
    test_sub-# PUBLICATION pub1
    test_sub-# WITH (connect=false);
    WARNING:  subscription was created, but is not connected
    HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
    CREATE SUBSCRIPTION
    
  • On the publisher, manually create a slot. Because the name was not specified during <literal>CREATE SUBSCRIPTION</literal>, the name of the slot to create is same as the subscription name, e.g. "sub1". パブリッシャーで、スロットを手動で作成します。 CREATE SUBSCRIPTION時に名前が指定されていないため、作成するスロットの名前はサブスクリプション名と同じになります。たとえば、"sub1"です。

    test_pub=# SELECT * FROM pg_create_logical_replication_slot('sub1', 'pgoutput');
     slot_name |    lsn
    -----------+-----------
     sub1      | 0/19404D0
    (1 row)
    
  • On the subscriber, complete the activation of the subscription. After this the tables of <literal>pub1</literal> will start replicating. サブスクライバーで、サブスクリプションのアクティブ化を完了します。 これにより、pub1のテーブルはレプリケーションを開始します。

    test_sub=# ALTER SUBSCRIPTION sub1 ENABLE;
    ALTER SUBSCRIPTION
    test_sub=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION;
    ALTER SUBSCRIPTION
    

Example 2: Where the subscription says <literal>connect = false</literal>, but also specifies the <link linkend="sql-createsubscription-params-with-slot-name"><literal>slot_name</literal></link> option. 例2: サブスクリプションがconnect = falseと記述されているが、slot_nameオプションも指定されている場合。

  • Create the subscription. サブスクリプションを作成します。

    test_sub=# CREATE SUBSCRIPTION sub1
    test_sub-# CONNECTION 'host=localhost dbname=test_pub'
    test_sub-# PUBLICATION pub1
    test_sub-# WITH (connect=false, slot_name='myslot');
    WARNING:  subscription was created, but is not connected
    HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
    CREATE SUBSCRIPTION
    
  • On the publisher, manually create a slot using the same name that was specified during <literal>CREATE SUBSCRIPTION</literal>, e.g. "myslot". パブリッシャーで、CREATE SUBSCRIPTION時に指定したものと同じ名前を使用して、スロットを手動で作成します。例えば、"myslot"です。

    test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput');
     slot_name |    lsn
    -----------+-----------
     myslot    | 0/19059A0
    (1 row)
    
  • On the subscriber, the remaining subscription activation steps are the same as before. サブスクライバーでは、残りのサブスクリプションのアクティブ化手順は以前と同じです。

    test_sub=# ALTER SUBSCRIPTION sub1 ENABLE;
    ALTER SUBSCRIPTION
    test_sub=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION;
    ALTER SUBSCRIPTION
    

Example 3: Where the subscription specifies <literal>slot_name = NONE</literal> 例3: サブスクリプションがslot_name = NONEを指定している場合

  • Create the subscription. When <literal>slot_name = NONE</literal> then <literal>enabled = false</literal>, and <literal>create_slot = false</literal> are also needed. サブスクリプションを作成します。 slot_name = NONEの場合、enabled = falsecreate_slot = falseも必要です。

    test_sub=# CREATE SUBSCRIPTION sub1
    test_sub-# CONNECTION 'host=localhost dbname=test_pub'
    test_sub-# PUBLICATION pub1
    test_sub-# WITH (slot_name=NONE, enabled=false, create_slot=false);
    CREATE SUBSCRIPTION
    
  • On the publisher, manually create a slot using any name, e.g. "myslot". パブリッシャーで、"myslot"などの名前を使用してスロットを手動で作成します。

    test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput');
     slot_name |    lsn
    -----------+-----------
     myslot    | 0/1905930
    (1 row)
    
  • On the subscriber, associate the subscription with the slot name just created. サブスクライバーで、先ほど作成したスロット名にサブスクリプションを関連付けます。

    test_sub=# ALTER SUBSCRIPTION sub1 SET (slot_name='myslot');
    ALTER SUBSCRIPTION
    
  • The remaining subscription activation steps are same as before. 残りのサブスクリプションのアクティブ化手順は、以前と同じです。

    test_sub=# ALTER SUBSCRIPTION sub1 ENABLE;
    ALTER SUBSCRIPTION
    test_sub=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION;
    ALTER SUBSCRIPTION