From 1b3ed757145dd6fa29feb6a31084527a6d6a46e3 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Tue, 22 Nov 2022 10:56:07 +0100 Subject: [PATCH] Ignore invalidated slots while computing oldest catalog Xmin Once a logical slot has acquired a catalog_xmin, it doesn't let go of it, even when invalidated by exceeding the max_slot_wal_keep_size, which means that dead catalog tuples are not removed by vacuum anymore since the point is invalidated, until the slot is dropped. This could be catastrophic if catalog churn is high. Change the computation of Xmin to ignore invalidated slots, to prevent dead rows from accumulating. Backpatch to 13, where slot invalidation appeared. Author: Sirisha Chamarthi Reviewed-by: Ashutosh Bapat Discussion: https://postgr.es/m/CAKrAKeUEDeqquN9vwzNeG-CN8wuVsfRYbeOUV9qKO_RHok=j+g@mail.gmail.com --- src/backend/replication/slot.c | 7 +++++++ src/backend/storage/ipc/procarray.c | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 3f34832151..037a347cba 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -778,6 +778,7 @@ ReplicationSlotsComputeRequiredXmin(bool already_locked) ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i]; TransactionId effective_xmin; TransactionId effective_catalog_xmin; + bool invalidated; if (!s->in_use) continue; @@ -785,8 +786,14 @@ ReplicationSlotsComputeRequiredXmin(bool already_locked) SpinLockAcquire(&s->mutex); effective_xmin = s->effective_xmin; effective_catalog_xmin = s->effective_catalog_xmin; + invalidated = (!XLogRecPtrIsInvalid(s->data.invalidated_at) && + XLogRecPtrIsInvalid(s->data.restart_lsn)); SpinLockRelease(&s->mutex); + /* invalidated slots need not apply */ + if (invalidated) + continue; + /* check the data xmin */ if (TransactionIdIsValid(effective_xmin) && (!TransactionIdIsValid(agg_xmin) || diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 755f842d6a..ea8278645e 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -3946,6 +3946,9 @@ ProcArraySetReplicationSlotXmin(TransactionId xmin, TransactionId catalog_xmin, if (!already_locked) LWLockRelease(ProcArrayLock); + + elog(DEBUG1, "xmin required by slots: data %u, catalog %u", + xmin, catalog_xmin); } /*