Skip to content

Commit e1d6347

Browse files
committed
Don't mark pages all-visible spuriously
Dan Wood diagnosed a long-standing problem that pages containing tuples that are locked by multixacts containing live lockers may spuriously end up as candidates for getting their all-visible flag set. This has the long-term effect that multixacts remain unfrozen; this may previously pass undetected, but since commit XYZ it would be reported as "ERROR: found multixact 134100944 from before relminmxid 192042633" because when a later vacuum tries to freeze the page it detects that a multixact that should have gotten frozen, wasn't. Dan proposed a (correct) patch that simply sets a variable to its correct value, after a bogus initialization. But, per discussion, it seems better coding to avoid the bogus initializations altogether, since they could give rise to more bugs later. Therefore this fix rewrites the logic a little bit to avoid depending on the bogus initializations. This bug was part of a family introduced in 9.6 by commit a892234; later, commit 38e9f90 fixed most of them, but this one was unnoticed. Authors: Dan Wood, Pavan Deolasee, Álvaro Herrera Reviewed-by: Masahiko Sawada, Pavan Deolasee, Álvaro Herrera Discussion: https://postgr.es/m/84EBAC55-F06D-4FBE-A3F3-8BDA093CE3E3@amazon.com
1 parent 56a4564 commit e1d6347

File tree

1 file changed

+25
-15
lines changed

1 file changed

+25
-15
lines changed

src/backend/access/heap/heapam.c

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6650,9 +6650,10 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
66506650
xl_heap_freeze_tuple *frz, bool *totally_frozen_p)
66516651
{
66526652
bool changed = false;
6653-
bool freeze_xmax = false;
6653+
bool xmax_already_frozen = false;
6654+
bool xmin_frozen;
6655+
bool freeze_xmax;
66546656
TransactionId xid;
6655-
bool totally_frozen = true;
66566657

66576658
frz->frzflags = 0;
66586659
frz->t_infomask2 = tuple->t_infomask2;
@@ -6661,6 +6662,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
66616662

66626663
/* Process xmin */
66636664
xid = HeapTupleHeaderGetXmin(tuple);
6665+
xmin_frozen = ((xid == FrozenTransactionId) ||
6666+
HeapTupleHeaderXminFrozen(tuple));
66646667
if (TransactionIdIsNormal(xid))
66656668
{
66666669
if (TransactionIdPrecedes(xid, relfrozenxid))
@@ -6679,9 +6682,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
66796682

66806683
frz->t_infomask |= HEAP_XMIN_FROZEN;
66816684
changed = true;
6685+
xmin_frozen = true;
66826686
}
6683-
else
6684-
totally_frozen = false;
66856687
}
66866688

66876689
/*
@@ -6704,9 +6706,9 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67046706
relfrozenxid, relminmxid,
67056707
cutoff_xid, cutoff_multi, &flags);
67066708

6707-
if (flags & FRM_INVALIDATE_XMAX)
6708-
freeze_xmax = true;
6709-
else if (flags & FRM_RETURN_IS_XID)
6709+
freeze_xmax = (flags & FRM_INVALIDATE_XMAX);
6710+
6711+
if (flags & FRM_RETURN_IS_XID)
67106712
{
67116713
/*
67126714
* NB -- some of these transformations are only valid because we
@@ -6720,7 +6722,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67206722
if (flags & FRM_MARK_COMMITTED)
67216723
frz->t_infomask |= HEAP_XMAX_COMMITTED;
67226724
changed = true;
6723-
totally_frozen = false;
67246725
}
67256726
else if (flags & FRM_RETURN_IS_MULTI)
67266727
{
@@ -6742,11 +6743,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67426743
frz->xmax = newxmax;
67436744

67446745
changed = true;
6745-
totally_frozen = false;
6746-
}
6747-
else
6748-
{
6749-
Assert(flags & FRM_NOOP);
67506746
}
67516747
}
67526748
else if (TransactionIdIsNormal(xid))
@@ -6774,11 +6770,24 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67746770
freeze_xmax = true;
67756771
}
67766772
else
6777-
totally_frozen = false;
6773+
freeze_xmax = false;
67786774
}
6775+
else if ((tuple->t_infomask & HEAP_XMAX_INVALID) ||
6776+
!TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
6777+
{
6778+
freeze_xmax = false;
6779+
xmax_already_frozen = true;
6780+
}
6781+
else
6782+
ereport(ERROR,
6783+
(errcode(ERRCODE_DATA_CORRUPTED),
6784+
errmsg_internal("found xmax %u (infomask 0x%04x) not frozen, not multi, not normal",
6785+
xid, tuple->t_infomask)));
67796786

67806787
if (freeze_xmax)
67816788
{
6789+
Assert(!xmax_already_frozen);
6790+
67826791
frz->xmax = InvalidTransactionId;
67836792

67846793
/*
@@ -6831,7 +6840,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68316840
}
68326841
}
68336842

6834-
*totally_frozen_p = totally_frozen;
6843+
*totally_frozen_p = (xmin_frozen &&
6844+
(freeze_xmax || xmax_already_frozen));
68356845
return changed;
68366846
}
68376847

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy