]> granicus.if.org Git - postgresql/commitdiff
VACUUM must make sure that a HEAP_MARKED_FOR_UPDATE tuple gets marked
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 11 Jan 2002 20:07:03 +0000 (20:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 11 Jan 2002 20:07:03 +0000 (20:07 +0000)
as either HEAP_XMAX_COMMITTED or HEAP_XMAX_INVALID once the updating
transaction is gone.  Otherwise some other transaction may come along
and try to test the commit status of t_xmax later --- which could be
after VACUUM has recycled the CLOG status for that xact.  Bug introduced
in post-beta4 bug fix.

src/backend/utils/time/tqual.c

index 6c7f579312e36f4655b05239d235e900228481f9..b71b97088bf4aa7497fffcd5ab8d600d9d055baf 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.45 2001/12/19 17:18:39 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.46 2002/01/11 20:07:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -742,7 +742,21 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
 
        if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
        {
-               /* "deleting" xact really only marked it for update */
+               /*
+                * "Deleting" xact really only marked it for update, so the tuple
+                * is live in any case.  However, we must make sure that either
+                * XMAX_COMMITTED or XMAX_INVALID gets set once the xact is gone;
+                * otherwise it is unsafe to recycle CLOG status after vacuuming.
+                */
+               if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
+               {
+                       if (TransactionIdIsInProgress(tuple->t_xmax))
+                               return HEAPTUPLE_LIVE;
+                       if (TransactionIdDidCommit(tuple->t_xmax))
+                               tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+                       else                            /* it's either aborted or crashed */
+                               tuple->t_infomask |= HEAP_XMAX_INVALID;
+               }
                return HEAPTUPLE_LIVE;
        }