From 5ab0ad5c7e70dd44d87dcdad58d9064fe10aa3e3 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 11 Jan 2002 20:07:03 +0000 Subject: [PATCH] VACUUM must make sure that a HEAP_MARKED_FOR_UPDATE tuple gets marked 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 | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index 6c7f579312..b71b97088b 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -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; }