Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3a11485

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 a9fbf55 commit 3a11485

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
@@ -6676,9 +6676,10 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
66766676
xl_heap_freeze_tuple *frz, bool *totally_frozen_p)
66776677
{
66786678
bool changed = false;
6679-
bool freeze_xmax = false;
6679+
bool xmax_already_frozen = false;
6680+
bool xmin_frozen;
6681+
bool freeze_xmax;
66806682
TransactionId xid;
6681-
bool totally_frozen = true;
66826683

66836684
frz->frzflags = 0;
66846685
frz->t_infomask2 = tuple->t_infomask2;
@@ -6687,6 +6688,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
66876688

66886689
/* Process xmin */
66896690
xid = HeapTupleHeaderGetXmin(tuple);
6691+
xmin_frozen = ((xid == FrozenTransactionId) ||
6692+
HeapTupleHeaderXminFrozen(tuple));
66906693
if (TransactionIdIsNormal(xid))
66916694
{
66926695
if (TransactionIdPrecedes(xid, relfrozenxid))
@@ -6705,9 +6708,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67056708

67066709
frz->t_infomask |= HEAP_XMIN_FROZEN;
67076710
changed = true;
6711+
xmin_frozen = true;
67086712
}
6709-
else
6710-
totally_frozen = false;
67116713
}
67126714

67136715
/*
@@ -6730,9 +6732,9 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67306732
relfrozenxid, relminmxid,
67316733
cutoff_xid, cutoff_multi, &flags);
67326734

6733-
if (flags & FRM_INVALIDATE_XMAX)
6734-
freeze_xmax = true;
6735-
else if (flags & FRM_RETURN_IS_XID)
6735+
freeze_xmax = (flags & FRM_INVALIDATE_XMAX);
6736+
6737+
if (flags & FRM_RETURN_IS_XID)
67366738
{
67376739
/*
67386740
* NB -- some of these transformations are only valid because we
@@ -6746,7 +6748,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67466748
if (flags & FRM_MARK_COMMITTED)
67476749
frz->t_infomask |= HEAP_XMAX_COMMITTED;
67486750
changed = true;
6749-
totally_frozen = false;
67506751
}
67516752
else if (flags & FRM_RETURN_IS_MULTI)
67526753
{
@@ -6768,11 +6769,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
67686769
frz->xmax = newxmax;
67696770

67706771
changed = true;
6771-
totally_frozen = false;
6772-
}
6773-
else
6774-
{
6775-
Assert(flags & FRM_NOOP);
67766772
}
67776773
}
67786774
else if (TransactionIdIsNormal(xid))
@@ -6800,11 +6796,24 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68006796
freeze_xmax = true;
68016797
}
68026798
else
6803-
totally_frozen = false;
6799+
freeze_xmax = false;
68046800
}
6801+
else if ((tuple->t_infomask & HEAP_XMAX_INVALID) ||
6802+
!TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
6803+
{
6804+
freeze_xmax = false;
6805+
xmax_already_frozen = true;
6806+
}
6807+
else
6808+
ereport(ERROR,
6809+
(errcode(ERRCODE_DATA_CORRUPTED),
6810+
errmsg_internal("found xmax %u (infomask 0x%04x) not frozen, not multi, not normal",
6811+
xid, tuple->t_infomask)));
68056812

68066813
if (freeze_xmax)
68076814
{
6815+
Assert(!xmax_already_frozen);
6816+
68086817
frz->xmax = InvalidTransactionId;
68096818

68106819
/*
@@ -6857,7 +6866,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68576866
}
68586867
}
68596868

6860-
*totally_frozen_p = totally_frozen;
6869+
*totally_frozen_p = (xmin_frozen &&
6870+
(freeze_xmax || xmax_already_frozen));
68616871
return changed;
68626872
}
68636873

0 commit comments

Comments
 (0)