]> granicus.if.org Git - postgresql/commitdiff
Accept pg_upgraded tuples during multixact freezing
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 10 Jan 2014 21:03:18 +0000 (18:03 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 10 Jan 2014 21:03:18 +0000 (18:03 -0300)
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
src/backend/catalog/heap.c

index 05c790f3c77926682215a228a619c6a3dbb38383..a771ccb772c5bbab66ec0c417f480a0de155e26f 100644 (file)
@@ -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++)
                        {
index e94de8b25f497b3334624bcff576f51a1e37b295..2cf4bc033c85a12f44abbc92b228e1faa415cfee 100644 (file)
@@ -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;