summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/catalogs.sgml2
-rw-r--r--doc/src/sgml/config.sgml16
-rw-r--r--doc/src/sgml/func/func-sequence.sgml28
-rw-r--r--doc/src/sgml/logical-replication.sgml294
-rw-r--r--doc/src/sgml/monitoring.sgml5
-rw-r--r--doc/src/sgml/ref/alter_subscription.sgml15
-rw-r--r--doc/src/sgml/ref/create_subscription.sgml31
7 files changed, 350 insertions, 41 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 6c8a0f173c9..2fc63442980 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -6568,7 +6568,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
(references <link linkend="catalog-pg-class"><structname>pg_class</structname></link>.<structfield>oid</structfield>)
</para>
<para>
- Reference to relation
+ Reference to table or sequence
</para></entry>
</row>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 683f7c36f46..d7e48f61905 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -5199,8 +5199,8 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
</para>
<para>
In logical replication, this parameter also limits how often a failing
- replication apply worker or table synchronization worker will be
- respawned.
+ replication apply worker or table/sequence synchronization worker will
+ be respawned.
</para>
</listitem>
</varlistentry>
@@ -5341,8 +5341,8 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
<listitem>
<para>
Specifies maximum number of logical replication workers. This includes
- leader apply workers, parallel apply workers, and table synchronization
- workers.
+ leader apply workers, parallel apply workers, and table/sequence
+ synchronization workers.
</para>
<para>
Logical replication workers are taken from the pool defined by
@@ -5365,10 +5365,14 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
<para>
Maximum number of synchronization workers per subscription. This
parameter controls the amount of parallelism of the initial data copy
- during the subscription initialization or when new tables are added.
+ for tables during the subscription initialization or when new tables
+ are added. One additional worker is also needed for sequence
+ synchronization.
</para>
<para>
- Currently, there can be only one synchronization worker per table.
+ Currently, there can be only one table synchronization worker per table
+ and one sequence synchronization worker to synchronize per
+ subscription.
</para>
<para>
The synchronization workers are taken from the pool defined by
diff --git a/doc/src/sgml/func/func-sequence.sgml b/doc/src/sgml/func/func-sequence.sgml
index e9f5b4e8e6b..e8d42b27c21 100644
--- a/doc/src/sgml/func/func-sequence.sgml
+++ b/doc/src/sgml/func/func-sequence.sgml
@@ -143,6 +143,34 @@ SELECT setval('myseq', 42, false); <lineannotation>Next <function>nextval</fu
or <literal>SELECT</literal> privilege on the last used sequence.
</para></entry>
</row>
+
+ <row>
+ <entry role="func_table_entry" id="func-pg-get-sequence-data"><para role="func_signature">
+ <indexterm>
+ <primary>pg_get_sequence_data</primary>
+ </indexterm>
+ <function>pg_get_sequence_data</function> ( <type>regclass</type> )
+ <returnvalue>record</returnvalue>
+ ( <parameter>last_value</parameter> <type>bigint</type>,
+ <parameter>is_called</parameter> <type>bool</type>,
+ <parameter>page_lsn</parameter> <type>pg_lsn</type> )
+ </para>
+ <para>
+ Returns information about the sequence.
+ <structfield>last_value</structfield> is the last sequence value
+ written to disk. If caching is used, this value can be greater than the
+ last value handed out from the sequence.
+ <structfield>is_called</structfield> indicates whether the sequence has
+ been used. <structfield>page_lsn</structfield> is the LSN corresponding
+ to the most recent WAL record that modified this sequence relation.
+ </para>
+ <para>
+ This function is primarily intended for internal use by pg_dump and by
+ logical replication to synchronize sequences. It requires
+ <literal>USAGE</literal> or <literal>SELECT</literal> privilege on the
+ sequence.
+ </para></entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index d64ed9dc36b..79ecd09614f 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -113,7 +113,9 @@
Publications may currently only contain tables or sequences. Objects must be
added explicitly, except when a publication is created using
<literal>FOR TABLES IN SCHEMA</literal>, <literal>FOR ALL TABLES</literal>,
- or <literal>FOR ALL SEQUENCES</literal>.
+ or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, sequences can be
+ synchronized at any time. For more information, see
+ <xref linkend="logical-replication-sequences"/>.
</para>
<para>
@@ -1745,6 +1747,247 @@ Publications:
</note>
</sect1>
+ <sect1 id="logical-replication-sequences">
+ <title>Replicating Sequences</title>
+
+ <para>
+ To synchronize sequences from a publisher to a subscriber, first publish
+ them using <link linkend="sql-createpublication-params-for-all-sequences">
+ <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link> and then
+ on the subscriber:
+ </para>
+
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ use <link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>
+ to initially synchronize the published sequences.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ use <link linkend="sql-altersubscription-params-refresh-publication">
+ <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command></link>
+ to synchronize only newly added sequences.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ use <link linkend="sql-altersubscription-params-refresh-sequences">
+ <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>
+ to re-synchronize all sequences currently known to the subscription.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ A <firstterm>sequence synchronization worker</firstterm> will be started
+ after executing any of the above subscriber commands, and will exit once the
+ sequences are synchronized.
+ </para>
+ <para>
+ The ability to launch a sequence synchronization worker is limited by the
+ <link linkend="guc-max-sync-workers-per-subscription">
+ <varname>max_sync_workers_per_subscription</varname></link>
+ configuration.
+ </para>
+
+ <sect2 id="sequence-definition-mismatches">
+ <title>Sequence Definition Mismatches</title>
+ <para>
+ The sequence synchronization worker validates that sequence definitions
+ match between publisher and subscriber. If mismatches exist, the worker
+ logs an error identifying them and exits. The apply worker continues
+ respawning the sequence synchronization worker until synchronization
+ succeeds. See also
+ <link linkend="guc-wal-retrieve-retry-interval"><varname>wal_retrieve_retry_interval</varname></link>.
+ </para>
+ <para>
+ To resolve this, use
+ <link linkend="sql-altersequence"><command>ALTER SEQUENCE</command></link>
+ to align the subscriber's sequence parameters with those of the publisher.
+ </para>
+ </sect2>
+
+ <sect2 id="sequences-out-of-sync">
+ <title>Refreshing Out-of-Sync Sequences</title>
+ <para>
+ Subscriber sequence values will become out of sync as the publisher
+ advances them.
+ </para>
+ <para>
+ To detect this, compare the
+ <link linkend="catalog-pg-subscription-rel">pg_subscription_rel</link>.<structfield>srsublsn</structfield>
+ on the subscriber with the <structfield>page_lsn</structfield> obtained
+ from the <link linkend="func-pg-get-sequence-data"><function>pg_get_sequence_data</function></link>
+ function for the sequence on the publisher. Then run
+ <link linkend="sql-altersubscription-params-refresh-sequences">
+ <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link> to
+ re-synchronize if necessary.
+ </para>
+ <warning>
+ <para>
+ Each sequence caches a block of values (typically 32) in memory before
+ generating a new WAL record, so its LSN advances only after the entire
+ cached batch has been consumed. As a result, sequence value drift cannot
+ be detected by LSN comparison when sequence increments fall within the
+ same cached block (typically 32 values).
+ </para>
+ </warning>
+ </sect2>
+
+ <sect2 id="logical-replication-sequences-examples">
+ <title>Examples</title>
+
+ <para>
+ Create some sequences on the publisher.
+<programlisting>
+/* pub # */ CREATE SEQUENCE s1 START WITH 10 INCREMENT BY 1;
+/* pub # */ CREATE SEQUENCE s2 START WITH 100 INCREMENT BY 10;
+</programlisting></para>
+
+ <para>
+ Create the same sequences on the subscriber.
+<programlisting>
+/* sub # */ CREATE SEQUENCE s1 START WITH 10 INCREMENT BY 1;
+/* sub # */ CREATE SEQUENCE s2 START WITH 100 INCREMENT BY 10;
+</programlisting></para>
+
+ <para>
+ Advance the sequences on the publisher a few times.
+<programlisting>
+/* pub # */ SELECT nextval('s1');
+ nextval
+---------
+ 10
+(1 row)
+/* pub # */ SELECT nextval('s1');
+ nextval
+---------
+ 11
+(1 row)
+/* pub # */ SELECT nextval('s2');
+ nextval
+---------
+ 100
+(1 row)
+/* pub # */ SELECT nextval('s2');
+ nextval
+---------
+ 110
+(1 row)
+</programlisting></para>
+
+ <para>
+ Check the sequence page LSNs on the publisher.
+<programlisting>
+/* pub # */ SELECT * FROM pg_get_sequence_data('s1');
+ last_value | is_called | page_lsn
+------------+-----------+------------
+ 11 | t | 0/0178F9E0
+(1 row)
+/* pub # */ SELECT * FROM pg_get_sequence_data('s2');
+ last_value | is_called | page_lsn
+------------+-----------+------------
+ 110 | t | 0/0178FAB0
+(1 row)
+</programlisting></para>
+
+ <para>
+ Create a publication for the sequences.
+<programlisting>
+/* pub # */ CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
+</programlisting></para>
+
+ <para>
+ Subscribe to the publication.
+<programlisting>
+/* sub # */ CREATE SUBSCRIPTION sub1
+/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=sub1'
+/* sub - */ PUBLICATION pub1;
+</programlisting></para>
+
+ <para>
+ Verify that the initial sequence values are synchronized.
+<programlisting>
+/* sub # */ SELECT last_value, is_called FROM s1;
+ last_value | is_called
+------------+-----------
+ 11 | t
+(1 row)
+
+/* sub # */ SELECT last_value, is_called FROM s2;
+ last_value | is_called
+------------+-----------
+ 110 | t
+(1 row)
+</programlisting></para>
+
+ <para>
+ Confirm that the sequence page LSNs on the publisher have been recorded
+ on the subscriber.
+<programlisting>
+/* sub # */ SELECT srrelid::regclass, srsublsn FROM pg_subscription_rel;
+ srrelid | srsublsn
+---------+------------
+ s1 | 0/0178F9E0
+ s2 | 0/0178FAB0
+(2 rows)
+</programlisting></para>
+
+ <para>
+ Advance the sequences on the publisher 50 more times.
+<programlisting>
+/* pub # */ SELECT nextval('s1') FROM generate_series(1,50);
+/* pub # */ SELECT nextval('s2') FROM generate_series(1,50);
+</programlisting></para>
+
+ <para>
+ Check the sequence page LSNs on the publisher.
+<programlisting>
+/* pub # */ SELECT * FROM pg_get_sequence_data('s1');
+ last_value | is_called | page_lsn
+------------+-----------+------------
+ 61 | t | 0/017CED28
+(1 row)
+
+/* pub # */ SELECT * FROM pg_get_sequence_data('s2');
+ last_value | is_called | page_lsn
+------------+-----------+------------
+ 610 | t | 0/017CEDF8
+(1 row)
+</programlisting></para>
+
+ <para>
+ The difference between the sequence page LSNs on the publisher and the
+ sequence page LSNs on the subscriber indicates that the sequences are out
+ of sync. Re-synchronize all sequences known to the subscriber using
+ <link linkend="sql-altersubscription-params-refresh-sequences">
+ <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>.
+<programlisting>
+/* sub # */ ALTER SUBSCRIPTION sub1 REFRESH SEQUENCES;
+</programlisting></para>
+
+ <para>
+ Recheck the sequences on the subscriber.
+<programlisting>
+/* sub # */ SELECT last_value, is_called FROM s1;
+ last_value | is_called
+------------+-----------
+ 61 | t
+(1 row)
+
+/* sub # */ SELECT last_value, is_called FROM s2;
+ last_value | is_called
+------------+-----------
+ 610 | t
+(1 row)
+</programlisting></para>
+ </sect2>
+ </sect1>
+
<sect1 id="logical-replication-conflicts">
<title>Conflicts</title>
@@ -2090,16 +2333,19 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<listitem>
<para>
- Sequence data is not replicated. The data in serial or identity columns
- backed by sequences will of course be replicated as part of the table,
- but the sequence itself would still show the start value on the
- subscriber. If the subscriber is used as a read-only database, then this
- should typically not be a problem. If, however, some kind of switchover
- or failover to the subscriber database is intended, then the sequences
- would need to be updated to the latest values, either by copying the
- current data from the publisher (perhaps
- using <command>pg_dump</command>) or by determining a sufficiently high
- value from the tables themselves.
+ Incremental sequence changes are not replicated. Although the data in
+ serial or identity columns backed by sequences will be replicated as part
+ of the table, the sequences themselves do not replicate ongoing changes.
+ On the subscriber, a sequence will retain the last value it synchronized
+ from the publisher. If the subscriber is used as a read-only database,
+ then this should typically not be a problem. If, however, some kind of
+ switchover or failover to the subscriber database is intended, then the
+ sequences would need to be updated to the latest values, either by
+ executing <link linkend="sql-altersubscription-params-refresh-sequences">
+ <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>
+ or by copying the current data from the publisher (perhaps using
+ <command>pg_dump</command>) or by determining a sufficiently high value
+ from the tables themselves.
</para>
</listitem>
@@ -2290,9 +2536,9 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
</para>
<para>
- In order to be able to copy the initial table data, the role used for the
- replication connection must have the <literal>SELECT</literal> privilege on
- a published table (or be a superuser).
+ In order to be able to copy the initial table or sequence data, the role
+ used for the replication connection must have the <literal>SELECT</literal>
+ privilege on a published table or sequence (or be a superuser).
</para>
<para>
@@ -2303,8 +2549,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<para>
To add tables to a publication, the user must have ownership rights on the
table. To add all tables in schema to a publication, the user must be a
- superuser. To create a publication that publishes all tables or all tables in
- schema automatically, the user must be a superuser.
+ superuser. To create a publication that publishes all tables, all tables in
+ schema, or all sequences automatically, the user must be a superuser.
</para>
<para>
@@ -2329,8 +2575,11 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
privileges of the subscription owner. However, when performing an insert,
update, delete, or truncate operation on a particular table, it will switch
roles to the table owner and perform the operation with the table owner's
- privileges. This means that the subscription owner needs to be able to
- <literal>SET ROLE</literal> to each role that owns a replicated table.
+ privileges. Similarly, when synchronizing sequence data, it will switch to
+ the sequence owner's role and perform the operation using the sequence
+ owner's privileges. This means that the subscription owner needs to be able
+ to <literal>SET ROLE</literal> to each role that owns a replicated table or
+ sequence.
</para>
<para>
@@ -2423,8 +2672,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<para>
<link linkend="guc-max-logical-replication-workers"><varname>max_logical_replication_workers</varname></link>
must be set to at least the number of subscriptions (for leader apply
- workers), plus some reserve for the table synchronization workers and
- parallel apply workers.
+ workers), plus some reserve for the parallel apply workers, and
+ table/sequence synchronization workers.
</para>
<para>
@@ -2437,8 +2686,9 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER
<para>
<link linkend="guc-max-sync-workers-per-subscription"><varname>max_sync_workers_per_subscription</varname></link>
- controls the amount of parallelism of the initial data copy during the
- subscription initialization or when new tables are added.
+ controls how many tables can be synchronized in parallel during
+ subscription initialization or when new tables are added. One additional
+ worker is also needed for sequence synchronization.
</para>
<para>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 2741c138593..7b9fa20df9e 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -2045,8 +2045,9 @@ description | Waiting for a newly initialized WAL file to reach durable storage
</para>
<para>
Type of the subscription worker process. Possible types are
- <literal>apply</literal>, <literal>parallel apply</literal>, and
- <literal>table synchronization</literal>.
+ <literal>apply</literal>, <literal>parallel apply</literal>,
+ <literal>table synchronization</literal>, and
+ <literal>sequence synchronization</literal>.
</para></entry>
</row>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index 8ab3b7fbd37..27c06439f4f 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -196,6 +196,12 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>.
</para>
<para>
+ See <xref linkend="sequence-definition-mismatches"/> for recommendations on how
+ to handle any warnings about sequence definition differences between
+ the publisher and the subscriber, which might occur when
+ <literal>copy_data = true</literal>.
+ </para>
+ <para>
See <xref linkend="sql-createsubscription-notes"/> for details of
how <literal>copy_data = true</literal> can interact with the
<link linkend="sql-createsubscription-params-with-origin"><literal>origin</literal></link>
@@ -225,6 +231,15 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
data for all currently subscribed sequences. It does not add or remove
sequences from the subscription to match the publication.
</para>
+ <para>
+ See <xref linkend="sequence-definition-mismatches"/> for
+ recommendations on how to handle any warnings about sequence definition
+ differences between the publisher and the subscriber.
+ </para>
+ <para>
+ See <xref linkend="sequences-out-of-sync"/> for recommendations on how to
+ identify and handle out-of-sync sequences.
+ </para>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index ed82cf1809e..197be0c6f6b 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -127,10 +127,10 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
<para>
Since no connection is made when this option is
- <literal>false</literal>, no tables are subscribed. To initiate
- replication, you must manually create the replication slot, enable
- the failover if required, enable the subscription, and refresh the
- subscription. See
+ <literal>false</literal>, no tables and sequences are subscribed. To
+ initiate replication, you must manually create the replication slot,
+ enable the failover if required, enable the subscription, and refresh
+ the subscription. See
<xref linkend="logical-replication-subscription-examples-deferred-slot"/>
for examples.
</para>
@@ -228,7 +228,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
the initial synchronization requires all data types to have binary
send and receive functions, otherwise the synchronization will fail
(see <xref linkend="sql-createtype"/> for more about send/receive
- functions).
+ functions). This parameter has no effect for sequences.
</para>
<para>
@@ -265,6 +265,12 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
<literal>copy_data = true</literal> can interact with the
<literal>origin</literal> parameter.
</para>
+ <para>
+ See <xref linkend="sequence-definition-mismatches"/>
+ for recommendations on how to handle any warnings about sequence
+ definition differences between the publisher and the subscriber,
+ which might occur when <literal>copy_data = true</literal>.
+ </para>
</listitem>
</varlistentry>
@@ -280,6 +286,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
temporary files and applied after the transaction is committed. Note
that if an error happens in a parallel apply worker, the finish LSN
of the remote transaction might not be reported in the server log.
+ This parameter has no effect for sequences.
</para>
<caution>
@@ -310,7 +317,8 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
The value of this parameter overrides the
<xref linkend="guc-synchronous-commit"/> setting within this
subscription's apply worker processes. The default value
- is <literal>off</literal>.
+ is <literal>off</literal>. This parameter has no effect for
+ sequences.
</para>
<para>
@@ -340,7 +348,8 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
<listitem>
<para>
Specifies whether two-phase commit is enabled for this subscription.
- The default is <literal>false</literal>.
+ The default is <literal>false</literal>. This parameter has no effect
+ for sequences.
</para>
<para>
@@ -398,8 +407,8 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
<para>
If true, all replication actions are performed as the subscription
owner. If false, replication workers will perform actions on each
- table as the owner of that table. The latter configuration is
- generally much more secure; for details, see
+ table or sequence as the owner of that relation. The latter
+ configuration is generally much more secure; for details, see
<xref linkend="logical-replication-security" />.
The default is <literal>false</literal>.
</para>
@@ -417,6 +426,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
changes that don't have an origin. Setting <literal>origin</literal>
to <literal>any</literal> means that the publisher sends changes
regardless of their origin. The default is <literal>any</literal>.
+ This parameter has no effect for sequences.
</para>
<para>
See <xref linkend="sql-createsubscription-notes"/> for details of how
@@ -449,7 +459,8 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
<xref linkend="conflict-update-deleted"/> is enabled, and a physical
replication slot named <quote><literal>pg_conflict_detection</literal></quote>
is created on the subscriber to prevent the information for detecting
- conflicts from being removed.
+ conflicts from being removed. This parameter has no effect for
+ sequences.
</para>
<para>