diff options
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 309 | ||||
-rw-r--r-- | doc/src/sgml/config.sgml | 41 | ||||
-rw-r--r-- | doc/src/sgml/filelist.sgml | 1 | ||||
-rw-r--r-- | doc/src/sgml/func.sgml | 2 | ||||
-rw-r--r-- | doc/src/sgml/logical-replication.sgml | 396 | ||||
-rw-r--r-- | doc/src/sgml/monitoring.sgml | 74 | ||||
-rw-r--r-- | doc/src/sgml/postgres.sgml | 1 | ||||
-rw-r--r-- | doc/src/sgml/protocol.sgml | 721 | ||||
-rw-r--r-- | doc/src/sgml/ref/allfiles.sgml | 6 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_publication.sgml | 139 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_subscription.sgml | 139 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_publication.sgml | 206 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_subscription.sgml | 176 | ||||
-rw-r--r-- | doc/src/sgml/ref/drop_publication.sgml | 107 | ||||
-rw-r--r-- | doc/src/sgml/ref/drop_subscription.sgml | 110 | ||||
-rw-r--r-- | doc/src/sgml/ref/pg_dump.sgml | 21 | ||||
-rw-r--r-- | doc/src/sgml/ref/psql-ref.sgml | 28 | ||||
-rw-r--r-- | doc/src/sgml/reference.sgml | 6 |
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; ®ress; </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=> </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; |