Skip to content

Commit d2599ec

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 966268c commit d2599ec

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
@@ -6803,9 +6803,10 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68036803
xl_heap_freeze_tuple *frz, bool *totally_frozen_p)
68046804
{
68056805
bool changed = false;
6806-
bool freeze_xmax = false;
6806+
bool xmax_already_frozen = false;
6807+
bool xmin_frozen;
6808+
bool freeze_xmax;
68076809
TransactionId xid;
6808-
bool totally_frozen = true;
68096810

68106811
frz->frzflags = 0;
68116812
frz->t_infomask2 = tuple->t_infomask2;
@@ -6814,6 +6815,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68146815

68156816
/* Process xmin */
68166817
xid = HeapTupleHeaderGetXmin(tuple);
6818+
xmin_frozen = ((xid == FrozenTransactionId) ||
6819+
HeapTupleHeaderXminFrozen(tuple));
68176820
if (TransactionIdIsNormal(xid))
68186821
{
68196822
if (TransactionIdPrecedes(xid, relfrozenxid))
@@ -6832,9 +6835,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68326835

68336836
frz->t_infomask |= HEAP_XMIN_FROZEN;
68346837
changed = true;
6838+
xmin_frozen = true;
68356839
}
6836-
else
6837-
totally_frozen = false;
68386840
}
68396841

68406842
/*
@@ -6857,9 +6859,9 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68576859
relfrozenxid, relminmxid,
68586860
cutoff_xid, cutoff_multi, &flags);
68596861

6860-
if (flags & FRM_INVALIDATE_XMAX)
6861-
freeze_xmax = true;
6862-
else if (flags & FRM_RETURN_IS_XID)
6862+
freeze_xmax = (flags & FRM_INVALIDATE_XMAX);
6863+
6864+
if (flags & FRM_RETURN_IS_XID)
68636865
{
68646866
/*
68656867
* NB -- some of these transformations are only valid because we
@@ -6873,7 +6875,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68736875
if (flags & FRM_MARK_COMMITTED)
68746876
frz->t_infomask |= HEAP_XMAX_COMMITTED;
68756877
changed = true;
6876-
totally_frozen = false;
68776878
}
68786879
else if (flags & FRM_RETURN_IS_MULTI)
68796880
{
@@ -6895,11 +6896,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
68956896
frz->xmax = newxmax;
68966897

68976898
changed = true;
6898-
totally_frozen = false;
6899-
}
6900-
else
6901-
{
6902-
Assert(flags & FRM_NOOP);
69036899
}
69046900
}
69056901
else if (TransactionIdIsNormal(xid))
@@ -6927,11 +6923,24 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
69276923
freeze_xmax = true;
69286924
}
69296925
else
6930-
totally_frozen = false;
6926+
freeze_xmax = false;
69316927
}
6928+
else if ((tuple->t_infomask & HEAP_XMAX_INVALID) ||
6929+
!TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
6930+
{
6931+
freeze_xmax = false;
6932+
xmax_already_frozen = true;
6933+
}
6934+
else
6935+
ereport(ERROR,
6936+
(errcode(ERRCODE_DATA_CORRUPTED),
6937+
errmsg_internal("found xmax %u (infomask 0x%04x) not frozen, not multi, not normal",
6938+
xid, tuple->t_infomask)));
69326939

69336940
if (freeze_xmax)
69346941
{
6942+
Assert(!xmax_already_frozen);
6943+
69356944
frz->xmax = InvalidTransactionId;
69366945

69376946
/*
@@ -6984,7 +6993,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
69846993
}
69856994
}
69866995

6987-
*totally_frozen_p = totally_frozen;
6996+
*totally_frozen_p = (xmin_frozen &&
6997+
(freeze_xmax || xmax_already_frozen));
69886998
return changed;
69896999
}
69907000

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