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

47.2. ロジカルデコーディングのコンセプト #

<title>Logical Decoding Concepts</title>

47.2.1. ロジカルデコーディング #

<title>Logical Decoding</title>

Logical decoding is the process of extracting all persistent changes to a database's tables into a coherent, easy to understand format which can be interpreted without detailed knowledge of the database's internal state. ロジカルデコーディングは、データベースのテーブルへの恒久的な更新を、一貫性があって、データベース内部の状態に関する詳細な知識がなくても容易に理解できる形式として取得するプロセスです。

In <productname>PostgreSQL</productname>, logical decoding is implemented by decoding the contents of the <link linkend="wal">write-ahead log</link>, which describe changes on a storage level, into an application-specific form such as a stream of tuples or SQL statements. PostgreSQLにおいてロジカルデコーディングは、記憶装置のレベルで更新を記述する書き込み先行ログの内容を、タプルやSQL文のストリームといったアプリケーション固有の形式にデコードすることによって実装されています。

47.2.2. レプリケーションスロット #

<title>Replication Slots</title>

In the context of logical replication, a slot represents a stream of changes that can be replayed to a client in the order they were made on the origin server. Each slot streams a sequence of changes from a single database. ロジカルレプリケーションの文脈ではスロットは、元のサーバで行われた変更と同じ順序でクライアント上でリプレイできるようなストリームを表します。 それぞれのスロットは、単一のデータベース上の変更操作の連鎖をストリームとして流します。

注記

<para><productname>PostgreSQL</productname> also has streaming replication slots (see <xref linkend="streaming-replication"/>), but they are used somewhat differently there.

またPostgreSQLには、ストリーミングレプリケーションスロットがあります (26.2.5参照)。しかし、ここでの説明とは少し違う使い方がされています。

A replication slot has an identifier that is unique across all databases in a <productname>PostgreSQL</productname> cluster. Slots persist independently of the connection using them and are crash-safe. それぞれのレプリケーションスロットはPostgreSQLクラスタの中で一意な識別子を持っています。 スロットは、そのために使用される接続とは独立しており、クラッシュセーフです。

A logical slot will emit each change just once in normal operation. The current position of each slot is persisted only at checkpoint, so in the case of a crash the slot may return to an earlier LSN, which will then cause recent changes to be sent again when the server restarts. Logical decoding clients are responsible for avoiding ill effects from handling the same message more than once. Clients may wish to record the last LSN they saw when decoding and skip over any repeated data or (when using the replication protocol) request that decoding start from that LSN rather than letting the server determine the start point. The Replication Progress Tracking feature is designed for this purpose, refer to <link linkend="replication-origins">replication origins</link>. ロジカルスロットは、通常の操作においては、各々の変更操作を一度だけ送出します。 それぞれのスロットにおける現在位置は、チェックポイントのときにだけ永続的になります。 ですからクラッシュすると、スロットは以前のLSNに戻ってしまうかもしれませんし、サーバの再起動時には最近の変更が再送されることになります。 ロジカルデコーディングのクライアントは、同じメッセージを複数回扱うことによる好ましくない結果を避けることに対して責任を追っています。 クライアントはデコーディングの際に最後に確認したLSNを記録し、繰り返されるデータをスキップしたり、(レプリケーションプロトコルを使う場合に)サーバに開始時点を決めさせるのではなく、記録しておいたLSNからデコーディングを始めるように要求するかもしれません。 レプリケーション進捗追跡機能はこの目的のために設計されています。 replication originsを参照してください。

Multiple independent slots may exist for a single database. Each slot has its own state, allowing different consumers to receive changes from different points in the database change stream. For most applications, a separate slot will be required for each consumer. 単一のデータベース中に、お互いに独立した複数のスロットが存在しても構いません。 それぞれのスロットは自分自身の状態を持っており、データベース更新のストリーム上の別の場所から変更データを受信する異なる消費者があり得ます。 多くのアプリケーションにとっては、各消費者に対して個別のスロットが必要となるでしょう。

