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");