If a transaction marks a tuple for update and later commits without
actually having updated the tuple, do we still need the information
that the tuple has once been reserved for an update or can we simply
set the HEAP_XMAX_INVALID hint bit of the tuple?

In other words, is this snippet from a patch I'm working on a valid
modification to HeapTupleSatisfiesVacuum in tqual.c?

    {
        if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
            return HEAPTUPLE_LIVE;
-           if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
-               tuple->t_infomask |= HEAP_XMAX_COMMITTED;
-           else
-/* it's either aborted or crashed */
-               tuple->t_infomask |= HEAP_XMAX_INVALID;
+           /*
+            * We don't really care whether xmax did commit, abort or
+            * crash. We know that xmax did mark the tuple for update,
+            * but it did not and will never actually update it.
+            */
+           tuple->t_infomask |= HEAP_XMAX_INVALID;
    }
    return HEAPTUPLE_LIVE;

There are a few more places in tqual.c which could be simplified like
that.

Servus
 Manfred

Wed, 11 Jun 2003 09:21:48 +0200
Manfred Koizar <mkoi-pg@aon.at>
MARKED_FOR_UPDATE && XMAX_COMMITTED == XMAX_INVALID ?
Manfred Koizar <mkoi-pg@aon.at> writes:
> If a transaction marks a tuple for update and later commits without
> actually having updated the tuple, do we still need the information
> that the tuple has once been reserved for an update or can we simply
> set the HEAP_XMAX_INVALID hint bit of the tuple?

AFAICS this is a reasonable thing to do.

Eventually we might also be able to remove the bits of logic that check
for MARKED_FOR_UPDATE in a committed tuple, but that would not be
backwards-compatible so I'd vote against doing it immediately.

			regards, tom lane

Wed, 11 Jun 2003 09:05:33 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: MARKED_FOR_UPDATE && XMAX_COMMITTED == XMAX_INVALID ? 
On Wed, 11 Jun 2003 09:05:33 -0400, Tom Lane <tgl@sss.pgh.pa.us>
wrote:
>> If a transaction marks a tuple for update and later commits without
>> actually having updated the tuple, [...] can we simply
>> set the HEAP_XMAX_INVALID hint bit of the tuple?
>
>AFAICS this is a reasonable thing to do.

Thanks for the confirmation.  Here's a patch which also contains some
more noncritical changes to tqual.c:
 .  make code more readable by introducing local variables for xvac
 .  no longer two separate branches for aborted and crashed.
    The actions were the same in all cases.

Servus
 Manfred

diff -rcN ../base/src/backend/utils/time/tqual.c src/backend/utils/time/tqual.c
*** ../base/src/backend/utils/time/tqual.c	Thu May  8 21:45:55 2003
--- src/backend/utils/time/tqual.c	Thu Jun 12 12:10:31 2003
***************
*** 76,86 ****
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return false;
! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
--- 76,87 ----
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return false;
! 			if (!TransactionIdIsInProgress(xvac))
  			{
! 				if (TransactionIdDidCommit(xvac))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
***************
*** 90,100 ****
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  					return false;
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
--- 91,102 ----
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (!TransactionIdIsCurrentTransactionId(xvac))
  			{
! 				if (TransactionIdIsInProgress(xvac))
  					return false;
! 				if (TransactionIdDidCommit(xvac))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
***************
*** 152,162 ****
  	}
  
  	/* xmax transaction committed */
- 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  		return true;
  
  	return false;
  }
  
--- 154,167 ----
  	}
  
  	/* xmax transaction committed */
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ 	{
+ 		tuple->t_infomask |= HEAP_XMAX_INVALID;
  		return true;
+ 	}
  
+ 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  	return false;
  }
  
***************
*** 212,222 ****
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return false;
! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
--- 217,228 ----
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return false;
! 			if (!TransactionIdIsInProgress(xvac))
  			{
! 				if (TransactionIdDidCommit(xvac))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
***************
*** 226,236 ****
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  					return false;
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
--- 232,243 ----
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (!TransactionIdIsCurrentTransactionId(xvac))
  			{
! 				if (TransactionIdIsInProgress(xvac))
  					return false;
! 				if (TransactionIdDidCommit(xvac))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
***************
*** 297,307 ****
  	}
  
  	/* xmax transaction committed */
- 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  		return true;
  
  	return false;
  }
  
