Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit48796a9

Browse files
Fix assertion when decoding XLOG_PARAMETER_CHANGE on promoted primary.
When a standby replays an XLOG_PARAMETER_CHANGE record that lowerswal_level below logical, we invalidate all logical slots in hotstandby mode. However, if this record was replayed while not in hotstandby 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 statuswhen restoring a logical replication slot on standbys. This checkensures that logical slots are invalidated when they becomeincompatible 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.comBackpatch-through: 16
1 parentd1146dc commit48796a9

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

‎src/backend/replication/slot.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,12 +2521,29 @@ RestoreSlotFromDisk(const char *name)
25212521
* NB: Changing the requirements here also requires adapting
25222522
* CheckSlotRequirements() and CheckLogicalDecodingRequirements().
25232523
*/
2524-
if (cp.slotdata.database!=InvalidOid&&wal_level<WAL_LEVEL_LOGICAL)
2525-
ereport(FATAL,
2526-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2527-
errmsg("logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"",
2528-
NameStr(cp.slotdata.name)),
2529-
errhint("Change \"wal_level\" to be \"logical\" or higher.")));
2524+
if (cp.slotdata.database!=InvalidOid)
2525+
{
2526+
if (wal_level<WAL_LEVEL_LOGICAL)
2527+
ereport(FATAL,
2528+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2529+
errmsg("logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"",
2530+
NameStr(cp.slotdata.name)),
2531+
errhint("Change \"wal_level\" to be \"logical\" or higher.")));
2532+
2533+
/*
2534+
* In standby mode, the hot standby must be enabled. This check is
2535+
* necessary to ensure logical slots are invalidated when they become
2536+
* incompatible due to insufficient wal_level. Otherwise, if the
2537+
* primary reduces wal_level < logical while hot standby is disabled,
2538+
* logical slots would remain valid even after promotion.
2539+
*/
2540+
if (StandbyMode&& !EnableHotStandby)
2541+
ereport(FATAL,
2542+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2543+
errmsg("logical replication slot \"%s\" exists on the standby, but \"hot_standby\" = \"off\"",
2544+
NameStr(cp.slotdata.name)),
2545+
errhint("Change \"hot_standby\" to be \"on\".")));
2546+
}
25302547
elseif (wal_level<WAL_LEVEL_REPLICA)
25312548
ereport(FATAL,
25322549
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

‎src/test/recovery/t/035_standby_logical_decoding.pl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,44 @@ sub wait_until_vacuum_can_remove
342342
\$psql_subscriber{subscriber_stderr},
343343
IPC::Run::timeout($default_timeout));
344344

345+
##################################################
346+
# Test that the standby requires hot_standby to be
347+
# enabled for pre-existing logical slots.
348+
##################################################
349+
350+
# create the logical slots
351+
$node_standby->create_logical_slot_on_standby($node_primary,'restart_test');
352+
$node_standby->stop;
353+
$node_standby->append_conf('postgresql.conf',qq[hot_standby = off]);
354+
355+
# Use run_log instead of $node_standby->start because this test expects
356+
# that the server ends with an error during startup.
357+
run_log(
358+
[
359+
'pg_ctl',
360+
'--pgdata'=>$node_standby->data_dir,
361+
'--log'=>$node_standby->logfile,
362+
'start',
363+
]);
364+
365+
# wait for postgres to terminate
366+
foreachmy$i (0 .. 10 *$PostgreSQL::Test::Utils::timeout_default)
367+
{
368+
lastif !-f$node_standby->data_dir .'/postmaster.pid';
369+
usleep(100_000);
370+
}
371+
372+
# Confirm that the server startup fails with an expected error
373+
my$logfile = slurp_file($node_standby->logfile());
374+
ok($logfile =~
375+
qr/FATAL: .* logical replication slot ".*" exists on the standby, but "hot_standby" = "off"/,
376+
"the standby ends with an error during startup because hot_standby was disabled"
377+
);
378+
$node_standby->adjust_conf('postgresql.conf','hot_standby','on');
379+
$node_standby->start;
380+
$node_standby->safe_psql('postgres',
381+
qq[SELECT pg_drop_replication_slot('restart_test')]);
382+
345383
##################################################
346384
# Test that logical decoding on the standby
347385
# behaves correctly.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp