diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 16c427e..5c66797 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -8109,7 +8109,7 @@ SCRAM-SHA-256$<iteration count>:&l This catalog only contains tables and sequences known to the subscription - after running either + after running CREATE SUBSCRIPTION or ALTER SUBSCRIPTION ... REFRESH PUBLICATION or diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml index eb7d544..f280019 100644 --- a/doc/src/sgml/ref/alter_subscription.sgml +++ b/doc/src/sgml/ref/alter_subscription.sgml @@ -200,6 +200,12 @@ ALTER SUBSCRIPTION name RENAME TO < ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES + See for recommendations on how + to handle any warnings about differences in the sequence definition + between the publisher and the subscriber, which might occur when + copy_data = true. + + See for details of how copy_data = true can interact with the origin @@ -211,11 +217,6 @@ ALTER SUBSCRIPTION name RENAME TO < parameter of CREATE SUBSCRIPTION for details about copying pre-existing data in binary format. - - See the copy_data - on how to handle the warnings regarding the difference in sequence - definition between the publisher and the subscriber. - @@ -230,12 +231,12 @@ ALTER SUBSCRIPTION name RENAME TO < sequence data with the publisher. Unlike ALTER SUBSCRIPTION ... REFRESH PUBLICATION which only synchronizes newly added sequences, REFRESH PUBLICATION SEQUENCES - will re-synchronize the sequence data for all subscribed sequences. The - sequence definition can differ between the publisher and the subscriber, - this is detected and a WARNING is logged to the user, but the warning is - only an indication of a potential problem; it is recommended to alter the - sequence to keep the sequence option same as the publisher and execute - the command again. + will re-synchronize the sequence data for all subscribed sequences. + + + See for recommendations on how + to handle any warnings about differences in the sequence definition + between the publisher and the subscriber. diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml index de3bdb8..e28ed96 100644 --- a/doc/src/sgml/ref/create_subscription.sgml +++ b/doc/src/sgml/ref/create_subscription.sgml @@ -264,12 +264,10 @@ CREATE SUBSCRIPTION subscription_nameorigin parameter. - The sequence definition can differ between the publisher and the - subscriber, this is detected and a WARNING is logged to the user, but - the warning is only an indication of a potential problem; it is - recommended to alter the sequence to keep the sequence option same as - the publisher and execute - ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES. + See for recommendations on how + to handle any warnings about differences in the sequence definition + between the publisher and the subscriber, which might occur when + copy_data = true. @@ -543,6 +541,17 @@ WHERE N.nspname = PT.schemaname AND PT.pubname IN (<pub-names>); + + Sequence definitions can differ between the publisher and the subscriber. + If this is detected, a WARNING is logged to inform the user of a + potential problem. It is recommended to use + ALTER SEQUENCE + to keep the subscriber sequence parameters the same as the publisher + sequence parameters. Then, execute + + ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES. + + diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index 8a2161e..876ab96 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -562,7 +562,7 @@ GetSubscriptionRelations(Oid subid, bool get_tables, bool get_sequences, if (!get_sequences) continue; - /* Skip all non-init sequences if not all_states were requested */ + /* Skip all non-init sequences unless all_states was requested */ if (!all_states && (subrel->srsubstate != SUBREL_STATE_INIT)) continue; } @@ -572,7 +572,7 @@ GetSubscriptionRelations(Oid subid, bool get_tables, bool get_sequences, if (!get_tables) continue; - /* Skip all ready tables if not all_states were requested */ + /* Skip all ready tables unless all_states was requested */ if (!all_states && (subrel->srsubstate == SUBREL_STATE_READY)) continue; } diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index ec7d5bb..322eb71 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -1898,13 +1898,13 @@ pg_sequence_last_value(PG_FUNCTION_ARGS) /* * Return the current on-disk state of the sequence. * + * Note: This is roughly equivalent to selecting the data from the sequence, + * except that it also returns the page LSN. + * * The page_lsn allows the user to determine if the sequence has been updated * since the last synchronization with the subscriber. This is done by * comparing the current page_lsn with the value stored in pg_subscription_rel * from the last synchronization. - * - * Note: This is roughly equivalent to selecting the data from the sequence, - * except that it also returns the page LSN. */ Datum pg_sequence_state(PG_FUNCTION_ARGS) diff --git a/src/backend/replication/logical/sequencesync.c b/src/backend/replication/logical/sequencesync.c index 2a5c8c5..44fa6ac 100644 --- a/src/backend/replication/logical/sequencesync.c +++ b/src/backend/replication/logical/sequencesync.c @@ -18,30 +18,19 @@ * ALTER SUBSCRIPTION ... REFRESH PUBLICATION * ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCE * - * Sequencesync worker will get the sequences that should be synchronized from - * pg_subscription_rel catalog table. It synchronizes - * MAX_SEQUENCES_SYNC_PER_BATCH (100) sequences within a single transaction by - * getting the sequence value from the remote publisher and updating it to the - * local subscriber sequence and updates the seqeunce state to READY. It also - * updates the remote sequence's lsn to pg_subscription_rel which can be - * later used to compare it with the pg_sequence_state page_lsn value to - * identify if sequence is changed since the last synchronization. - * - * The sequencesync worker retrieves the sequences that need to be synchronized - * from the pg_subscription_rel catalog table. It synchronizes up to - * MAX_SEQUENCES_SYNC_PER_BATCH (100) sequences in a single transaction by - * fetching the sequence values and the sequence's page_lsn from the remote - * publisher and updating them in the local subscriber sequence. After - * synchronization, it sets the sequence state to READY. This LSN can later be - * compared with the pg_sequence_state page LSN value to determine if the + * The sequencesync worker retrieves the sequences to be synchronized from the + * pg_subscription_rel catalog table. It synchronizes multiple sequences per + * single transaction by fetching the sequence value and page LSN from the + * remote publisher and updating them in the local subscriber sequence. After + * synchronization, it sets the sequence state to READY. The page LSN can + * later be compared with the pg_sequence_state page_lsn to determine if the * sequence has changed since the last synchronization. * * So the state progression is always just: INIT -> READY. * - * Here MAX_SEQUENCES_SYNC_PER_BATCH (100) sequences are synchronized within a - * single transaction to avoid creating a lot of transactions and also the - * locks on the sequence relation will be periodically released during the - * commit transaction. + * To avoid creating too many transactions, up to MAX_SEQUENCES_SYNC_PER_BATCH + * (100) sequences are synchronized per transaction. The locks on the sequence + * relation will be periodically released at each transaction commit. * *------------------------------------------------------------------------- */ @@ -70,12 +59,12 @@ * * The sequence last_value will be returned directly, while * log_cnt, is_called and page_lsn will be returned via the output - * parameters log_cnt, is_called and lsn, respectively. + * parameters log_cnt, is_called and page_lsn, respectively. */ static int64 fetch_remote_sequence_data(WalReceiverConn *conn, Oid remoteid, char *nspname, char *relname, int64 *log_cnt, bool *is_called, - XLogRecPtr *lsn) + XLogRecPtr *page_lsn) { WalRcvExecResult *res; StringInfoData cmd; @@ -114,7 +103,7 @@ fetch_remote_sequence_data(WalReceiverConn *conn, Oid remoteid, char *nspname, *is_called = DatumGetBool(slot_getattr(slot, 3, &isnull)); Assert(!isnull); - *lsn = DatumGetLSN(slot_getattr(slot, 4, &isnull)); + *page_lsn = DatumGetLSN(slot_getattr(slot, 4, &isnull)); Assert(!isnull); ExecDropSingleTupleTableSlot(slot); @@ -138,7 +127,7 @@ copy_sequence(WalReceiverConn *conn, Relation rel) int64 seq_last_value; int64 seq_log_cnt; bool seq_is_called; - XLogRecPtr seq_lsn = InvalidXLogRecPtr; + XLogRecPtr seq_page_lsn = InvalidXLogRecPtr; WalRcvExecResult *res; Oid tableRow[] = {OIDOID, CHAROID}; TupleTableSlot *slot; @@ -185,13 +174,13 @@ copy_sequence(WalReceiverConn *conn, Relation rel) seq_last_value = fetch_remote_sequence_data(conn, remoteid, nspname, relname, &seq_log_cnt, &seq_is_called, - &seq_lsn); + &seq_page_lsn); SetSequence(RelationGetRelid(rel), seq_last_value, seq_is_called, seq_log_cnt); /* return the LSN when the sequence state was set */ - return seq_lsn; + return seq_page_lsn; } /* diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h index 58abed9..1c954c9 100644 --- a/src/include/catalog/pg_subscription_rel.h +++ b/src/include/catalog/pg_subscription_rel.h @@ -92,6 +92,6 @@ extern void RemoveSubscriptionRel(Oid subid, Oid relid); extern bool HasSubscriptionRelations(Oid subid); extern List *GetSubscriptionRelations(Oid subid, bool get_tables, bool get_sequences, - bool all_relations); + bool all_states); #endif /* PG_SUBSCRIPTION_REL_H */ diff --git a/src/test/subscription/t/034_sequences.pl b/src/test/subscription/t/034_sequences.pl index 88f2705..100a420 100644 --- a/src/test/subscription/t/034_sequences.pl +++ b/src/test/subscription/t/034_sequences.pl @@ -67,9 +67,11 @@ my $result = $node_subscriber->safe_psql( )); is($result, '100|32|t', 'initial test data replicated'); -# ALTER SUBSCRIPTION ... REFRESH PUBLICATION should cause sync of new +########## +## ALTER SUBSCRIPTION ... REFRESH PUBLICATION should cause sync of new # sequences of the publisher, but changes to existing sequences should # not be synced. +########## # Create a new sequence 'regress_s2', and update existing sequence 'regress_s1' $node_publisher->safe_psql( @@ -105,9 +107,11 @@ $result = $node_subscriber->safe_psql( is($result, '100|32|t', 'REFRESH PUBLICATION will sync newly published sequence'); -# ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES should cause sync of +########## +## ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES should cause sync of # new sequences of the publisher, and changes to existing sequences should # also be synced. +########## # Create a new sequence 'regress_s3', and update the existing sequence # 'regress_s2'. @@ -128,7 +132,7 @@ $result = $node_subscriber->safe_psql( $node_subscriber->poll_query_until('postgres', $synced_query) or die "Timed out while waiting for subscriber to synchronize data"; -# Check - existing sequences are syned +# Check - existing sequences are synced $result = $node_subscriber->safe_psql( 'postgres', qq( SELECT last_value, log_cnt, is_called FROM regress_s1; @@ -150,8 +154,10 @@ $result = $node_subscriber->safe_psql( is($result, '100|32|t', 'REFRESH PUBLICATION SEQUENCES will sync newly published sequence'); +########## # ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES should throw a warning # for sequence definition not matching between the publisher and the subscriber. +########## # Create a new sequence 'regress_s4' whose START value is not the same in the # publisher and subscriber. @@ -165,6 +171,7 @@ $node_subscriber->safe_psql( CREATE SEQUENCE regress_s4 START 10 INCREMENT 2; )); +# Do ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES ($result, my $stdout, my $stderr) = $node_subscriber->psql( 'postgres', " ALTER SUBSCRIPTION regress_seq_sub REFRESH PUBLICATION SEQUENCES");