A logical replication slot knows nothing about the state of the receiver(s). It's even possible to have multiple different receivers using the same slot at different times; they'll just get the changes following on from when the last receiver stopped consuming them. Only one receiver may consume changes from a slot at any given time. ロジカルレプリケーションスロットは、受信者の状態については関知しません。 同時にでなければ、同じスロットを使う複数の異なる受信者を持つことさえできます。 その場合は、直近の受信者がストリームの消費を終了した時点から更新データを受信するだけです。 どの時点でも1つのスロットからの変更を消費できるのは1つの受信側だけです。

A logical replication slot can also be created on a hot standby. To prevent <command>VACUUM</command> from removing required rows from the system catalogs, <varname>hot_standby_feedback</varname> should be set on the standby. In spite of that, if any required rows get removed, the slot gets invalidated. It's highly recommended to use a physical slot between the primary and the standby. Otherwise, <varname>hot_standby_feedback</varname> will work but only while the connection is alive (for example a node restart would break it). Then, the primary may delete system catalog rows that could be needed by the logical decoding on the standby (as it does not know about the <literal>catalog_xmin</literal> on the standby). Existing logical slots on standby also get invalidated if <varname>wal_level</varname> on the primary is reduced to less than <literal>logical</literal>. This is done as soon as the standby detects such a change in the WAL stream. It means that, for walsenders that are lagging (if any), some WAL records up to the <varname>wal_level</varname> parameter change on the primary won't be decoded. ロジカルレプリケーションスロットは、ホットスタンバイ上でも作成できます。 システムカタログから必要な行をVACUUMが削除するのを防ぐためには、スタンバイ上でhot_standby_feedbackを設定する必要があります。 それでも、必要な行が削除されると、スロットは無効になります。 プライマリとスタンバイの間に物理スロットを使用することを強くお勧めします。 そうしないと、hot_standby_feedbackが動作するのは接続が生きている間だけです(たとえばノードの再起動で破壊されます)。 その場合、プライマリはスタンバイ上のロジカルデコーディングが必要とするシステムカタログ行を削除するかもしれません(スタンバイ上のcatalog_xminについては知らないため)。 既存のスタンバイ上のロジカルスロットも、プライマリ上のwal_levellogicalよりも小さくなると無効になります。 これはスタンバイがWALストリームでそのような変更を検出したときにすぐに行われます。 これは、遅れているwalsender(もしあれば)に対して、プライマリでのwal_levelパラメータの変更までの一部のWALレコードがデコードされないことを意味します。

Creation of a logical slot requires information about all the currently running transactions. On the primary, this information is available directly, but on a standby, this information has to be obtained from primary. Thus, slot creation may need to wait for some activity to happen on the primary. If the primary is idle, creating a logical slot on standby may take noticeable time. This can be sped up by calling the <function>pg_log_standby_snapshot</function> function on the primary. ロジカルスロットの作成には、現在実行中のすべてのトランザクションに関する情報が必要です。 プライマリではこの情報は直接利用できますが、スタンバイではこの情報をプライマリから取得する必要があります。 したがって、スロットの作成はプライマリで何らかのアクティビティが発生するのを待つ必要があるかもしれません。 プライマリがアイドル状態の場合、スタンバイ上でのロジカルスロットの作成にはかなりの時間がかかるかもしれません。 これは、プライマリでpg_log_standby_snapshot関数を呼び出すことで高速化できます。

注意

Replication slots persist across crashes and know nothing about the state of their consumer(s). They will prevent removal of required resources even when there is no connection using them. This consumes storage because neither required WAL nor required rows from the system catalogs can be removed by <command>VACUUM</command> as long as they are required by a replication slot. In extreme cases this could cause the database to shut down to prevent transaction ID wraparound (see <xref linkend="vacuum-for-wraparound"/>). So if a slot is no longer required it should be dropped. レプリケーションスロットは、クラッシュをまたがって永続し、消費者の状態については関知しません。 スロットを使う接続がない場合でも、消費者が必要としているリソースが削除されることを防ぎます。 これによりストレージが消費されます。何故ならば、関連するWALもシステムカタログの行も、レプリケーションスロットが必要とする限りVACUUMによって削除されないからです。 極端な場合、トランザクションIDの周回(24.1.5を参照)を防ぐためのデータベース停止をもたらす可能性があります。 したがって、必要でなくなったスロットは削除すべきです。

47.2.3. レプリケーションスロットの同期 #

<title>Replication Slot Synchronization</title>

The logical replication slots on the primary can be synchronized to the hot standby by using the <literal>failover</literal> parameter of <link linkend="pg-create-logical-replication-slot"> <function>pg_create_logical_replication_slot</function></link>, or by using the <link linkend="sql-createsubscription-params-with-failover"> <literal>failover</literal></link> option of <command>CREATE SUBSCRIPTION</command> during slot creation, and then calling <link linkend="pg-sync-replication-slots"> <function>pg_sync_replication_slots</function></link> on the standby. By setting <link linkend="guc-sync-replication-slots"> <varname>sync_replication_slots</varname></link> on the standby, the failover slots can be synchronized periodically in the slotsync worker. For the synchronization to work, it is mandatory to have a physical replication slot between the primary and the standby (i.e., <link linkend="guc-primary-slot-name"><varname>primary_slot_name</varname></link> should be configured on the standby), and <link linkend="guc-hot-standby-feedback"><varname>hot_standby_feedback</varname></link> must be enabled on the standby. It is also necessary to specify a valid <literal>dbname</literal> in the <link linkend="guc-primary-conninfo"><varname>primary_conninfo</varname></link>. It's highly recommended that the said physical replication slot is named in <link linkend="guc-synchronized-standby-slots"><varname>synchronized_standby_slots</varname></link> list on the primary, to prevent the subscriber from consuming changes faster than the hot standby. Even when correctly configured, some latency is expected when sending changes to logical subscribers due to the waiting on slots named in <link linkend="guc-synchronized-standby-slots"><varname>synchronized_standby_slots</varname></link>. When <varname>synchronized_standby_slots</varname> is utilized, the primary server will not completely shut down until the corresponding standbys, associated with the physical replication slots specified in <varname>synchronized_standby_slots</varname>, have confirmed receiving the WAL up to the latest flushed position on the primary server. プライマリ上のロジカルレプリケーションスロットは、ホットスタンバイと同期させることができます。 これは、スロットの作成時にpg_create_logical_replication_slotfailoverパラメータを指定するか、CREATE SUBSCRIPTIONfailoverオプションを指定したうえで、スタンバイでpg_sync_replication_slotsを呼び出すことで可能です。 スタンバイでsync_replication_slotsを設定すると、フェイルオーバースロットをスロット同期ワーカーによって定期的に同期させることができます。 同期を機能させるには、プライマリとスタンバイの間に物理レプリケーションスロットが必要であり(つまり、スタンバイでprimary_slot_nameが設定されている必要があります)、スタンバイではhot_standby_feedbackが有効になっている必要があります。 また、primary_conninfoに有効なdbnameを指定する必要があります。 この物理レプリケーションスロットを、プライマリのsynchronized_standby_slotsリスト内に指定することを強くお勧めします。 これは、サブスクライバーがホットスタンバイよりも早く変更を消費しないようにするためです。 正しく設定されていても、synchronized_standby_slots内に指定されたスロットを待つため、サブスクライバに変更を送信するときに多少の遅延が予想されます。 synchronized_standby_slotsが使用されている場合、synchronized_standby_slotsで指定された物理レプリケーションスロットに関連付けられた対応するスタンバイが、プライマリサーバ上の最新のフラッシュされた位置までWALを受信することを確認するまで、プライマリサーバは完全にはシャットダウンしません。