--- 304,317 ----
  	}
  
  	/* xmax transaction committed */
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ 	{
+ 		tuple->t_infomask |= HEAP_XMAX_INVALID;
  		return true;
+ 	}
  
+ 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  	return false;
  }
  
***************
*** 329,339 ****
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return false;
! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
--- 339,350 ----
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return false;
! 			if (!TransactionIdIsInProgress(xvac))
  			{
! 				if (TransactionIdDidCommit(xvac))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
***************
*** 343,353 ****
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  					return false;
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
--- 354,365 ----
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (!TransactionIdIsCurrentTransactionId(xvac))
  			{
! 				if (TransactionIdIsInProgress(xvac))
  					return false;
! 				if (TransactionIdDidCommit(xvac))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
***************
*** 382,392 ****
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return HeapTupleInvisible;
! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return HeapTupleInvisible;
--- 394,405 ----
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return HeapTupleInvisible;
! 			if (!TransactionIdIsInProgress(xvac))
  			{
! 				if (TransactionIdDidCommit(xvac))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return HeapTupleInvisible;
***************
*** 396,406 ****
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  					return HeapTupleInvisible;
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
--- 409,420 ----
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (!TransactionIdIsCurrentTransactionId(xvac))
  			{
! 				if (TransactionIdIsInProgress(xvac))
  					return HeapTupleInvisible;
! 				if (TransactionIdDidCommit(xvac))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
***************
*** 475,485 ****
  	}
  
  	/* xmax transaction committed */
- 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  		return HeapTupleMayBeUpdated;
  
  	return HeapTupleUpdated;	/* updated by other */
  }
  
--- 489,502 ----
  	}
  
  	/* xmax transaction committed */
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ 	{
+ 		tuple->t_infomask |= HEAP_XMAX_INVALID;
  		return HeapTupleMayBeUpdated;
+ 	}
  
+ 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  	return HeapTupleUpdated;	/* updated by other */
  }
  
***************
*** 513,523 ****
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return false;
! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
--- 530,541 ----
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return false;
! 			if (!TransactionIdIsInProgress(xvac))
  			{
! 				if (TransactionIdDidCommit(xvac))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
***************
*** 527,537 ****
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  					return false;
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
--- 545,556 ----
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (!TransactionIdIsCurrentTransactionId(xvac))
  			{
! 				if (TransactionIdIsInProgress(xvac))
  					return false;
! 				if (TransactionIdDidCommit(xvac))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
***************
*** 600,610 ****
  	}
  
  	/* xmax transaction committed */
- 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  		return true;
  
  	SnapshotDirty->tid = tuple->t_ctid;
  	return false;				/* updated by other */
  }
--- 619,632 ----
  	}
  
  	/* xmax transaction committed */
  
  	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ 	{
+ 		tuple->t_infomask |= HEAP_XMAX_INVALID;
  		return true;
+ 	}
  
+ 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  	SnapshotDirty->tid = tuple->t_ctid;
  	return false;				/* updated by other */
  }
***************
*** 644,654 ****
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return false;
! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
--- 666,677 ----
  
  		if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return false;
