]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Allow logical replication workers to ignore default_transaction_read_only.
authorAmit Kapila <akapila@postgresql.org>
Tue, 21 Jul 2026 03:42:52 +0000 (09:12 +0530)
committerAmit Kapila <akapila@postgresql.org>
Tue, 21 Jul 2026 03:42:52 +0000 (09:12 +0530)
Sequence synchronization updates sequence state via setval(), which
explicitly calls PreventCommandIfReadOnly(). If
default_transaction_read_only is enabled on the subscriber, this causes
sequencesync workers to fail with "cannot execute setval() in a read-only
transaction". Apply and tablesync workers are not affected, since they
write via direct heap access rather than through these read-only-checked
functions.

Rather than special-casing sequencesync, override
default_transaction_read_only to "off" for all logical replication workers
in InitializeLogRepWorker(), the same way session_replication_role and
search_path are already forced there. This keeps the initialization
uniform.

For PG-19, we kept the fix narrow by overriding
default_transaction_read_only to "off" only for sequencesync workers.

Reported-by: Noah Misch <noah@leadboat.com>
Author: vignesh C <vignesh21@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com

src/backend/replication/logical/sequencesync.c
src/test/subscription/t/036_sequences.pl

index 63ad46d7fd7b2a9f76eb294f48988afba47a9c53..82f503f1c0007f0d95b3a37d18fb98092496b1fc 100644 (file)
@@ -835,6 +835,14 @@ SequenceSyncWorkerMain(Datum main_arg)
 {
        int                     worker_slot = DatumGetInt32(main_arg);
 
+       /*
+        * Ignore default_transaction_read_only for sequence synchronization
+        * workers, as they need to be able to modify sequences regardless of that
+        * setting.
+        */
+       SetConfigOption("default_transaction_read_only", "off", PGC_SUSET,
+                                       PGC_S_OVERRIDE);
+
        SetupApplyOrSyncWorker(worker_slot);
 
        start_sequence_sync();
index 77ac9386cd86ebdf85e7c57adcc98cf4ffbd68c2..dd6fa515df3feb97fbf1975bd5ec835432034785 100644 (file)
@@ -188,6 +188,57 @@ is($result, '1|f',
        'REFRESH PUBLICATION will not sync newly published sequence with copy_data as false'
 );
 
+##########
+# Ensure that ALTER SUBSCRIPTION ... REFRESH SEQUENCES can still update
+# sequence values and mark the sequence as ready even when
+# default_transaction_read_only is enabled on the subscriber.
+##########
+
+$node_subscriber->safe_psql(
+       'postgres', qq(
+       ALTER SYSTEM SET default_transaction_read_only = on;
+       SELECT pg_reload_conf();
+));
+
+# Update the existing sequence 'regress_s3' on the publisher
+$node_publisher->safe_psql(
+       'postgres', qq(
+       INSERT INTO regress_seq_test SELECT nextval('regress_s3') FROM generate_series(1,100);
+));
+
+$node_subscriber->safe_psql(
+       'postgres', qq(
+       set default_transaction_read_only = off;
+       ALTER SUBSCRIPTION regress_seq_sub REFRESH SEQUENCES;
+));
+$node_subscriber->poll_query_until('postgres', $synced_query)
+  or die "Timed out while waiting for subscriber to synchronize data";
+
+# Check - sequence value is updated despite default_transaction_read_only
+# being enabled on the subscriber
+$result = $node_subscriber->safe_psql(
+       'postgres', qq(
+       SELECT last_value, is_called FROM regress_s3;
+));
+is($result, '200|t',
+       'REFRESH SEQUENCES updates sequence value with default_transaction_read_only enabled'
+);
+
+# Check - sequence is marked as ready ('r')
+$result = $node_subscriber->safe_psql(
+       'postgres', qq(
+       SELECT srsubstate FROM pg_subscription_rel WHERE srrelid = 'regress_s3'::regclass;
+));
+is($result, 'r',
+       'sequence is marked as ready after REFRESH SEQUENCES with default_transaction_read_only enabled'
+);
+
+$node_subscriber->safe_psql(
+       'postgres', qq(
+       ALTER SYSTEM SET default_transaction_read_only = off;
+       SELECT pg_reload_conf();
+));
+
 ##########
 # A sequence dropped concurrently on the publisher, while the sequencesync
 # worker's batch query is executing, must be treated the same as any other