From 423e1211a86df0d0dd8914223137edbfd4d52400 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Fri, 10 Jan 2014 18:03:18 -0300 Subject: [PATCH] Accept pg_upgraded tuples during multixact freezing The new MultiXact freezing routines introduced by commit 8e9a16ab8f7 neglected to consider tuples that came from a pg_upgrade'd database; a vacuum run that tried to freeze such tuples would die with an error such as ERROR: MultiXactId 11415437 does no longer exist -- apparent wraparound To fix, ensure that GetMultiXactIdMembers is allowed to return empty multis when the infomask bits are right, as is done in other callsites. Per trouble report from F-Secure. In passing, fix a copy&paste bug reported by Andrey Karpov from VIVA64 from their PVS-Studio static checked, that instead of setting relminmxid to Invalid, we were setting relfrozenxid twice. Not an important mistake because that code branch is about relations for which we don't use the frozenxid/minmxid values at all in the first place, but seems to warrants a fix nonetheless. --- src/backend/access/heap/heapam.c | 10 ++++++++-- src/backend/catalog/heap.c | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 05c790f3c7..a771ccb772 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -5456,6 +5456,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, bool has_lockers; TransactionId update_xid; bool update_committed; + bool allow_old; *flags = 0; @@ -5517,7 +5518,9 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, * anything. */ - nmembers = GetMultiXactIdMembers(multi, &members, false); + allow_old = !(t_infomask & HEAP_LOCK_MASK) && + HEAP_XMAX_IS_LOCKED_ONLY(t_infomask); + nmembers = GetMultiXactIdMembers(multi, &members, allow_old); if (nmembers <= 0) { /* Nothing worth keeping */ @@ -6219,10 +6222,13 @@ heap_tuple_needs_freeze(HeapTupleHeader tuple, TransactionId cutoff_xid, MultiXactMember *members; int nmembers; int i; + bool allow_old; /* need to check whether any member of the mxact is too old */ - nmembers = GetMultiXactIdMembers(multi, &members, false); + allow_old = !(tuple->t_infomask & HEAP_LOCK_MASK) && + HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask); + nmembers = GetMultiXactIdMembers(multi, &members, allow_old); for (i = 0; i < nmembers; i++) { diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index e94de8b25f..2cf4bc033c 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -911,7 +911,7 @@ AddNewRelationTuple(Relation pg_class_desc, * commands/sequence.c.) */ new_rel_reltup->relfrozenxid = InvalidTransactionId; - new_rel_reltup->relfrozenxid = InvalidMultiXactId; + new_rel_reltup->relminmxid = InvalidMultiXactId; } new_rel_reltup->relowner = relowner;