! 			if (!TransactionIdIsInProgress(xvac))
  			{
! 				if (TransactionIdDidCommit(xvac))
  				{
  					tuple->t_infomask |= HEAP_XMIN_INVALID;
  					return false;
***************
*** 658,668 ****
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  			{
! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  					return false;
! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
--- 681,692 ----
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (!TransactionIdIsCurrentTransactionId(xvac))
  			{
! 				if (TransactionIdIsInProgress(xvac))
  					return false;
! 				if (TransactionIdDidCommit(xvac))
  					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  				else
  				{
***************
*** 802,812 ****
  			return HEAPTUPLE_DEAD;
  		else if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return HEAPTUPLE_DELETE_IN_PROGRESS;
! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  				return HEAPTUPLE_DELETE_IN_PROGRESS;
! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  			{
  				tuple->t_infomask |= HEAP_XMIN_INVALID;
  				return HEAPTUPLE_DEAD;
--- 826,837 ----
  			return HEAPTUPLE_DEAD;
  		else if (tuple->t_infomask & HEAP_MOVED_OFF)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return HEAPTUPLE_DELETE_IN_PROGRESS;
! 			if (TransactionIdIsInProgress(xvac))
  				return HEAPTUPLE_DELETE_IN_PROGRESS;
! 			if (TransactionIdDidCommit(xvac))
  			{
  				tuple->t_infomask |= HEAP_XMIN_INVALID;
  				return HEAPTUPLE_DEAD;
***************
*** 815,825 ****
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
  				return HEAPTUPLE_INSERT_IN_PROGRESS;
! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
  				return HEAPTUPLE_INSERT_IN_PROGRESS;
! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
  				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  			else
  			{
--- 840,851 ----
  		}
  		else if (tuple->t_infomask & HEAP_MOVED_IN)
  		{
! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
! 			if (TransactionIdIsCurrentTransactionId(xvac))
  				return HEAPTUPLE_INSERT_IN_PROGRESS;
! 			if (TransactionIdIsInProgress(xvac))
  				return HEAPTUPLE_INSERT_IN_PROGRESS;
! 			if (TransactionIdDidCommit(xvac))
  				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  			else
  			{
***************
*** 831,846 ****
  			return HEAPTUPLE_INSERT_IN_PROGRESS;
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
  			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
- 		{
- 			tuple->t_infomask |= HEAP_XMIN_INVALID;
- 			return HEAPTUPLE_DEAD;
- 		}
  		else
  		{
  			/*
! 			 * Not in Progress, Not Committed, Not Aborted - so it's from
! 			 * crashed process. - vadim 11/26/96
  			 */
  			tuple->t_infomask |= HEAP_XMIN_INVALID;
  			return HEAPTUPLE_DEAD;
--- 857,866 ----
  			return HEAPTUPLE_INSERT_IN_PROGRESS;
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
  			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  		else
  		{
  			/*
! 			 * Not in Progress, Not Committed, so either Aborted or crashed
  			 */
  			tuple->t_infomask |= HEAP_XMIN_INVALID;
  			return HEAPTUPLE_DEAD;
***************
*** 868,878 ****
  		{
  			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
  				return HEAPTUPLE_LIVE;
! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
! 				tuple->t_infomask |= HEAP_XMAX_COMMITTED;
! 			else
! /* it's either aborted or crashed */
! 				tuple->t_infomask |= HEAP_XMAX_INVALID;
  		}
  		return HEAPTUPLE_LIVE;
  	}
--- 888,899 ----
  		{
  			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
  				return HEAPTUPLE_LIVE;
! 			/*
! 			 * We don't really care whether xmax did commit, abort or crash.
! 			 * We know that xmax did mark the tuple for update, but it did not
! 			 * and will never actually update it.
! 			 */
! 			tuple->t_infomask |= HEAP_XMAX_INVALID;
  		}
  		return HEAPTUPLE_LIVE;
  	}
***************
*** 883,898 ****
  			return HEAPTUPLE_DELETE_IN_PROGRESS;
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
  			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
- 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
- 		{
- 			tuple->t_infomask |= HEAP_XMAX_INVALID;
- 			return HEAPTUPLE_LIVE;
- 		}
  		else
  		{
  			/*
! 			 * Not in Progress, Not Committed, Not Aborted - so it's from
! 			 * crashed process. - vadim 06/02/97
  			 */
  			tuple->t_infomask |= HEAP_XMAX_INVALID;
  			return HEAPTUPLE_LIVE;
--- 904,913 ----
  			return HEAPTUPLE_DELETE_IN_PROGRESS;
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
  			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  		else
  		{
  			/*
! 			 * Not in Progress, Not Committed, so either Aborted or crashed
  			 */
  			tuple->t_infomask |= HEAP_XMAX_INVALID;
  			return HEAPTUPLE_LIVE;
Thu, 12 Jun 2003 15:59:27 +0200
Manfred Koizar <mkoi-pg@aon.at>
Re: [HACKERS] MARKED_FOR_UPDATE && XMAX_COMMITTED == XMAX_INVALID ? 

Your patch has been added to the PostgreSQL unapplied patches list at:

	http://momjian.postgresql.org/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Manfred Koizar wrote:
> On Wed, 11 Jun 2003 09:05:33 -0400, Tom Lane <tgl@sss.pgh.pa.us>
> wrote:
> >> If a transaction marks a tuple for update and later commits without
> >> actually having updated the tuple, [...] can we simply
> >> set the HEAP_XMAX_INVALID hint bit of the tuple?
> >
> >AFAICS this is a reasonable thing to do.
> 
> Thanks for the confirmation.  Here's a patch which also contains some
> more noncritical changes to tqual.c:
>  .  make code more readable by introducing local variables for xvac
>  .  no longer two separate branches for aborted and crashed.
>     The actions were the same in all cases.
> 
> Servus
>  Manfred

> diff -rcN ../base/src/backend/utils/time/tqual.c src/backend/utils/time/tqual.c
> *** ../base/src/backend/utils/time/tqual.c	Thu May  8 21:45:55 2003
> --- src/backend/utils/time/tqual.c	Thu Jun 12 12:10:31 2003
> ***************
> *** 76,86 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 76,87 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 90,100 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 91,102 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 152,162 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return true;
>   
>   	return false;
>   }
>   
> --- 154,167 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return true;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	return false;
>   }
>   
> ***************
> *** 212,222 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 217,228 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 226,236 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 232,243 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 297,307 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return true;
>   
>   	return false;
>   }
>   
> --- 304,317 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return true;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	return false;
>   }
>   
> ***************
> *** 329,339 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 339,350 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 343,353 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 354,365 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 382,392 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HeapTupleInvisible;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return HeapTupleInvisible;
> --- 394,405 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return HeapTupleInvisible;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return HeapTupleInvisible;
> ***************
> *** 396,406 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return HeapTupleInvisible;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 409,420 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return HeapTupleInvisible;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 475,485 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return HeapTupleMayBeUpdated;
>   
>   	return HeapTupleUpdated;	/* updated by other */
>   }
>   
> --- 489,502 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return HeapTupleMayBeUpdated;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	return HeapTupleUpdated;	/* updated by other */
>   }
>   
> ***************
> *** 513,523 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 530,541 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 527,537 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 545,556 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 600,610 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return true;
>   
>   	SnapshotDirty->tid = tuple->t_ctid;
>   	return false;				/* updated by other */
>   }
> --- 619,632 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return true;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	SnapshotDirty->tid = tuple->t_ctid;
>   	return false;				/* updated by other */
>   }
> ***************
> *** 644,654 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 666,677 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 658,668 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 681,692 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 802,812 ****
>   			return HEAPTUPLE_DEAD;
>   		else if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return HEAPTUPLE_DEAD;
> --- 826,837 ----
>   			return HEAPTUPLE_DEAD;
>   		else if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(xvac))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(xvac))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return HEAPTUPLE_DEAD;
> ***************
> *** 815,825 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   			else
>   			{
> --- 840,851 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(xvac))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(xvac))
>   				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   			else
>   			{
> ***************
> *** 831,846 ****
>   			return HEAPTUPLE_INSERT_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
> - 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
> - 		{
> - 			tuple->t_infomask |= HEAP_XMIN_INVALID;
> - 			return HEAPTUPLE_DEAD;
> - 		}
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, Not Aborted - so it's from
> ! 			 * crashed process. - vadim 11/26/96
>   			 */
>   			tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return HEAPTUPLE_DEAD;
> --- 857,866 ----
>   			return HEAPTUPLE_INSERT_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, so either Aborted or crashed
>   			 */
>   			tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return HEAPTUPLE_DEAD;
> ***************
> *** 868,878 ****
>   		{
>   			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
>   				return HEAPTUPLE_LIVE;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
> ! 				tuple->t_infomask |= HEAP_XMAX_COMMITTED;
> ! 			else
> ! /* it's either aborted or crashed */
> ! 				tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		}
>   		return HEAPTUPLE_LIVE;
>   	}
> --- 888,899 ----
>   		{
>   			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
>   				return HEAPTUPLE_LIVE;
> ! 			/*
> ! 			 * We don't really care whether xmax did commit, abort or crash.
> ! 			 * We know that xmax did mark the tuple for update, but it did not
> ! 			 * and will never actually update it.
> ! 			 */
> ! 			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		}
>   		return HEAPTUPLE_LIVE;
>   	}
> ***************
> *** 883,898 ****
>   			return HEAPTUPLE_DELETE_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
> - 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
> - 		{
> - 			tuple->t_infomask |= HEAP_XMAX_INVALID;
> - 			return HEAPTUPLE_LIVE;
> - 		}
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, Not Aborted - so it's from
> ! 			 * crashed process. - vadim 06/02/97
>   			 */
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   			return HEAPTUPLE_LIVE;
> --- 904,913 ----
>   			return HEAPTUPLE_DELETE_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, so either Aborted or crashed
>   			 */
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   			return HEAPTUPLE_LIVE;

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Mon, 23 Jun 2003 02:09:10 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: [HACKERS] MARKED_FOR_UPDATE && XMAX_COMMITTED == XMAX_INVALID ?

