1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-09 17:03:00 +03:00

Fix the handling of two GUCs during upgrade.

Previously, the check_hook functions for max_slot_wal_keep_size and
idle_replication_slot_timeout would incorrectly raise an ERROR for values
set in postgresql.conf during upgrade, even though those values were not
actively used in the upgrade process.

To prevent logical slot invalidation during upgrade, we used to set
special values for these GUCs. Now, instead of relying on those values, we
directly prevent WAL removal and logical slot invalidation caused by
max_slot_wal_keep_size and idle_replication_slot_timeout.

Note: PostgreSQL 17 does not include the idle_replication_slot_timeout
GUC, so related changes were not backported.

BUG #18979
Reported-by: jorsol <jorsol@gmail.com>
Author: Dilip Kumar <dilipbalaut@gmail.com>
Reviewed by: vignesh C <vignesh21@gmail.com>
Reviewed by: Alvaro Herrera <alvherre@alvh.no-ip.org>
Backpatch-through: 17, where it was introduced
Discussion: https://postgr.es/m/219561.1751826409@sss.pgh.pa.us
Discussion: https://postgr.es/m/18979-a1b7fdbb7cd181c6@postgresql.org
This commit is contained in:
Amit Kapila
2025-07-11 10:28:29 +05:30
parent a1973e5466
commit f36e577451
5 changed files with 14 additions and 77 deletions

View File

@@ -2346,25 +2346,6 @@ check_wal_segment_size(int *newval, void **extra, GucSource source)
return true;
}
/*
* GUC check_hook for max_slot_wal_keep_size
*
* We don't allow the value of max_slot_wal_keep_size other than -1 during the
* binary upgrade. See start_postmaster() in pg_upgrade for more details.
*/
bool
check_max_slot_wal_keep_size(int *newval, void **extra, GucSource source)
{
if (IsBinaryUpgrade && *newval != -1)
{
GUC_check_errdetail("\"%s\" must be set to -1 during binary upgrade mode.",
"max_slot_wal_keep_size");
return false;
}
return true;
}
/*
* At a checkpoint, how many WAL segments to recycle as preallocated future
* XLOG segments? Returns the highest segment that should be preallocated.
@@ -8151,17 +8132,19 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
XLByteToSeg(recptr, currSegNo, wal_segment_size);
segno = currSegNo;
/*
* Calculate how many segments are kept by slots first, adjusting for
* max_slot_wal_keep_size.
*/
/* Calculate how many segments are kept by slots. */
keep = XLogGetReplicationSlotMinimumLSN();
if (keep != InvalidXLogRecPtr && keep < recptr)
{
XLByteToSeg(keep, segno, wal_segment_size);
/* Cap by max_slot_wal_keep_size ... */
if (max_slot_wal_keep_size_mb >= 0)
/*
* Account for max_slot_wal_keep_size to avoid keeping more than
* configured. However, don't do that during a binary upgrade: if
* slots were to be invalidated because of this, it would not be
* possible to preserve logical ones during the upgrade.
*/
if (max_slot_wal_keep_size_mb >= 0 && !IsBinaryUpgrade)
{
uint64 slot_keep_segs;

View File

@@ -1887,15 +1887,6 @@ InvalidatePossiblyObsoleteSlot(uint32 possible_causes,
SpinLockRelease(&s->mutex);
/*
* The logical replication slots shouldn't be invalidated as GUC
* max_slot_wal_keep_size is set to -1 and
* idle_replication_slot_timeout is set to 0 during the binary
* upgrade. See check_old_cluster_for_valid_slots() where we ensure
* that no slot was invalidated before the upgrade.
*/
Assert(!(*invalidated && SlotIsLogical(s) && IsBinaryUpgrade));
/*
* Calculate the idle time duration of the slot if slot is marked
* invalidated with RS_INVAL_IDLE_TIMEOUT.
@@ -2042,6 +2033,10 @@ restart:
if (!s->in_use)
continue;
/* Prevent invalidation of logical slots during binary upgrade */
if (SlotIsLogical(s) && IsBinaryUpgrade)
continue;
if (InvalidatePossiblyObsoleteSlot(possible_causes, s, oldestLSN, dboid,
snapshotConflictHorizon,
&invalidated))
@@ -3054,22 +3049,3 @@ WaitForStandbyConfirmation(XLogRecPtr wait_for_lsn)
ConditionVariableCancelSleep();
}
/*
* GUC check_hook for idle_replication_slot_timeout
*
* The value of idle_replication_slot_timeout must be set to 0 during
* a binary upgrade. See start_postmaster() in pg_upgrade for more details.
*/
bool
check_idle_replication_slot_timeout(int *newval, void **extra, GucSource source)
{
if (IsBinaryUpgrade && *newval != 0)
{
GUC_check_errdetail("\"%s\" must be set to 0 during binary upgrade mode.",
"idle_replication_slot_timeout");
return false;
}
return true;
}

View File

@@ -3081,7 +3081,7 @@ struct config_int ConfigureNamesInt[] =
},
&max_slot_wal_keep_size_mb,
-1, -1, MAX_KILOBYTES,
check_max_slot_wal_keep_size, NULL, NULL
NULL, NULL, NULL
},
{
@@ -3104,7 +3104,7 @@ struct config_int ConfigureNamesInt[] =
},
&idle_replication_slot_timeout_secs,
0, 0, INT_MAX,
check_idle_replication_slot_timeout, NULL, NULL
NULL, NULL, NULL
},
{

View File

@@ -241,24 +241,6 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
if (cluster == &new_cluster)
appendPQExpBufferStr(&pgoptions, " -c synchronous_commit=off -c fsync=off -c full_page_writes=off");
/*
* Use max_slot_wal_keep_size as -1 to prevent the WAL removal by the
* checkpointer process. If WALs required by logical replication slots
* are removed, the slots are unusable. This setting prevents the
* invalidation of slots during the upgrade. We set this option when
* cluster is PG17 or later because logical replication slots can only be
* migrated since then. Besides, max_slot_wal_keep_size is added in PG13.
*/
if (GET_MAJOR_VERSION(cluster->major_version) >= 1700)
appendPQExpBufferStr(&pgoptions, " -c max_slot_wal_keep_size=-1");
/*
* Use idle_replication_slot_timeout=0 to prevent slot invalidation due to
* idle_timeout by checkpointer process during upgrade.
*/
if (GET_MAJOR_VERSION(cluster->major_version) >= 1800)
appendPQExpBufferStr(&pgoptions, " -c idle_replication_slot_timeout=0");
/*
* Use -b to disable autovacuum and logical replication launcher
* (effective in PG17 or later for the latter).

View File

@@ -84,8 +84,6 @@ extern const char *show_log_timezone(void);
extern void assign_maintenance_io_concurrency(int newval, void *extra);
extern void assign_io_max_combine_limit(int newval, void *extra);
extern void assign_io_combine_limit(int newval, void *extra);
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
GucSource source);
extern void assign_max_wal_size(int newval, void *extra);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
extern void assign_max_stack_depth(int newval, void *extra);
@@ -176,7 +174,5 @@ extern void assign_wal_sync_method(int new_wal_sync_method, void *extra);
extern bool check_synchronized_standby_slots(char **newval, void **extra,
GucSource source);
extern void assign_synchronized_standby_slots(const char *newval, void *extra);
extern bool check_idle_replication_slot_timeout(int *newval, void **extra,
GucSource source);
#endif /* GUC_HOOKS_H */