aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/catalogs.sgml309
-rw-r--r--doc/src/sgml/config.sgml41
-rw-r--r--doc/src/sgml/filelist.sgml1
-rw-r--r--doc/src/sgml/func.sgml2
-rw-r--r--doc/src/sgml/logical-replication.sgml396
-rw-r--r--doc/src/sgml/monitoring.sgml74
-rw-r--r--doc/src/sgml/postgres.sgml1
-rw-r--r--doc/src/sgml/protocol.sgml721
-rw-r--r--doc/src/sgml/ref/allfiles.sgml6
-rw-r--r--doc/src/sgml/ref/alter_publication.sgml139
-rw-r--r--doc/src/sgml/ref/alter_subscription.sgml139
-rw-r--r--doc/src/sgml/ref/create_publication.sgml206
-rw-r--r--doc/src/sgml/ref/create_subscription.sgml176
-rw-r--r--doc/src/sgml/ref/drop_publication.sgml107
-rw-r--r--doc/src/sgml/ref/drop_subscription.sgml110
-rw-r--r--doc/src/sgml/ref/pg_dump.sgml21
-rw-r--r--doc/src/sgml/ref/psql-ref.sgml28
-rw-r--r--doc/src/sgml/reference.sgml6
18 files changed, 2482 insertions, 1 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 493050618df..7c758a5081a 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -241,6 +241,16 @@
</row>
<row>
+ <entry><link linkend="catalog-pg-publication"><structname>pg_publication</structname></link></entry>
+ <entry>publications for logical replication</entry>
+ </row>
+
+ <row>
+ <entry><link linkend="catalog-pg-publication-rel"><structname>pg_publication_rel</structname></link></entry>
+ <entry>relation to publication mapping</entry>
+ </row>
+
+ <row>
<entry><link linkend="catalog-pg-range"><structname>pg_range</structname></link></entry>
<entry>information about range types</entry>
</row>
@@ -286,6 +296,11 @@
</row>
<row>
+ <entry><link linkend="catalog-pg-subscription"><structname>pg_subscription</structname></link></entry>
+ <entry>logical replication subscriptions</entry>
+ </row>
+
+ <row>
<entry><link linkend="catalog-pg-tablespace"><structname>pg_tablespace</structname></link></entry>
<entry>tablespaces within this database cluster</entry>
</row>
@@ -5271,6 +5286,137 @@
</sect1>
+ <sect1 id="catalog-pg-publication">
+ <title><structname>pg_publication</structname></title>
+
+ <indexterm zone="catalog-pg-publication">
+ <primary>pg_publication</primary>
+ </indexterm>
+
+ <para>
+ The catalog <structname>pg_publication</structname> contains all
+ publications created in the database. For more on publications see
+ <xref linkend="logical-replication-publication">.
+ </para>
+
+ <table>
+ <title><structname>pg_publication</structname> Columns</title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>References</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><structfield>oid</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry></entry>
+ <entry>Row identifier (hidden attribute; must be explicitly selected)</entry>
+ </row>
+
+ <row>
+ <entry><structfield>pubname</structfield></entry>
+ <entry><type>Name</type></entry>
+ <entry></entry>
+ <entry>Name of the publication</entry>
+ </row>
+
+ <row>
+ <entry><structfield>pubowner</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
+ <entry>Owner of the publication</entry>
+ </row>
+
+ <row>
+ <entry><structfield>puballtables</structfield></entry>
+ <entry><type>bool</type></entry>
+ <entry></entry>
+ <entry>If true, this publication automatically includes all tables
+ in the database, including any that will be created in the future.
+ </entry>
+ </row>
+
+ <row>
+ <entry><structfield>pubinsert</structfield></entry>
+ <entry><type>bool</type></entry>
+ <entry></entry>
+ <entry>If true, <command>INSERT</command> operations are replicated for
+ tables in the publication.</entry>
+ </row>
+
+ <row>
+ <entry><structfield>pubupdate</structfield></entry>
+ <entry><type>bool</type></entry>
+ <entry></entry>
+ <entry>If true, <command>UPDATE</command> operations are replicated for
+ tables in the publication.</entry>
+ </row>
+
+ <row>
+ <entry><structfield>pubdelete</structfield></entry>
+ <entry><type>bool</type></entry>
+ <entry></entry>
+ <entry>If true, <command>DELETE</command> operations are replicated for
+ tables in the publication.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
+
+ <sect1 id="catalog-pg-publication-rel">
+ <title><structname>pg_publication_rel</structname></title>
+
+ <indexterm zone="catalog-pg-publication-rel">
+ <primary>pg_publication_rel</primary>
+ </indexterm>
+
+ <para>
+ The catalog <structname>pg_publication_rel</structname> contains the
+ mapping between relations and publications in the database. This is a
+ many-to-many mapping. See also <xref linkend="view-pg-publication-tables">
+ for a more user-friendly view of this information.
+ </para>
+
+ <table>
+ <title><structname>pg_publication_rel</structname> Columns</title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>References</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><structfield>prpubid</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry><literal><link linkend="catalog-pg-publication"><structname>pg_publication</structname></link>.oid</literal></entry>
+ <entry>Reference to publication</entry>
+ </row>
+
+ <row>
+ <entry><structfield>prrelid</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+ <entry>Reference to relation</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
+
<sect1 id="catalog-pg-range">
<title><structname>pg_range</structname></title>
@@ -6150,6 +6296,109 @@
</sect1>
+ <sect1 id="catalog-pg-subscription">
+ <title><structname>pg_subscription</structname></title>
+
+ <indexterm zone="catalog-pg-subscription">
+ <primary>pg_subscription</primary>
+ </indexterm>
+
+ <para>
+ The catalog <structname>pg_subscription</structname> contains all existing
+ logical replication subscriptions. For more information about logical
+ replication see <xref linkend="logical-replication">.
+ </para>
+
+ <para>
+ Unlike most system catalogs, <structname>pg_subscription</structname> is
+ shared across all databases of a cluster: There is only one copy
+ of <structname>pg_subscription</structname> per cluster, not one per
+ database.
+ </para>
+
+ <para>
+ Access to this catalog is restricted from normal users. Normal users can
+ use the view <xref linkend="pg-stat-subscription"> to get some information
+ about subscriptions.
+ </para>
+
+ <table>
+ <title><structname>pg_subscription</structname> Columns</title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>References</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><structfield>oid</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry></entry>
+ <entry>Row identifier (hidden attribute; must be explicitly selected)</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subdbid</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
+ <entry>OID of the database which the subscription resides in</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subname</structfield></entry>
+ <entry><type>name</type></entry>
+ <entry></entry>
+ <entry>Name of the subscription</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subowner</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
+ <entry>Owner of the subscription</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subenabled</structfield></entry>
+ <entry><type>bool</type></entry>
+ <entry></entry>
+ <entry>If true, the subscription is enabled and should be replicating.</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subconninfo</structfield></entry>
+ <entry><type>text</type></entry>
+ <entry></entry>
+ <entry>Connection string to the upstream database</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subslotname</structfield></entry>
+ <entry><type>name</type></entry>
+ <entry></entry>
+ <entry>Name of the replication slot in the upstream database. Also used
+ for local replication origin name.</entry>
+ </row>
+
+ <row>
+ <entry><structfield>subpublications</structfield></entry>
+ <entry><type>text[]</type></entry>
+ <entry></entry>
+ <entry>Array of subscribed publication names. These reference the
+ publications on the publisher server. For more on publications
+ see <xref linkend="logical-replication-publication">.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
<sect1 id="catalog-pg-tablespace">
<title><structname>pg_tablespace</structname></title>
@@ -7590,6 +7839,11 @@
</row>
<row>
+ <entry><link linkend="view-pg-publication-tables"><structname>pg_publication_tables</structname></link></entry>
+ <entry>publications and their associated tables</entry>
+ </row>
+
+ <row>
<entry><link linkend="view-pg-replication-origin-status"><structname>pg_replication_origin_status</structname></link></entry>
<entry>information about replication origins, including replication progress</entry>
</row>
@@ -8871,6 +9125,61 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
</sect1>
+ <sect1 id="view-pg-publication-tables">
+ <title><structname>pg_publication_tables</structname></title>
+
+ <indexterm zone="view-pg-publication-tables">
+ <primary>pg_publication_tables</primary>
+ </indexterm>
+
+ <para>
+ The view <structname>pg_publication_tables</structname> provides
+ information about the mapping between publications and the tables they
+ contain. Unlike the underlying
+ catalog <structname>pg_publication_rel</structname>, this view expands
+ publications defined as <literal>FOR ALL TABLES</literal>, so for such
+ publications there will be a row for each eligible table.
+ </para>
+
+ <table>
+ <title><structname>pg_publication_tables</structname> Columns</title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Type</entry>
+ <entry>References</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><structfield>pubname</structfield></entry>
+ <entry><type>name</type></entry>
+ <entry><literal><link linkend="catalog-pg-publication"><structname>pg_publication</structname></link>.pubname</literal></entry>
+ <entry>Name of publication</entry>
+ </row>
+
+ <row>
+ <entry><structfield>schemaname</structfield></entry>
+ <entry><type>name</type></entry>
+ <entry><literal><link linkend="catalog-pg-namespace"><structname>pg_namespace</structname></link>.nspname</literal></entry>
+ <entry>Name of schema containing table</entry>
+ </row>
+
+ <row>
+ <entry><structfield>tablename</structfield></entry>
+ <entry><type>name</type></entry>
+ <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relname</literal></entry>
+ <entry>Name of table</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
+
<sect1 id="view-pg-replication-origin-status">
<title><structname>pg_replication_origin_status</structname></title>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 07afa3c77a7..fb5d6473efe 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -3411,6 +3411,47 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
</variablelist>
</sect2>
+
+ <sect2 id="runtime-config-replication-subscriber">
+ <title>Subscribers</title>
+
+ <para>
+ These settings control the behavior of a logical replication subscriber.
+ Their values on the publisher are irrelevant.
+ </para>
+
+ <para>
+ Note that <varname>wal_receiver_timeout</varname> and
+ <varname>wal_retrieve_retry_interval</varname> configuration parameters
+ affect the logical replication workers as well.
+ </para>
+
+ <variablelist>
+
+ <varlistentry id="guc-max-logical-replication-workers" xreflabel="max_logical_replication_workers">
+ <term><varname>max_logical_replication_workers</varname> (<type>int</type>)
+ <indexterm>
+ <primary><varname>max_logical_replication_workers</> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Specifies maximum number of logical replication workers. This includes
+ both apply workers and table synchronization workers.
+ </para>
+ <para>
+ Logical replication workers are taken from the pool defined by
+ <varname>max_worker_processes</varname>.
+ </para>
+ <para>
+ The default value is 4.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </sect2>
+
</sect1>
<sect1 id="runtime-config-query">
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 69649a7da4b..2624c627dcb 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -50,6 +50,7 @@
<!ENTITY config SYSTEM "config.sgml">
<!ENTITY user-manag SYSTEM "user-manag.sgml">
<!ENTITY wal SYSTEM "wal.sgml">
+<!ENTITY logical-replication SYSTEM "logical-replication.sgml">
<!-- programmer's guide -->
<!ENTITY bgworker SYSTEM "bgworker.sgml">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 2504a466e6d..b214218791e 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -18762,7 +18762,7 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
</row>
<row>
- <entry>
+ <entry id="pg-replication-origin-advance">
<indexterm>
<primary>pg_replication_origin_advance</primary>
</indexterm>
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
new file mode 100644
index 00000000000..9312c0c9a0d
--- /dev/null
+++ b/doc/src/sgml/logical-replication.sgml
@@ -0,0 +1,396 @@
+<!-- doc/src/sgml/logical-replication.sgml -->
+
+<chapter id="logical-replication">
+ <title>Logical Replication</title>
+
+ <para>
+ Logical replication is a method of replicating data objects and their
+ changes, based upon their replication identity (usually a primary key). We
+ use the term logical in contrast to physical replication, which uses exact
+ block addresses and byte-by-byte replication. PostgreSQL supports both
+ mechanisms concurrently, see <xref linkend="high-availability">. Logical
+ replication allows fine-grained control over both data replication and
+ security.
+ </para>
+
+ <para>
+ Logical replication uses a <firstterm>publish</firstterm>
+ and <firstterm>subscribe</firstterm> model with one or
+ more <firstterm>subscribers</firstterm> subscribing to one or more
+ <firstterm>publications</firstterm> on a <firstterm>publisher</firstterm>
+ node. Subscribers pull data from the publications they subscribe to and may
+ subsequently re-publish data to allow cascading replication or more complex
+ configurations.
+ </para>
+
+ <para>
+ Logical replication sends the changes on the publisher to the subscriber as
+ they occur in real-time. The subscriber applies the data in the same order
+ as the publisher so that transactional consistency is guaranteed for
+ publications within a single subscription. This method of data replication
+ is sometimes referred to as transactional replication.
+ </para>
+
+ <para>
+ The typical use-cases for logical replication are:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Sending incremental changes in a single database or a subset of a
+ database to subscribers as they occur.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Firing triggers for individual changes as they are incoming to
+ subscriber.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Consolidating multiple databases into a single one (for example for
+ analytical purposes).
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Replicating between different major versions of PostgreSQL.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Giving access to replicated data to different groups of users.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Sharing a subset of the database between multiple databases.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ 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. When the subscriber is treated as read-only by
+ application, there will be no conflicts from a single subscription. On the
+ other hand, if there are other writes done either by application or other
+ subscribers to the same set of tables conflicts can arise.
+ </para>
+
+ <sect1 id="logical-replication-publication">
+ <title>Publication</title>
+
+ <para>
+ A <firstterm>publication</firstterm> object can be defined on any physical
+ replication master. The node where a publication is defined is referred to
+ as <firstterm>publisher</firstterm>. A publication is a set of changes
+ generated from a group of tables, and might also be described as a change
+ set or replication set. Each publication exists in only one database.
+ </para>
+
+ <para>
+ Publications are different from schemas and do not affect how the table is
+ accessed. Each table can be added to multiple publications if needed.
+ Publications may currently only contain tables. Objects must be added
+ explicitly, except when a publication is created for <literal>ALL
+ TABLES</literal>.
+ </para>
+
+ <para>
+ Publications can choose to limit the changes they produce to show
+ any combination of <command>INSERT</command>, <command>UPDATE</command>, and
+ <command>DELETE</command> in a similar way to the way triggers are fired by
+ particular event types. If a table without a <literal>REPLICA
+ IDENTITY</literal> is added to a publication that
+ replicates <command>UPDATE</command> or <command>DELETE</command>
+ operations then subsequent <command>UPDATE</command>
+ or <command>DELETE</command> operations will fail on the publisher.
+ </para>
+
+ <para>
+ Every publication can have multiple subscribers.
+ </para>
+
+ <para>
+ A publication is created using the <xref linkend="sql-createpublication">
+ command and may be later altered or dropped using corresponding commands.
+ </para>
+
+ <para>
+ The individual tables can be added and removed dynamically using
+ <xref linkend="sql-alterpublication">. Both the <literal>ADD
+ TABLE</literal> and <literal>DROP TABLE</literal> operations are
+ transactional; so the table will start or stop replicating at the correct
+ snapshot once the transaction has committed.
+ </para>
+ </sect1>
+
+ <sect1 id="logical-replication-subscription">
+ <title>Subscription</title>
+
+ <para>
+ 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>. Subscription defines the connection
+ to another database and set of publications (one or more) to which it wants
+ to be subscribed.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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 extra care must be taken to ensure
+ that the subscribed publication objects don't overlap.
+ </para>
+
+ <para>
+ Each subscription will receive changes via one replication slot (see
+ <xref linkend="streaming-replication-slots">).
+ </para>
+
+ <para>
+ Subscriptions are not dumped by <command>pg_dump</command> by default but
+ can be requested using the command-line
+ option <option>--subscriptions</option>.
+ </para>
+
+ <para>
+ The subscription is added using <xref linkend="sql-createsubscription"> and
+ can be stopped/resumed at any time using the
+ <xref linkend="sql-altersubscription"> command and removed using
+ <xref linkend="sql-dropsubscription">.
+ </para>
+
+ <para>
+ When a subscription is dropped and recreated, the synchronization
+ information is lost. This means that the data has to be resynchronized
+ afterwards.
+ </para>
+
+ <para>
+ The schema definitions are not replicated and the published tables must
+ exist on the subsriber for replication to work. Only regular tables may be
+ the target of replication. For example, you can't replicate to a view.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ Columns of a table are also matched by name. A different order of columns
+ in the target table is allowed, but the column types have to match.
+ </para>
+ </sect1>
+
+ <sect1 id="logical-replication-conflicts">
+ <title>Conflicts</title>
+
+ <para>
+ The logical replication behaves similarly to normal DML operations in that
+ the data will be updated even if it was changed locally on the subscriber
+ node. If the incoming data violates any constraints the replication will
+ stop. This is referred to as a <firstterm>conflict</firstterm>. When
+ replicating <command>UPDATE</command> or <command>DELETE</command>
+ operations, missing data will not produce a conflict and such operations
+ will simply be skipped.
+ </para>
+
+ <para>
+ A conflict will produce an error and will stop the replication; it must be
+ resolved manually by the user. Details about the conflict can be found in
+ the subscriber's server log.
+ </para>
+
+ <para>
+ The resolution can be done either by changing data on the subscriber so
+ that it does not conflict with the incoming change or by skipping the
+ transaction that conflicts with the existing data. The transaction can be
+ skipped by calling the <link linkend="pg-replication-origin-advance">
+ <function>pg_replication_origin_advance()</function></link> function with
+ a <parameter>node_name</parameter> corresponding to the subscription name.
+ The current position of origins can be seen in the
+ <link linkend="view-pg-replication-origin-status">
+ <structname>pg_replication_origin_status</structname></link> system view.
+ </para>
+ </sect1>
+
+ <sect1 id="logical-replication-architecture">
+ <title>Architecture</title>
+
+ <para>
+ Logical replication starts by copying a snapshot of the data on the
+ publisher database. Once that is done, changes on the publisher are sent
+ to the subscriber as they occur in real time. The subscriber applies data
+ in the order in which commits were made on the publisher so that
+ transactional consistency is guaranteed for the publications within any
+ single subscription.
+ </para>
+
+ <para>
+ Logical replication is built with an architecture similar to physical
+ streaming replication (see <xref linkend="streaming-replication">). It is
+ implemented by <quote>walsender</quote> and the <quote>apply</quote>
+ processes. The walsender starts logical decoding (described
+ in <xref linkend="logicaldecoding">) of the WAL and loads the standard
+ logical decoding plugin (pgoutput). The plugin transforms the changes read
+ from WAL to the logical replication protocol
+ (see <xref linkend="protocol-logical-replication">) and filters the data
+ according to the publication specification. The data is then continuously
+ transferred using the streaming replication protocol to the apply worker,
+ which maps the data to local tables and applies the individual changes as
+ they are received in exact transactional order.
+ </para>
+
+ <para>
+ The apply process on the subscriber database always runs with
+ <varname>session_replication_role</varname> set
+ to <literal>replica</literal>, which produces the usual effects on triggers
+ and constraints.
+ </para>
+ </sect1>
+
+ <sect1 id="logical-replication-monitoring">
+ <title>Monitoring</title>
+
+ <para>
+ Because logical replication is based on similar architecture as
+ <link linkend="streaming-replication">physical streaming replication</link>
+ the monitoring on a publication node is very similar to monitoring of
+ physical replication master
+ (see <xref linkend="streaming-replication-monitoring">).
+ </para>
+
+ <para>
+ The monitoring information about subscription is visible in
+ <link linkend="pg-stat-subscription"><literal>pg_stat_subscription</literal></link>.
+ This view contains one row for every subscription worker. A subscription
+ can have zero or more active subscription workers depending on its state.
+ </para>
+
+ <para>
+ Normally, there is a single apply process running for an enabled
+ subscription. A disabled subscription or a crashed subscription will have
+ zero rows in this view.
+ </para>
+ </sect1>
+
+ <sect1 id="logical-replication-security">
+ <title>Security</title>
+
+ <para>
+ Logical replication connections occur in the same way as physical streaming
+ replication. It requires access to be specifically given using
+ <filename>pg_hba.conf</filename>. The role used for the replication
+ connection must have the <literal>REPLICATION</literal> attribute. This
+ gives a role access to both logical and physical replication.
+ </para>
+
+ <para>
+ To create a publication, the user must have the <literal>CREATE</literal>
+ privilege in the database.
+ </para>
+
+ <para>
+ To create a subscription, the user must be a superuser.
+ </para>
+
+ <para>
+ The subscription apply process will run in the local database with the
+ privileges of a superuser.
+ </para>
+
+ <para>
+ Privileges are only checked once at the start of a replication connection.
+ They are not re-checked as each change record is read from the publisher,
+ nor are they re-checked for each change when applied.
+ </para>
+ </sect1>
+
+ <sect1 id="logical-replication-config">
+ <title>Configuration Settings</title>
+
+ <para>
+ Logical replication requires several configuration options to be set.
+ </para>
+
+ <para>
+ On the publisher side, <varname>wal_level</varname> must be set to
+ <literal>logical</literal>, and <varname>max_replication_slots</varname>
+ has to be set to at least the number of subscriptions expected to connect.
+ And <varname>max_wal_senders</varname> should be set to at least the same
+ as <varname>max_replication_slots</varname> plus the number of physical replicas
+ that are connected at the same time.
+ </para>
+
+ <para>
+ The subscriber also requires the <varname>max_replication_slots</varname>
+ to be set. In this case it should be set to at least the number of
+ subscriptions that will be added to the subscriber.
+ <varname>max_logical_replication_workers</varname> has to be set to at
+ least the number of subscriptions. Additionally the
+ <varname>max_worker_processes</varname> may need to be adjusted to
+ accommodate for replication workers, at least
+ (<varname>max_logical_replication_workers</varname>
+ + <literal>1</literal>). Note that some extensions and parallel queries
+ also take worker slots from <varname>max_worker_processes</varname>.
+ </para>
+ </sect1>
+
+ <sect1 id="logical-replication-quick-setup">
+ <title>Quick Setup</title>
+
+ <para>
+ First set the configuration options in <filename>postgresql.conf</filename>:
+<programlisting>
+wal_level = logical
+</programlisting>
+ The other required settings have default values that are sufficient for a
+ basic setup.
+ </para>
+
+ <para>
+ <filename>pg_hba.conf</filename> needs to be adjusted to allow replication
+ (the values here depend on your actual network configuration and user you
+ want to use for connecting):
+<programlisting>
+host replication repuser 0.0.0.0/0 md5
+</programlisting>
+ </para>
+
+ <para>
+ Then on the publisher database:
+<programlisting>
+CREATE PUBLICATION mypub FOR TABLE users, departments;
+</programlisting>
+ </para>
+
+ <para>
+ And on the subscriber database:
+<programlisting>
+CREATE SUBSCRIPTION mysub CONNECTION 'dbname=foo host=bar user=repuser' PUBLICATION mypub;
+</programlisting>
+ </para>
+
+ <para>
+ The above will start the replication process of changes to
+ <literal>users</literal> and <literal>departments</literal> tables.
+ </para>
+ </sect1>
+</chapter>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 1545f03656c..01fad3870f6 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -309,6 +309,14 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
</row>
<row>
+ <entry><structname>pg_stat_subscription</><indexterm><primary>pg_stat_subscription</primary></indexterm></entry>
+ <entry>At least one row per subscription, showing information about
+ the subscription workers.
+ See <xref linkend="pg-stat-subscription"> for details.
+ </entry>
+ </row>
+
+ <row>
<entry><structname>pg_stat_ssl</><indexterm><primary>pg_stat_ssl</primary></indexterm></entry>
<entry>One row per connection (regular and replication), showing information about
SSL used on this connection.
@@ -1545,6 +1553,72 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
connected server.
</para>
+ <table id="pg-stat-subscription" xreflabel="pg_stat_subscription">
+ <title><structname>pg_stat_subscription</structname> View</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Column</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><structfield>subid</></entry>
+ <entry><type>oid</></entry>
+ <entry>OID of the subscription</entry>
+ </row>
+ <row>
+ <entry><structfield>subname</></entry>
+ <entry><type>text</></entry>
+ <entry>Name of the subscription</entry>
+ </row>
+ <row>
+ <entry><structfield>pid</></entry>
+ <entry><type>integer</></entry>
+ <entry>Process ID of the subscription worker process</entry>
+ </row>
+ <row>
+ <entry><structfield>received_lsn</></entry>
+ <entry><type>pg_lsn</></entry>
+ <entry>Last transaction log position received, the initial value of
+ this field being 0</entry>
+ </row>
+ <row>
+ <entry><structfield>last_msg_send_time</></entry>
+ <entry><type>timestamp with time zone</></entry>
+ <entry>Send time of last message received from origin WAL sender</entry>
+ </row>
+ <row>
+ <entry><structfield>last_msg_receipt_time</></entry>
+ <entry><type>timestamp with time zone</></entry>
+ <entry>Receipt time of last message received from origin WAL sender
+ </entry>
+ </row>
+ <row>
+ <entry><structfield>latest_end_lsn</></entry>
+ <entry><type>pg_lsn</></entry>
+ <entry>Last transaction log position reported to origin WAL sender
+ </entry>
+ </row>
+ <row>
+ <entry><structfield>latest_end_time</></entry>
+ <entry><type>timestamp with time zone</></entry>
+ <entry>Time of last transaction log position reported to origin WAL
+ sender</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ The <structname>pg_stat_subscription</structname> view will contain one
+ row per subscription for main worker (with null PID if the worker is
+ not running).
+ </para>
+
<table id="pg-stat-ssl-view" xreflabel="pg_stat_ssl">
<title><structname>pg_stat_ssl</structname> View</title>
<tgroup cols="3">
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 9143917c490..4e169d1b189 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -160,6 +160,7 @@
&monitoring;
&diskusage;
&wal;
+ &logical-replication;
&regress;
</part>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 9ba147cae5e..5f89db58570 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -2122,6 +2122,119 @@ The commands accepted in walsender mode are:
</sect1>
+<sect1 id="protocol-logical-replication">
+ <title>Logical Streaming Replication Protocol</title>
+
+ <para>
+ This section describes the logical replication protocol, which is the message
+ flow started by the <literal>START_REPLICATION</literal>
+ <literal>SLOT</literal> <replaceable class="parameter">slot_name</>
+ <literal>LOGICAL</literal> replication command.
+ </para>
+
+ <para>
+ The logical streaming replication protocol builds on the primitives of
+ the physical streaming replication protocol.
+ </para>
+
+ <sect2 id="protocol-logical-replication-params">
+ <title>Logical Streaming Replication Parameters</title>
+
+ <para>
+ The logical replication <literal>START_REPLICATION</literal> command
+ accepts following parameters:
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ proto_version
+ </term>
+ <listitem>
+ <para>
+ Protocol version. Currently only version <literal>1</literal> is
+ supported.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ publication_names
+ </term>
+ <listitem>
+ <para>
+ Comma separated list of publication names for which to subscribe
+ (receive changes). The individual publication names are treated
+ as standard objects names and can be quoted the same as needed.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+ </sect2>
+
+ <sect2 id="protocol-logical-messages">
+ <title>Logical Replication Protocol Messages</title>
+
+ <para>
+ The individual protocol messages are discussed in the following
+ subsections. Individual messages are describer in
+ <xref linkend="protocol-logicalrep-message-formats"> section.
+ </para>
+
+ <para>
+ All top-level protocol messages begin with a message type byte.
+ While represented in code as a character, this is a signed byte with no
+ associated encoding.
+ </para>
+
+ <para>
+ Since the streaming replication protocol supplies a message length there
+ is no need for top-level protocol messages to embed a length in their
+ header.
+ </para>
+
+ </sect2>
+
+ <sect2 id="protocol-logical-messages-flow">
+ <title>Logical Replication Protocol Message Flow</title>
+
+ <para>
+ With the exception of the <literal>START_REPLICATION</literal> command and
+ the replay progress messages, all information flows only from the backend
+ to the frontend.
+ </para>
+
+ <para>
+ The logical replication protocol sends individual transactions one by one.
+ This means that all messages between a pair of Begin and Commit messages
+ belong to the same transaction.
+ </para>
+
+ <para>
+ Every sent transaction contains zero or more DML messages (Insert,
+ Update, Delete). In case of a cascaded setup it can also contain Origin
+ messages. The origin message indicated that the transaction originated on
+ different replication node. Since a replication node in the scope of logical
+ replication protocol can be pretty much anything, the only identifier
+ is the origin name. It's downstream's responsibility to handle this as
+ needed (if needed). The Origin message is always sent before any DML
+ messages in the transaction.
+ </para>
+
+ <para>
+ Every DML message contains an arbitrary relation ID, which can be mapped to
+ an ID in the Relation messages. The Relation messages describe the schema of the
+ given relation. The Relation message is sent for a given relation either
+ because it is the first time we send a DML message for given relation in the
+ current session or because the relation definition has changed since the
+ last Relation message was sent for it. The protocol assumes that the client
+ is capable of caching the metadata for as many relations as needed.
+ </para>
+ </sect2>
+</sect1>
+
<sect1 id="protocol-message-types">
<title>Message Data Types</title>
@@ -5149,6 +5262,614 @@ not line breaks.
</sect1>
+<sect1 id="protocol-logicalrep-message-formats">
+<title>Logical Replication Message Formats</title>
+
+<para>
+This section describes the detailed format of each logical replication message.
+These messages are returned either by the replication slot SQL interface or are
+sent by a walsender. In case of a walsender they are encapsulated inside the replication
+protocol WAL messages as described in <xref linkend="protocol-replication">
+and generally obey same message flow as physical replication.
+</para>
+
+<variablelist>
+
+<varlistentry>
+<term>
+Begin
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('B')
+</term>
+<listitem>
+<para>
+ Identifies the message as a begin message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int64
+</term>
+<listitem>
+<para>
+ The final LSN of the transaction.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int64
+</term>
+<listitem>
+<para>
+ Commit timestamp of the transaction. The value is in number
+ of microseconds since PostgreSQL epoch (2000-01-01).
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int32
+</term>
+<listitem>
+<para>
+ Xid of the transaction.
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+Commit
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('C')
+</term>
+<listitem>
+<para>
+ Identifies the message as a commit message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int64
+</term>
+<listitem>
+<para>
+ The LSN of the commit.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int64
+</term>
+<listitem>
+<para>
+ The end LSN of the transaction.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int64
+</term>
+<listitem>
+<para>
+ Commit timestamp of the transaction. The value is in number
+ of microseconds since PostgreSQL epoch (2000-01-01).
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+Origin
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('O')
+</term>
+<listitem>
+<para>
+ Identifies the message as an origin message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int64
+</term>
+<listitem>
+<para>
+ The LSN of the commit on the origin server.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ String
+</term>
+<listitem>
+<para>
+ Name of the origin.
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+
+<para>
+ Note that there can be multiple Origin messages inside a single transaction.
+</para>
+
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+Relation
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('R')
+</term>
+<listitem>
+<para>
+ Identifies the message as a relation message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int32
+</term>
+<listitem>
+<para>
+ ID of the relation.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ String
+</term>
+<listitem>
+<para>
+ Namespace (empty string for <literal>pg_catalog</literal>).
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ String
+</term>
+<listitem>
+<para>
+ Relation name.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ Int8
+</term>
+<listitem>
+<para>
+ Replica identity setting for the relation (same as
+ <structfield>relreplident</structfield> in <structname>pg_class</structname>).
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ Int16
+</term>
+<listitem>
+<para>
+ Number of columns.
+</para>
+</listitem>
+</varlistentry>
+</variablelist>
+ Next, the following message part appears for each column:
+<variablelist>
+<varlistentry>
+<term>
+ Int8
+</term>
+<listitem>
+<para>
+ Flags for the column. Currently can be either 0 for no flags
+ or 1 which marks the column as part of the key.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ String
+</term>
+<listitem>
+<para>
+ Name of the column.
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+Insert
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('I')
+</term>
+<listitem>
+<para>
+ Identifies the message as an insert message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int32
+</term>
+<listitem>
+<para>
+ ID of the relation corresponding to the ID in the relation
+ message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Byte1('N')
+</term>
+<listitem>
+<para>
+ Identifies the following TupleData message as a new tuple.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ TupleData
+</term>
+<listitem>
+<para>
+ TupleData message part representing the contents of new tuple.
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+Update
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('U')
+</term>
+<listitem>
+<para>
+ Identifies the message as an update message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int32
+</term>
+<listitem>
+<para>
+ ID of the relation corresponding to the ID in the relation
+ message.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ Byte1('K')
+</term>
+<listitem>
+<para>
+ Identifies the following TupleData submessage as a key.
+ This field is optional and is only present if
+ the update changed data in any of the column(s) that are
+ part of the REPLICA IDENTITY index.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ Byte1('O')
+</term>
+<listitem>
+<para>
+ Identifies the following TupleData submessage as an old tuple.
+ This field is optional and is only present if table in which
+ the update happened has REPLICA IDENTITY set to FULL.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ TupleData
+</term>
+<listitem>
+<para>
+ TupleData message part representing the contents of the old tuple
+ or primary key. Only present if the previous 'O' or 'K' part
+ is present.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ Byte1('N')
+</term>
+<listitem>
+<para>
+ Identifies the following TupleData message as a new tuple.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ TupleData
+</term>
+<listitem>
+<para>
+ TupleData message part representing the contents of a new tuple.
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+
+<para>
+ The Update message may contain either a 'K' message part or an 'O' message part
+ or neither of them, but never both of them.
+</para>
+
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+Delete
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('D')
+</term>
+<listitem>
+<para>
+ Identifies the message as a delete message.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int32
+</term>
+<listitem>
+<para>
+ ID of the relation corresponding to the ID in the relation
+ message.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ Byte1('K')
+</term>
+<listitem>
+<para>
+ Identifies the following TupleData submessage as a key.
+ This field is present if the table in which the delete has
+ happened uses an index as REPLICA IDENTITY.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ Byte1('O')
+</term>
+<listitem>
+<para>
+ Identifies the following TupleData message as a old tuple.
+ This field is is present if the table in which the delete has
+ happened has REPLICA IDENTITY set to FULL.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+ TupleData
+</term>
+<listitem>
+<para>
+ TupleData message part representing the contents of the old tuple
+ or primary key, depending on the previous field.
+</para>
+</listitem>
+</varlistentry>
+</variablelist>
+</para>
+
+<para>
+ The Delete message may contain either a 'K' message part or an 'O' message part,
+ but never both of them.
+</para>
+
+</listitem>
+</varlistentry>
+
+</variablelist>
+
+<para>
+
+Following message parts that are shared by above messages.
+
+</para>
+
+<variablelist>
+
+<varlistentry>
+<term>
+TupleData
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+ Int16
+</term>
+<listitem>
+<para>
+ Number of columns.
+</para>
+</listitem>
+</varlistentry>
+</variablelist>
+ Next, one of the following submessages appears for each column:
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('n')
+</term>
+<listitem>
+<para>
+ Idenfifies the data as NULL value.
+</para>
+</listitem>
+</varlistentry>
+</variablelist>
+ Or
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('u')
+</term>
+<listitem>
+<para>
+ Idenfifies unchanged TOASTed value (the actual value is not
+ sent).
+</para>
+</listitem>
+</varlistentry>
+</variablelist>
+ Or
+<variablelist>
+<varlistentry>
+<term>
+ Byte1('t')
+</term>
+<listitem>
+<para>
+ Idenfifies the data as text formatted value.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ Int32
+</term>
+<listitem>
+<para>
+ Length of the column value.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+ String
+</term>
+<listitem>
+<para>
+ The text value.
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+
+</sect1>
+
<sect1 id="protocol-changes">
<title>Summary of Changes since Protocol 2.0</title>
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 77667bdebd1..0d09f81ccc7 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -26,11 +26,13 @@ Complete list of usable sgml source files in this directory.
<!ENTITY alterOperatorClass SYSTEM "alter_opclass.sgml">
<!ENTITY alterOperatorFamily SYSTEM "alter_opfamily.sgml">
<!ENTITY alterPolicy SYSTEM "alter_policy.sgml">
+<!ENTITY alterPublication SYSTEM "alter_publication.sgml">
<!ENTITY alterRole SYSTEM "alter_role.sgml">
<!ENTITY alterRule SYSTEM "alter_rule.sgml">
<!ENTITY alterSchema SYSTEM "alter_schema.sgml">
<!ENTITY alterServer SYSTEM "alter_server.sgml">
<!ENTITY alterSequence SYSTEM "alter_sequence.sgml">
+<!ENTITY alterSubscription SYSTEM "alter_subscription.sgml">
<!ENTITY alterSystem SYSTEM "alter_system.sgml">
<!ENTITY alterTable SYSTEM "alter_table.sgml">
<!ENTITY alterTableSpace SYSTEM "alter_tablespace.sgml">
@@ -72,11 +74,13 @@ Complete list of usable sgml source files in this directory.
<!ENTITY createOperatorClass SYSTEM "create_opclass.sgml">
<!ENTITY createOperatorFamily SYSTEM "create_opfamily.sgml">
<!ENTITY createPolicy SYSTEM "create_policy.sgml">
+<!ENTITY createPublication SYSTEM "create_publication.sgml">
<!ENTITY createRole SYSTEM "create_role.sgml">
<!ENTITY createRule SYSTEM "create_rule.sgml">
<!ENTITY createSchema SYSTEM "create_schema.sgml">
<!ENTITY createSequence SYSTEM "create_sequence.sgml">
<!ENTITY createServer SYSTEM "create_server.sgml">
+<!ENTITY createSubscription SYSTEM "create_subscription.sgml">
<!ENTITY createTable SYSTEM "create_table.sgml">
<!ENTITY createTableAs SYSTEM "create_table_as.sgml">
<!ENTITY createTableSpace SYSTEM "create_tablespace.sgml">
@@ -116,11 +120,13 @@ Complete list of usable sgml source files in this directory.
<!ENTITY dropOperatorFamily SYSTEM "drop_opfamily.sgml">
<!ENTITY dropOwned SYSTEM "drop_owned.sgml">
<!ENTITY dropPolicy SYSTEM "drop_policy.sgml">
+<!ENTITY dropPublication SYSTEM "drop_publication.sgml">
<!ENTITY dropRole SYSTEM "drop_role.sgml">
<!ENTITY dropRule SYSTEM "drop_rule.sgml">
<!ENTITY dropSchema SYSTEM "drop_schema.sgml">
<!ENTITY dropSequence SYSTEM "drop_sequence.sgml">
<!ENTITY dropServer SYSTEM "drop_server.sgml">
+<!ENTITY dropSubscription SYSTEM "drop_subscription.sgml">
<!ENTITY dropTable SYSTEM "drop_table.sgml">
<!ENTITY dropTableSpace SYSTEM "drop_tablespace.sgml">
<!ENTITY dropTransform SYSTEM "drop_transform.sgml">
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
new file mode 100644
index 00000000000..47d83b80be5
--- /dev/null
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -0,0 +1,139 @@
+<!--
+doc/src/sgml/ref/alter_publication.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERPUBLICATION">
+ <indexterm zone="sql-alterpublication">
+ <primary>ALTER PUBLICATION</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>ALTER PUBLICATION</refentrytitle>
+ <manvolnum>7</manvolnum>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER PUBLICATION</refname>
+ <refpurpose>change the definition of a publication</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> WITH ( <replaceable class="PARAMETER">option</replaceable> [, ... ] )
+
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
+
+ PUBLISH INSERT | NOPUBLISH INSERT
+ | PUBLISH UPDATE | NOPUBLISH UPDATE
+ | PUBLISH DELETE | NOPUBLISH DELETE
+
+ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> ADD TABLE <replaceable class="PARAMETER">table_name</replaceable> [, ...]
+ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> SET TABLE <replaceable class="PARAMETER">table_name</replaceable> [, ...]
+ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> DROP TABLE <replaceable class="PARAMETER">table_name</replaceable> [, ...]
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ The first variant of this command listed in the synopsis can change
+ all of the publication properties specified in
+ <xref linkend="sql-createpublication">. Properties not mentioned in the
+ command retain their previous settings. Database superusers can change any
+ of these settings for any role.
+ </para>
+
+ <para>
+ To alter the owner, you must also be a direct or indirect member of the
+ new owning role. The new owner has to be a superuser
+ </para>
+
+ <para>
+ The other variants of this command deal with the table membership of the
+ publication. The <literal>SET TABLE</literal> clause will replace the
+ list of tables in the publication with the specified one.
+ The <literal>ADD TABLE</literal> and
+ <literal>DROP TABLE</literal> will add and remove one or more tables from
+ the publication.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Parameters</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ The name of an existing publication whose definition is to be altered.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>PUBLISH INSERT</literal></term>
+ <term><literal>NOPUBLISH INSERT</literal></term>
+ <term><literal>PUBLISH UPDATE</literal></term>
+ <term><literal>NOPUBLISH UPDATE</literal></term>
+ <term><literal>PUBLISH DELETE</literal></term>
+ <term><literal>NOPUBLISH DELETE</literal></term>
+ <listitem>
+ <para>
+ These clauses alter properties originally set by
+ <xref linkend="SQL-CREATEPUBLICATION">. See there for more information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">table_name</replaceable></term>
+ <listitem>
+ <para>
+ Name of an existing table.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ Change the publication to not publish inserts:
+<programlisting>
+ALTER PUBLICATION noinsert WITH (NOPUBLISH INSERT);
+</programlisting>
+ </para>
+
+ <para>
+ Add some tables to the publication:
+<programlisting>
+ALTER PUBLICATION mypublication ADD TABLE users, departments;
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ <command>ALTER PUBLICATION</command> is a <productname>PostgreSQL</>
+ extension.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createpublication"></member>
+ <member><xref linkend="sql-droppublication"></member>
+ </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
new file mode 100644
index 00000000000..032ecbb885e
--- /dev/null
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -0,0 +1,139 @@
+<!--
+doc/src/sgml/ref/alter_subscription.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERSUBSCRIPTION">
+ <indexterm zone="sql-altersubscription">
+ <primary>ALTER SUBSCRIPTION</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>ALTER SUBSCRIPTION</refentrytitle>
+ <manvolnum>7</manvolnum>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER SUBSCRIPTION</refname>
+ <refpurpose>change the definition of a subscription</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> WITH ( <replaceable class="PARAMETER">option</replaceable> [, ... ] ) ]
+
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
+
+ SLOT NAME = slot_name
+
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> CONNECTION 'conninfo'
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> SET PUBLICATION publication_name [, ...]
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> ENABLE
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> DISABLE
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>ALTER SUBSCRIPTION</command> can change most of the subscription
+ properties that can be specified
+ in <xref linkend="sql-createsubscription">.
+ </para>
+
+ <para>
+ To alter the owner, you must also be a direct or indirect member of the
+ new owning role. The new owner has to be a superuser
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Parameters</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ The name of a subscription whose properties are to be altered.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
+ <term><literal>SET PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
+ <term><literal>SLOT NAME = <replaceable class="parameter">slot_name</replaceable></literal></term>
+ <listitem>
+ <para>
+ These clauses alter properties originally set by
+ <xref linkend="SQL-CREATESUBSCRIPTION">. See there for more
+ information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>ENABLE</literal></term>
+ <listitem>
+ <para>
+ Enables the previously disabled subscription, starting the logical
+ replication worker at the end of transaction.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>DISABLE</literal></term>
+ <listitem>
+ <para>
+ Disables the running subscription, stopping the logical replication
+ worker at the end of transaction.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ Change the publication subscribed by a subscription to
+ <literal>insert_only</literal>:
+<programlisting>
+ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only;
+</programlisting>
+ </para>
+
+ <para>
+ Disable (stop) the subscription:
+<programlisting>
+ALTER SUBSCRIPTION mysub DISABLE;
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ <command>ALTER SUBSCRIPTION</command> is a <productname>PostgreSQL</>
+ extension.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createsubscription"></member>
+ <member><xref linkend="sql-dropsubscription"></member>
+ <member><xref linkend="sql-createpublication"></member>
+ <member><xref linkend="sql-alterpublication"></member>
+ </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/ref/create_publication.sgml b/doc/src/sgml/ref/create_publication.sgml
new file mode 100644
index 00000000000..995f2bcf3c1
--- /dev/null
+++ b/doc/src/sgml/ref/create_publication.sgml
@@ -0,0 +1,206 @@
+<!--
+doc/src/sgml/ref/create_publication.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-CREATEPUBLICATION">
+ <indexterm zone="sql-createpublication">
+ <primary>CREATE PUBLICATION</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>CREATE PUBLICATION</refentrytitle>
+ <manvolnum>7</manvolnum>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>CREATE PUBLICATION</refname>
+ <refpurpose>define a new publication</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
+ [ FOR TABLE <replaceable class="parameter">table_name</replaceable> [, ...]
+ | FOR ALL TABLES ]
+ [ WITH ( <replaceable class="parameter">option</replaceable> [, ... ] ) ]
+
+<phrase>where <replaceable class="parameter">option</replaceable> can be:</phrase>
+
+ PUBLISH INSERT | NOPUBLISH INSERT
+ | PUBLISH UPDATE | NOPUBLISH UPDATE
+ | PUBLISH DELETE | NOPUBLISH DELETE
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>CREATE PUBLICATION</command> adds a new publication
+ into the current database. The publication name must be distinct from
+ the name of any existing publication in the current database.
+ </para>
+
+ <para>
+ A publication is essentially a group of tables whose data changes are
+ intended to be replicated through logical replication. See
+ <xref linkend="logical-replication-publication"> for details about how
+ publications fit into the logical replication setup.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Parameters</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ The name of the new publication.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>FOR TABLE</literal></term>
+ <listitem>
+ <para>
+ Specifies a list of tables to add to the publication.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>FOR ALL TABLES</literal></term>
+ <listitem>
+ <para>
+ Marks the publication as one that replicates changes for all tables in
+ the database, including tables created in the future.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>PUBLISH INSERT</literal></term>
+ <term><literal>NOPUBLISH INSERT</literal></term>
+ <listitem>
+ <para>
+ These clauses determine whether the new publication will send
+ the <command>INSERT</command> operations to the subscribers.
+ <literal>PUBLISH INSERT</literal> is the default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>PUBLISH UPDATE</literal></term>
+ <term><literal>NOPUBLISH UPDATE</literal></term>
+ <listitem>
+ <para>
+ These clauses determine whether the new publication will send
+ the <command>UPDATE</command> operations to the subscribers.
+ <literal>PUBLISH UPDATE</literal> is the default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>PUBLISH DELETE</literal></term>
+ <term><literal>NOPUBLISH DELETE</literal></term>
+ <listitem>
+ <para>
+ These clauses determine whether the new publication will send
+ the <command>DELETE</command> operations to the subscribers.
+ <literal>PUBLISH DELETE</literal> is the default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para>
+ If neither <literal>FOR TABLE</literal> nor <literal>FOR ALL
+ TABLES</literal> is specified, then the publication starts out with an
+ empty set of tables. That is useful if tables are to be added later.
+ </para>
+
+ <para>
+ The creation of a publication does not start replication. It only defines
+ a grouping and filtering logic for future subscribers.
+ </para>
+
+ <para>
+ To create a publication, the invoking user must have the
+ <literal>CREATE</> privilege for the current database.
+ (Of course, superusers bypass this check.)
+ </para>
+
+ <para>
+ To add a table to a publication, the invoking user must have
+ <command>SELECT</command> privilege on given table. The
+ <command>FOR ALL TABLES</command> clause requires superuser.
+ </para>
+
+ <para>
+ The tables added to a publication that publishes <command>UPDATE</command>
+ and/or <command>DELETE</command> operations must have
+ <literal>REPLICA IDENTITY</> defined. Otherwise those operations will be
+ disallowed on those tables.
+ </para>
+
+ <para>
+ For an <command>INSERT ... ON CONFLICT</> command, the publication will
+ publish the operation that actually results from the command. So depending
+ of the outcome, it may be published as either <command>INSERT</command> or
+ <command>UPDATE</command>, or it may not be published at all.
+ </para>
+
+ <para>
+ <command>TRUNCATE</command> and other <acronym>DDL</acronym> operations
+ are not published.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ Create a simple publication that just publishes all DML for tables in it:
+<programlisting>
+CREATE PUBLICATION mypublication;
+</programlisting>
+ </para>
+
+ <para>
+ Create an insert-only publication:
+<programlisting>
+CREATE PUBLICATION insert_only WITH (NOPUBLISH UPDATE, NOPUBLISH DELETE);
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ <command>CREATE PUBLICATION</command> is a <productname>PostgreSQL</>
+ extension.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-alterpublication"></member>
+ <member><xref linkend="sql-droppublication"></member>
+ </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
new file mode 100644
index 00000000000..40d08b34409
--- /dev/null
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -0,0 +1,176 @@
+<!--
+doc/src/sgml/ref/create_subscription.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-CREATESUBSCRIPTION">
+ <indexterm zone="sql-createsubscription">
+ <primary>CREATE SUBSCRIPTION</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>CREATE SUBSCRIPTION</refentrytitle>
+ <manvolnum>7</manvolnum>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>CREATE SUBSCRIPTION</refname>
+ <refpurpose>define a new subscription</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+CREATE SUBSCRIPTION <replaceable class="PARAMETER">subscription_name</replaceable> CONNECTION 'conninfo' PUBLICATION { publication_name [, ...] } [ WITH ( <replaceable class="PARAMETER">option</replaceable> [, ... ] ) ]
+
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
+
+ | ENABLED | DISABLED
+ | CREATE SLOT | NOCREATE SLOT
+ | SLOT NAME = slot_name
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>CREATE SUBSCRIPTION</command> adds a new subscription for a
+ current database. The subscription name must be distinct from the name of
+ any existing subscription in the database.
+ </para>
+
+ <para>
+ The subscription represents a replication connection to the publisher. As
+ such this command does not only add definitions in the local catalogs but
+ also creates a replication slot on the publisher.
+ </para>
+
+ <para>
+ A logical replication worker will be started to replicate data for the new
+ subscription at the commit of the transaction where this command is run.
+ </para>
+
+ <para>
+ Additional info about subscriptions and logical replication as a whole
+ can is available at <xref linkend="logical-replication-subscription"> and
+ <xref linkend="logical-replication">.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Parameters</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable class="parameter">subscription_name</replaceable></term>
+ <listitem>
+ <para>
+ The name of the new subscription.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
+ <listitem>
+ <para>
+ The connection string to the publisher.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
+ <listitem>
+ <para>
+ Name(s) of the publications on the publisher to subscribe to.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>ENABLED</literal></term>
+ <term><literal>DISABLED</literal></term>
+ <listitem>
+ <para>
+ Specifies whether the subscription should be actively replicating or
+ if it should be just setup but not started yet. Note that the
+ replication slot as described above is created in either case.
+ <literal>ENABLED</literal> is the default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>CREATE SLOT</literal></term>
+ <term><literal>NOCREATE SLOT</literal></term>
+ <listitem>
+ <para>
+ Specifies whether the command should create the replication slot on the
+ publisher. <literal>CREATE SLOT</literal> is the default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>SLOT NAME = <replaceable class="parameter">slot_name</replaceable></literal></term>
+ <listitem>
+ <para>
+ Name of the replication slot to use. The default behavior is to use
+ <literal>subscription_name</> for slot name.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ Create a subscription to a remote server that replicates tables in
+ the publications <literal>mypubclication</literal> and
+ <literal>insert_only</literal> and starts replicating immediately on
+ commit:
+<programlisting>
+CREATE SUBSCRIPTION mysub
+ CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb password=foopass'
+ PUBLICATION mypublication, insert_only;
+</programlisting>
+ </para>
+
+ <para>
+ Create a subscription to a remote server that replicates tables in
+ the <literal>insert_only</literal> publication and does not start replicating
+ until enabled at a later time.
+<programlisting>
+CREATE SUBSCRIPTION mysub
+ CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb password=foopass'
+ PUBLICATION insert_only
+ WITH (DISABLED);
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ <command>CREATE SUBSCRIPTION</command> is a <productname>PostgreSQL</>
+ extension.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-altersubscription"></member>
+ <member><xref linkend="sql-dropsubscription"></member>
+ <member><xref linkend="sql-createpublication"></member>
+ <member><xref linkend="sql-alterpublication"></member>
+ </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/ref/drop_publication.sgml b/doc/src/sgml/ref/drop_publication.sgml
new file mode 100644
index 00000000000..1a1be579ad8
--- /dev/null
+++ b/doc/src/sgml/ref/drop_publication.sgml
@@ -0,0 +1,107 @@
+<!--
+doc/src/sgml/ref/drop_publication.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-DROPPUBLICATION">
+ <indexterm zone="sql-droppublication">
+ <primary>DROP PUBLICATION</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>DROP PUBLICATION</refentrytitle>
+ <manvolnum>7</manvolnum>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>DROP PUBLICATION</refname>
+ <refpurpose>remove a publication</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+DROP PUBLICATION [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ]
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>DROP PUBLICATION</command> removes an existing publication from
+ the database.
+ </para>
+
+ <para>
+ A publication can only be dropped by its owner or a superuser.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Parameters</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>IF EXISTS</literal></term>
+ <listitem>
+ <para>
+ Do not throw an error if the extension does not exist. A notice is issued
+ in this case.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ The name of an existing publication.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>CASCADE</literal></term>
+ <term><literal>RESTRICT</literal></term>
+
+ <listitem>
+ <para>
+ These key words do not have any effect, since there are no dependencies
+ on publications.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ Drop a publication:
+<programlisting>
+DROP PUBLICATION mypublication;
+</programlisting>
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ <command>DROP PUBLICATION</command> is a <productname>PostgreSQL</>
+ extension.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createpublication"></member>
+ <member><xref linkend="sql-alterpublication"></member>
+ </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/ref/drop_subscription.sgml b/doc/src/sgml/ref/drop_subscription.sgml
new file mode 100644
index 00000000000..9f2fb93275c
--- /dev/null
+++ b/doc/src/sgml/ref/drop_subscription.sgml
@@ -0,0 +1,110 @@
+<!--
+doc/src/sgml/ref/drop_subscription.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-DROPSUBSCRIPTION">
+ <indexterm zone="sql-dropsubscription">
+ <primary>DROP SUBSCRIPTION</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>DROP SUBSCRIPTION</refentrytitle>
+ <manvolnum>7</manvolnum>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>DROP SUBSCRIPTION</refname>
+ <refpurpose>remove a subscription</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+DROP SUBSCRIPTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable> [ <replaceable class="parameter">DROP SLOT</replaceable> | <replaceable class="parameter">NODROP SLOT</replaceable> ]
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>DROP SUBSCRIPTION</command> removes a subscription from the
+ database cluster.
+ </para>
+
+ <para>
+ A subscription can only be dropped by a superuser.
+ </para>
+
+ <para>
+ The replication worker associated with the subscription will not stop until
+ after the transaction that issued this command has committed.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Parameters</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ The name of a subscription to be dropped.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">DROP SLOT</replaceable></term>
+ <term><replaceable class="parameter">NODROP SLOT</replaceable></term>
+ <listitem>
+ <para>
+ Specifies whether to drop the replication slot on the publisher. The
+ default is
+ <literal>DROP SLOT</literal>.
+ </para>
+
+ <para>
+ If the publisher is not reachable when the subscription is to be
+ dropped, then it is useful to specify <literal>NODROP SLOT</literal>.
+ But the replication slot on the publisher will then have to be removed
+ manually.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ Drop a subscription:
+<programlisting>
+DROP SUBSCRIPTION mysub;
+</programlisting>
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ <command>DROP SUBSCRIPTION</command> is a <productname>PostgreSQL</>
+ extension.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createsubscription"></member>
+ <member><xref linkend="sql-altersubscription"></member>
+ </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index b70e7d57e95..a1e03c481d1 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -756,6 +756,15 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
+ <term><option>--include-subscriptions</option></term>
+ <listitem>
+ <para>
+ Include logical replication subscriptions in the dump.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--inserts</option></term>
<listitem>
<para>
@@ -790,6 +799,18 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
+ <term><option>--no-create-subscription-slots</option></term>
+ <listitem>
+ <para>
+ When dumping logical replication subscriptions,
+ generate <command>CREATE SUBSCRIPTION</command> commands that do not
+ create the remote replication slot. That way, the dump can be
+ restored without requiring network access to the remote servers.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--no-security-labels</option></term>
<listitem>
<para>
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 991573121be..640fe12bbf6 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1601,6 +1601,34 @@ testdb=&gt;
</varlistentry>
<varlistentry>
+ <term><literal>\dRp[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
+ <listitem>
+ <para>
+ Lists replication publications.
+ If <replaceable class="parameter">pattern</replaceable> is
+ specified, only those publications whose names match the pattern are
+ listed.
+ If <literal>+</literal> is appended to the command name, the tables
+ associated with each publication are shown as well.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>\dRs[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
+ <listitem>
+ <para>
+ Lists replication subscriptions.
+ If <replaceable class="parameter">pattern</replaceable> is
+ specified, only those subscriptions whose names match the pattern are
+ listed.
+ If <literal>+</literal> is appended to the command name, additional
+ properties of the subscriptions are shown.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>\dT[S+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
<listitem>
<para>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 8acdff1393f..34007d3508d 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -54,11 +54,13 @@
&alterOperatorClass;
&alterOperatorFamily;
&alterPolicy;
+ &alterPublication;
&alterRole;
&alterRule;
&alterSchema;
&alterSequence;
&alterServer;
+ &alterSubscription;
&alterSystem;
&alterTable;
&alterTableSpace;
@@ -100,11 +102,13 @@
&createOperatorClass;
&createOperatorFamily;
&createPolicy;
+ &createPublication;
&createRole;
&createRule;
&createSchema;
&createSequence;
&createServer;
+ &createSubscription;
&createTable;
&createTableAs;
&createTableSpace;
@@ -144,11 +148,13 @@
&dropOperatorFamily;
&dropOwned;
&dropPolicy;
+ &dropPublication;
&dropRole;
&dropRule;
&dropSchema;
&dropSequence;
&dropServer;
+ &dropSubscription;
&dropTable;
&dropTableSpace;
&dropTSConfig;