aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorMasahiko Sawada <msawada@postgresql.org>2025-02-24 14:03:04 -0800
committerMasahiko Sawada <msawada@postgresql.org>2025-02-24 14:03:04 -0800
commit48796a98d5aed68e349118d4e05ac26b76c765b0 (patch)
treea3ddf904c411f6d7c9e0d3bda4f4484cd852ba74 /src/test
parentd1146dc2a72e96294045f7feb6d0f29082e1c71c (diff)
downloadpostgresql-48796a98d5aed68e349118d4e05ac26b76c765b0.tar.gz
postgresql-48796a98d5aed68e349118d4e05ac26b76c765b0.zip
Fix assertion when decoding XLOG_PARAMETER_CHANGE on promoted primary.
When a standby replays an XLOG_PARAMETER_CHANGE record that lowers wal_level below logical, we invalidate all logical slots in hot standby mode. However, if this record was replayed while not in hot standby mode, logical slots could remain valid even after promotion, potentially causing an assertion failure during WAL record decoding. To fix this issue, this commit adds a check for hot_standby status when restoring a logical replication slot on standbys. This check ensures that logical slots are invalidated when they become incompatible due to insufficient wal_level during recovery. Backpatch to v16 where logical decoding on standby was introduced. Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Discussion: https://postgr.es/m/CAD21AoABoFwGY_Rh2aeE6tEq3HkJxf0c6UeOXn4VV9v6BAQPSw%40mail.gmail.com Backpatch-through: 16
Diffstat (limited to 'src/test')
-rw-r--r--src/test/recovery/t/035_standby_logical_decoding.pl38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/test/recovery/t/035_standby_logical_decoding.pl b/src/test/recovery/t/035_standby_logical_decoding.pl
index 505e85d1eb6..8903177d883 100644
--- a/src/test/recovery/t/035_standby_logical_decoding.pl
+++ b/src/test/recovery/t/035_standby_logical_decoding.pl
@@ -343,6 +343,44 @@ $psql_subscriber{run} = IPC::Run::start(
IPC::Run::timeout($default_timeout));
##################################################
+# Test that the standby requires hot_standby to be
+# enabled for pre-existing logical slots.
+##################################################
+
+# create the logical slots
+$node_standby->create_logical_slot_on_standby($node_primary, 'restart_test');
+$node_standby->stop;
+$node_standby->append_conf('postgresql.conf', qq[hot_standby = off]);
+
+# Use run_log instead of $node_standby->start because this test expects
+# that the server ends with an error during startup.
+run_log(
+ [
+ 'pg_ctl',
+ '--pgdata' => $node_standby->data_dir,
+ '--log' => $node_standby->logfile,
+ 'start',
+ ]);
+
+# wait for postgres to terminate
+foreach my $i (0 .. 10 * $PostgreSQL::Test::Utils::timeout_default)
+{
+ last if !-f $node_standby->data_dir . '/postmaster.pid';
+ usleep(100_000);
+}
+
+# Confirm that the server startup fails with an expected error
+my $logfile = slurp_file($node_standby->logfile());
+ok( $logfile =~
+ qr/FATAL: .* logical replication slot ".*" exists on the standby, but "hot_standby" = "off"/,
+ "the standby ends with an error during startup because hot_standby was disabled"
+);
+$node_standby->adjust_conf('postgresql.conf', 'hot_standby', 'on');
+$node_standby->start;
+$node_standby->safe_psql('postgres',
+ qq[SELECT pg_drop_replication_slot('restart_test')]);
+
+##################################################
# Test that logical decoding on the standby
# behaves correctly.
##################################################