Ignore invalidated slots while computing oldest catalog Xmin
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 22 Nov 2022 09:56:07 +0000 (10:56 +0100)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 22 Nov 2022 09:56:07 +0000 (10:56 +0100)
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 <sirichamarthi22@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://postgr.es/m/CAKrAKeUEDeqquN9vwzNeG-CN8wuVsfRYbeOUV9qKO_RHok=j+g@mail.gmail.com

src/backend/replication/slot.c
src/backend/storage/ipc/procarray.c

index 329599e99dec52189d2a20305f206a82ffea81f5..80d96db8eb9d117db2737b5272654bd0f00b4e79 100644 (file)
@@ -846,6 +846,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;
@@ -853,8 +854,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) ||
index dadaa958a84104e1ff36b002200e21322e1bc754..0d1972104617f5ae016e52855480b926937c1332 100644 (file)
@@ -3900,6 +3900,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);
 }
 
 /*