Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Simplify multixact freezing a bit
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 29 Jul 2014 19:40:55 +0000 (15:40 -0400)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 29 Jul 2014 19:40:55 +0000 (15:40 -0400)
Testing for abortedness of a multixact member that's being frozen is
unnecessary: we only need to know whether the transaction is still in
progress or committed to determine whether it must be kept or not.  This
let us simplify the code a bit and avoid a useless TransactionIdDidAbort
test.

Suggested by Andres Freund awhile back.

src/backend/access/heap/heapam.c

index 35f9404ff4117f989f77489469d555782cb5f905..0524f2efdf3b95c9d8dacd1a8b7214269dbfdae0 100644 (file)
@@ -5627,17 +5627,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
 
            /*
             * It's an update; should we keep it?  If the transaction is known
-            * aborted then it's okay to ignore it, otherwise not.  However,
-            * if the Xid is older than the cutoff_xid, we must remove it.
-            * Note that such an old updater cannot possibly be committed,
-            * because HeapTupleSatisfiesVacuum would have returned
+            * aborted or crashed then it's okay to ignore it, otherwise not.
+            * Note that an updater older than cutoff_xid cannot possibly be
+            * committed, because HeapTupleSatisfiesVacuum would have returned
             * HEAPTUPLE_DEAD and we would not be trying to freeze the tuple.
             *
-            * Note the TransactionIdDidAbort() test is just an optimization
-            * and not strictly necessary for correctness.
-            *
             * As with all tuple visibility routines, it's critical to test
-            * TransactionIdIsInProgress before the transam.c routines,
+            * TransactionIdIsInProgress before TransactionIdDidCommit,
             * because of race conditions explained in detail in tqual.c.
             */
            if (TransactionIdIsCurrentTransactionId(xid) ||
@@ -5646,46 +5642,40 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
                Assert(!TransactionIdIsValid(update_xid));
                update_xid = xid;
            }
-           else if (!TransactionIdDidAbort(xid))
+           else if (TransactionIdDidCommit(xid))
            {
                /*
-                * Test whether to tell caller to set HEAP_XMAX_COMMITTED
-                * while we have the Xid still in cache.  Note this can only
-                * be done if the transaction is known not running.
+                * The transaction committed, so we can tell caller to set
+                * HEAP_XMAX_COMMITTED.  (We can only do this because we know
+                * the transaction is not running.)
                 */
-               if (TransactionIdDidCommit(xid))
-                   update_committed = true;
                Assert(!TransactionIdIsValid(update_xid));
+               update_committed = true;
                update_xid = xid;
            }
 
+           /*
+            * Not in progress, not committed -- must be aborted or crashed;
+            * we can ignore it.
+            */
+
+           /*
+            * Since the tuple wasn't marked HEAPTUPLE_DEAD by vacuum, the
+            * update Xid cannot possibly be older than the xid cutoff.
+            */
+           Assert(!TransactionIdIsValid(update_xid) ||
+                  !TransactionIdPrecedes(update_xid, cutoff_xid));
+
            /*
             * If we determined that it's an Xid corresponding to an update
             * that must be retained, additionally add it to the list of
-            * members of the new Multis, in case we end up using that.  (We
+            * members of the new Multi, in case we end up using that.  (We
             * might still decide to use only an update Xid and not a multi,
             * but it's easier to maintain the list as we walk the old members
             * list.)
-            *
-            * It is possible to end up with a very old updater Xid that
-            * crashed and thus did not mark itself as aborted in pg_clog.
-            * That would manifest as a pre-cutoff Xid.  Make sure to ignore
-            * it.
             */
            if (TransactionIdIsValid(update_xid))
-           {
-               if (!TransactionIdPrecedes(update_xid, cutoff_xid))
-               {
-                   newmembers[nnewmembers++] = members[i];
-               }
-               else
-               {
-                   /* cannot have committed: would be HEAPTUPLE_DEAD */
-                   Assert(!TransactionIdDidCommit(update_xid));
-                   update_xid = InvalidTransactionId;
-                   update_committed = false;
-               }
-           }
+               newmembers[nnewmembers++] = members[i];
        }
        else
        {