The ability to resume logical replication after failover depends upon the <link linkend="view-pg-replication-slots">pg_replication_slots</link>.<structfield>synced</structfield> value for the synchronized slots on the standby at the time of failover. Only persistent slots that have attained synced state as true on the standby before failover can be used for logical replication after failover. Temporary synced slots cannot be used for logical decoding, therefore logical replication for those slots cannot be resumed. For example, if the synchronized slot could not become persistent on the standby due to a disabled subscription, then the subscription cannot be resumed after failover even when it is enabled. フェイルオーバー後にロジカルレプリケーションを再開できるかどうかは、フェイルオーバー時のスタンバイ上で同期されていたスロットの持つpg_replication_slots.syncedの値によって決まります。 フェイルオーバー前に、スタンバイで同期状態が真となっている永続スロットだけが、フェイルオーバー後の論理レプリケーションに使用できます。 同期されていた一時スロットはロジカルデコーディングには使用できないため、これらのスロットによるロジカルレプリケーションは再開できません。 例えば、サブスクリプション無効になっているため、同期されたスロットがスタンバイ上で永続化できなかった場合、フェイルオーバー後にサブスクリプションを有効にしても、そのサブスクリプションは再利用できません。

To resume logical replication after failover from the synced logical slots, the subscription's 'conninfo' must be altered to point to the new primary server. This is done using <link linkend="sql-altersubscription-params-connection"><command>ALTER SUBSCRIPTION ... CONNECTION</command></link>. It is recommended that subscriptions are first disabled before promoting the standby and are re-enabled after altering the connection string. 同期されたロジカルスロットからフェイルオーバーの後にロジカルレプリケーションを再開するには、サブスクリプションの'conninfo'オプションを新しいプライマリサーバを指すように変更する必要があります。 これはALTER SUBSCRIPTION ... CONNECTIONを使用して行います。 スタンバイが昇格する前に先にサブスクリプションを無効にし、接続文字列を変更した後に再度有効にすることをお勧めします。

注意

There is a chance that the old primary is up again during the promotion and if subscriptions are not disabled, the logical subscribers may continue to receive data from the old primary server even after promotion until the connection string is altered. This might result in data inconsistency issues, preventing the logical subscribers from being able to continue replication from the new primary server. 昇格中に古いプライマリが再度起動する場合があります。 このときサブスクリプションが無効なっていない場合、サブスクライバは昇格後も接続文字列が変更されるまで、古いプライマリサーバからデータを受信し続ける可能性があります。 これによりデータの不整合の問題が生じ、サブスクライバが新しいプライマリからのレプリケーションを継続できなくなる可能性があります。

47.2.4. 出力プラグイン #

<title>Output Plugins</title>

Output plugins transform the data from the write-ahead log's internal representation into the format the consumer of a replication slot desires. 出力プラグインは、書き込み先行ログの内部データ表現を、レプリケーションスロットの消費者が必要とする形式に変換します。

47.2.5. スナップショットのエクスポート #

<title>Exported Snapshots</title>

When a new replication slot is created using the streaming replication interface (see <xref linkend="protocol-replication-create-replication-slot"/>), a snapshot is exported (see <xref linkend="functions-snapshot-synchronization"/>), which will show exactly the state of the database after which all changes will be included in the change stream. This can be used to create a new replica by using <link linkend="sql-set-transaction"><literal>SET TRANSACTION SNAPSHOT</literal></link> to read the state of the database at the moment the slot was created. This transaction can then be used to dump the database's state at that point in time, which afterwards can be updated using the slot's contents without losing any changes. ストリーミングレプリケーションのインタフェースを使って新しいスロットを作ると(CREATE_REPLICATION_SLOT参照)、スナップショットがエクスポートされます(9.28.5参照)。 このスナップショットはまさにその時点でのデータベースの状態を示しており、スナップショット以後のすべての変更は更新ストリームに含まれるようになります。 このことを利用して、スロットが作られた際のデータベースの状態をSET TRANSACTION SNAPSHOTを使って読み込むことにより、新しいレプリカを作ることができます。 このトランザクションは、その時点のデータベースの状態をダンプするために使用することができます。 また、スロットに含まれるデータを使って、ダンプした後で行われた更新を失うことなくデータベースを更新できます。

Creation of a snapshot is not always possible. In particular, it will fail when connected to a hot standby. Applications that do not require snapshot export may suppress it with the <literal>NOEXPORT_SNAPSHOT</literal> option. スナップショットの作成はいつでも可能なわけではありません。 とりわけ、ホットスタンバイに接続するときは失敗します。 スナップショットのエクスポートが必要ないアプリケーションは、NOEXPORT_SNAPSHOTオプションを使ってスナップショットのエクスポートを抑止できます。