diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 4b474c13917..6066c4784f4 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -8893,7 +8893,11 @@ SCRAM-SHA-256$<iteration count>:&l
Remote LSN of the state change used for synchronization coordination
when in s or r states,
- otherwise null
+ otherwise null. For sequences, this instead holds the publisher
+ sequence's page LSN as of the last synchronization, which does not
+ track replication progress the way it does for tables; see
+ for how it is used to detect
+ out-of-sync sequences.
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 1d8094c55d4..2d0ebd6f27d 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -2318,8 +2318,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage
Process ID of the leader apply worker if this process is a parallel
- apply worker; NULL if this process is a leader apply worker or a table
- synchronization worker
+ apply worker; NULL if this process is a leader apply worker, a table
+ synchronization worker or a sequence synchronization worker
@@ -2329,7 +2329,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage
OID of the relation that the worker is synchronizing; NULL for the
- leader apply worker and parallel apply workers
+ leader apply worker, parallel apply workers and the sequence
+ synchronization worker
@@ -2339,7 +2340,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage
Last write-ahead log location received, the initial value of
- this field being 0; NULL for parallel apply workers
+ this field being 0; NULL for parallel apply workers and the sequence
+ synchronization worker
@@ -2349,7 +2351,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
Send time of last message received from origin WAL sender; NULL for
- parallel apply workers
+ parallel apply workers and the sequence synchronization worker
@@ -2359,7 +2361,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
Receipt time of last message received from origin WAL sender; NULL for
- parallel apply workers
+ parallel apply workers and the sequence synchronization worker
@@ -2369,7 +2371,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
Last write-ahead log location reported to origin WAL sender; NULL for
- parallel apply workers
+ parallel apply workers and the sequence synchronization worker
@@ -2379,7 +2381,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage
Time of last write-ahead log location reported to origin WAL
- sender; NULL for parallel apply workers
+ sender; NULL for parallel apply workers and the sequence synchronization
+ worker
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index c05f7c5de4c..5eca5a5bb4a 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1229,34 +1229,6 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
}
}
- /*
- * Drop the tablesync slots associated with removed tables. This has
- * to be at the end because otherwise if there is an error while doing
- * the database operations we won't be able to rollback dropped slots.
- */
- foreach_ptr(SubRemoveRels, sub_remove_rel, sub_remove_rels)
- {
- if (sub_remove_rel->state != SUBREL_STATE_READY &&
- sub_remove_rel->state != SUBREL_STATE_SYNCDONE)
- {
- char syncslotname[NAMEDATALEN] = {0};
-
- /*
- * For READY/SYNCDONE states we know the tablesync slot has
- * already been dropped by the tablesync worker.
- *
- * For other states, there is no certainty, maybe the slot
- * does not exist yet. Also, if we fail after removing some of
- * the slots, next time, it will again try to drop already
- * dropped slots and fail. For these reasons, we allow
- * missing_ok = true for the drop.
- */
- ReplicationSlotNameForTablesync(sub->oid, sub_remove_rel->relid,
- syncslotname, sizeof(syncslotname));
- ReplicationSlotDropAtPubNode(wrconn, syncslotname, true);
- }
- }
-
/*
* Next remove state for sequences we should not care about anymore
* using the data we collected above
@@ -1284,6 +1256,34 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
sub->name));
}
}
+
+ /*
+ * Drop the tablesync slots associated with removed tables. This has
+ * to be at the end because otherwise if there is an error while doing
+ * the database operations we won't be able to rollback dropped slots.
+ */
+ foreach_ptr(SubRemoveRels, sub_remove_rel, sub_remove_rels)
+ {
+ if (sub_remove_rel->state != SUBREL_STATE_READY &&
+ sub_remove_rel->state != SUBREL_STATE_SYNCDONE)
+ {
+ char syncslotname[NAMEDATALEN] = {0};
+
+ /*
+ * For READY/SYNCDONE states we know the tablesync slot has
+ * already been dropped by the tablesync worker.
+ *
+ * For other states, there is no certainty, maybe the slot
+ * does not exist yet. Also, if we fail after removing some of
+ * the slots, next time, it will again try to drop already
+ * dropped slots and fail. For these reasons, we allow
+ * missing_ok = true for the drop.
+ */
+ ReplicationSlotNameForTablesync(sub->oid, sub_remove_rel->relid,
+ syncslotname, sizeof(syncslotname));
+ ReplicationSlotDropAtPubNode(wrconn, syncslotname, true);
+ }
+ }
}
PG_FINALLY();
{
diff --git a/src/backend/replication/logical/sequencesync.c b/src/backend/replication/logical/sequencesync.c
index 69a1a4c0473..40f0f1c6973 100644
--- a/src/backend/replication/logical/sequencesync.c
+++ b/src/backend/replication/logical/sequencesync.c
@@ -495,6 +495,7 @@ copy_sequences(WalReceiverConn *conn)
TupleTableSlot *slot;
StartTransactionCommand();
+ maybe_reread_subscription();
for (int idx = cur_batch_base_index; idx < n_seqinfos; idx++)
{
@@ -724,6 +725,7 @@ LogicalRepSyncSequences(void)
StringInfoData app_name;
StartTransactionCommand();
+ maybe_reread_subscription();
rel = table_open(SubscriptionRelRelationId, AccessShareLock);
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 7799266c614..dba4d743cf5 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -5977,8 +5977,18 @@ SetupApplyOrSyncWorker(int worker_slot)
*/
/* Initialise stats to a sanish value */
- MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
- MyLogicalRepWorker->reply_time = GetCurrentTimestamp();
+ if (am_sequencesync_worker())
+ {
+ MyLogicalRepWorker->last_send_time =
+ MyLogicalRepWorker->last_recv_time =
+ MyLogicalRepWorker->reply_time = 0;
+ }
+ else
+ {
+ MyLogicalRepWorker->last_send_time =
+ MyLogicalRepWorker->last_recv_time =
+ MyLogicalRepWorker->reply_time = GetCurrentTimestamp();
+ }
/* Load the libpq-specific functions */
load_file("libpqwalreceiver", false);
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 6207c91d482..745eb3d004c 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -2368,6 +2368,9 @@ match_previous_words(int pattern_id,
/* ALTER SUBSCRIPTION REFRESH */
else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH"))
COMPLETE_WITH("PUBLICATION", "SEQUENCES");
+ /* ALTER SUBSCRIPTION REFRESH PUBLICATION */
+ else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION"))
+ COMPLETE_WITH("WITH (");
/* ALTER SUBSCRIPTION REFRESH PUBLICATION WITH ( */
else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION", "WITH", "("))
COMPLETE_WITH("copy_data");