]> granicus.if.org Git - postgresql/commitdiff
Avoid repeated CLOG access from heap_hot_search_buffer.
authorRobert Haas <rhaas@postgresql.org>
Wed, 2 May 2012 16:40:07 +0000 (12:40 -0400)
committerRobert Haas <rhaas@postgresql.org>
Wed, 2 May 2012 16:40:07 +0000 (12:40 -0400)
At the time we check whether the tuple is dead to all running
transactions, we've already verified that it isn't visible to our
scan, setting hint bits if appropriate.  So there's no need to
recheck CLOG for the all-dead test we do just a moment later.
So, add HeapTupleIsSurelyDead() to test the appropriate condition
under the assumption that all relevant hit bits are already set.

Review by Tom Lane.

src/backend/access/heap/heapam.c
src/backend/utils/time/tqual.c
src/include/utils/tqual.h

index 3259354d5e08fa16458b2af6a01e493e758e3203..7e4c8f52ab2a503cae4b0fd15d6be1fa0adb4bd5 100644 (file)
@@ -1609,8 +1609,7 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
                 * transactions.
                 */
                if (all_dead && *all_dead &&
-                       HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin,
-                                                                        buffer) != HEAPTUPLE_DEAD)
+                       !HeapTupleIsSurelyDead(heapTuple->t_data, RecentGlobalXmin))
                        *all_dead = false;
 
                /*
index c1c78c389cb84d99e4324f3ace8000a2341f1fcf..727e0bf91bf365fbc0704bae7f2723089a5d7957 100644 (file)
@@ -1219,6 +1219,46 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
        return HEAPTUPLE_DEAD;
 }
 
+/*
+ * HeapTupleIsSurelyDead
+ *
+ *     Determine whether a tuple is surely dead.  We sometimes use this
+ *     in lieu of HeapTupleSatisifesVacuum when the tuple has just been
+ *     tested by HeapTupleSatisfiesMVCC and, therefore, any hint bits that
+ *     can be set should already be set.  We assume that if no hint bits
+ *     either for xmin or xmax, the transaction is still running.  This is
+ *     therefore faster than HeapTupleSatisfiesVacuum, because we don't
+ *     consult CLOG (and also because we don't need to give an exact answer,
+ *     just whether or not the tuple is surely dead).
+ */
+bool
+HeapTupleIsSurelyDead(HeapTupleHeader tuple, TransactionId OldestXmin)
+{
+       /*
+        * If the inserting transaction is marked invalid, then it aborted,
+        * and the tuple is definitely dead.  If it's marked neither committed
+        * nor invalid, then we assume it's still alive (since the presumption
+        * is that all relevant hint bits were just set moments ago).
+        */
+       if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
+               return (tuple->t_infomask & HEAP_XMIN_INVALID) != 0 ? true : false;
+
+       /*
+        * If the inserting transaction committed, but any deleting transaction
+        * aborted, the tuple is still alive.  Likewise, if XMAX is a lock rather
+        * than a delete, the tuple is still alive.
+        */
+       if (tuple->t_infomask &
+               (HEAP_XMAX_INVALID | HEAP_IS_LOCKED | HEAP_XMAX_IS_MULTI))
+               return false;
+
+       /* If deleter isn't known to have committed, assume it's still running. */
+       if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
+               return false;
+
+       /* Deleter committed, so tuple is dead if the XID is old enough. */
+       return TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin);
+}
 
 /*
  * XidInMVCCSnapshot
index 0f8a7f8c2d24f6842df41be6292ada120cc89be0..3d8a480d8106bf9e02722247cf2cb74ffcc6e5e5 100644 (file)
@@ -83,6 +83,8 @@ extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple,
                                                 CommandId curcid, Buffer buffer);
 extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
                                                 TransactionId OldestXmin, Buffer buffer);
+extern bool HeapTupleIsSurelyDead(HeapTupleHeader tuple,
+                                                TransactionId OldestXmin);
 
 extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
                                         uint16 infomask, TransactionId xid);