Patch applied.  Thanks.

---------------------------------------------------------------------------


Manfred Koizar wrote:
> On Wed, 11 Jun 2003 09:05:33 -0400, Tom Lane <tgl@sss.pgh.pa.us>
> wrote:
> >> If a transaction marks a tuple for update and later commits without
> >> actually having updated the tuple, [...] can we simply
> >> set the HEAP_XMAX_INVALID hint bit of the tuple?
> >
> >AFAICS this is a reasonable thing to do.
> 
> Thanks for the confirmation.  Here's a patch which also contains some
> more noncritical changes to tqual.c:
>  .  make code more readable by introducing local variables for xvac
>  .  no longer two separate branches for aborted and crashed.
>     The actions were the same in all cases.
> 
> Servus
>  Manfred

> diff -rcN ../base/src/backend/utils/time/tqual.c src/backend/utils/time/tqual.c
> *** ../base/src/backend/utils/time/tqual.c	Thu May  8 21:45:55 2003
> --- src/backend/utils/time/tqual.c	Thu Jun 12 12:10:31 2003
> ***************
> *** 76,86 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 76,87 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 90,100 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 91,102 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 152,162 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return true;
>   
>   	return false;
>   }
>   
> --- 154,167 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return true;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	return false;
>   }
>   
> ***************
> *** 212,222 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 217,228 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 226,236 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 232,243 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 297,307 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return true;
>   
>   	return false;
>   }
>   
> --- 304,317 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return true;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	return false;
>   }
>   
> ***************
> *** 329,339 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 339,350 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 343,353 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 354,365 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 382,392 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HeapTupleInvisible;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return HeapTupleInvisible;
> --- 394,405 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return HeapTupleInvisible;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return HeapTupleInvisible;
> ***************
> *** 396,406 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return HeapTupleInvisible;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 409,420 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return HeapTupleInvisible;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 475,485 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return HeapTupleMayBeUpdated;
>   
>   	return HeapTupleUpdated;	/* updated by other */
>   }
>   
> --- 489,502 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return HeapTupleMayBeUpdated;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	return HeapTupleUpdated;	/* updated by other */
>   }
>   
> ***************
> *** 513,523 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 530,541 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 527,537 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 545,556 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 600,610 ****
>   	}
>   
>   	/* xmax transaction committed */
> - 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
>   		return true;
>   
>   	SnapshotDirty->tid = tuple->t_ctid;
>   	return false;				/* updated by other */
>   }
> --- 619,632 ----
>   	}
>   
>   	/* xmax transaction committed */
>   
>   	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
> + 	{
> + 		tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		return true;
> + 	}
>   
> + 	tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   	SnapshotDirty->tid = tuple->t_ctid;
>   	return false;				/* updated by other */
>   }
> ***************
> *** 644,654 ****
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> --- 666,677 ----
>   
>   		if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return false;
> ! 			if (!TransactionIdIsInProgress(xvac))
>   			{
> ! 				if (TransactionIdDidCommit(xvac))
>   				{
>   					tuple->t_infomask |= HEAP_XMIN_INVALID;
>   					return false;
> ***************
> *** 658,668 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   			{
> ! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   					return false;
> ! 				if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> --- 681,692 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (!TransactionIdIsCurrentTransactionId(xvac))
>   			{
> ! 				if (TransactionIdIsInProgress(xvac))
>   					return false;
> ! 				if (TransactionIdDidCommit(xvac))
>   					tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   				else
>   				{
> ***************
> *** 802,812 ****
>   			return HEAPTUPLE_DEAD;
>   		else if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return HEAPTUPLE_DEAD;
> --- 826,837 ----
>   			return HEAPTUPLE_DEAD;
>   		else if (tuple->t_infomask & HEAP_MOVED_OFF)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(xvac))
>   				return HEAPTUPLE_DELETE_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(xvac))
>   			{
>   				tuple->t_infomask |= HEAP_XMIN_INVALID;
>   				return HEAPTUPLE_DEAD;
> ***************
> *** 815,825 ****
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
>   				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   			else
>   			{
> --- 840,851 ----
>   		}
>   		else if (tuple->t_infomask & HEAP_MOVED_IN)
>   		{
> ! 			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
> ! 			if (TransactionIdIsCurrentTransactionId(xvac))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdIsInProgress(xvac))
>   				return HEAPTUPLE_INSERT_IN_PROGRESS;
> ! 			if (TransactionIdDidCommit(xvac))
>   				tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   			else
>   			{
> ***************
> *** 831,846 ****
>   			return HEAPTUPLE_INSERT_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
> - 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
> - 		{
> - 			tuple->t_infomask |= HEAP_XMIN_INVALID;
> - 			return HEAPTUPLE_DEAD;
> - 		}
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, Not Aborted - so it's from
> ! 			 * crashed process. - vadim 11/26/96
>   			 */
>   			tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return HEAPTUPLE_DEAD;
> --- 857,866 ----
>   			return HEAPTUPLE_INSERT_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
>   			tuple->t_infomask |= HEAP_XMIN_COMMITTED;
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, so either Aborted or crashed
>   			 */
>   			tuple->t_infomask |= HEAP_XMIN_INVALID;
>   			return HEAPTUPLE_DEAD;
> ***************
> *** 868,878 ****
>   		{
>   			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
>   				return HEAPTUPLE_LIVE;
> ! 			if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
> ! 				tuple->t_infomask |= HEAP_XMAX_COMMITTED;
> ! 			else
> ! /* it's either aborted or crashed */
> ! 				tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		}
>   		return HEAPTUPLE_LIVE;
>   	}
> --- 888,899 ----
>   		{
>   			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
>   				return HEAPTUPLE_LIVE;
> ! 			/*
> ! 			 * We don't really care whether xmax did commit, abort or crash.
> ! 			 * We know that xmax did mark the tuple for update, but it did not
> ! 			 * and will never actually update it.
> ! 			 */
> ! 			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   		}
>   		return HEAPTUPLE_LIVE;
>   	}
> ***************
> *** 883,898 ****
>   			return HEAPTUPLE_DELETE_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
> - 		else if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
> - 		{
> - 			tuple->t_infomask |= HEAP_XMAX_INVALID;
> - 			return HEAPTUPLE_LIVE;
> - 		}
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, Not Aborted - so it's from
> ! 			 * crashed process. - vadim 06/02/97
>   			 */
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   			return HEAPTUPLE_LIVE;
> --- 904,913 ----
>   			return HEAPTUPLE_DELETE_IN_PROGRESS;
>   		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
>   			tuple->t_infomask |= HEAP_XMAX_COMMITTED;
>   		else
>   		{
>   			/*
> ! 			 * Not in Progress, Not Committed, so either Aborted or crashed
>   			 */
>   			tuple->t_infomask |= HEAP_XMAX_INVALID;
>   			return HEAPTUPLE_LIVE;

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Tue, 24 Jun 2003 21:08:20 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: [HACKERS] MARKED_FOR_UPDATE && XMAX_COMMITTED == XMAX_INVALID ?