Alvaro Herrera wrote:

> Well, it would help if those cases weren't dead code.  Neither
> heap_update nor heap_delete are ever called in the "no wait" case at
> all.  Only heap_lock_tuple is, and I can't see any misbehavior there
> either, even with HeapTupleBeingUpdated returned when there's a
> non-local locker, or when there's a MultiXact as xmax, regardless of its
> status.

I spent some more time trying to generate a test case that would show a
problem with the changed return values here, and was unable to.

I intend to apply this patch soon.

-- 
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
*** a/src/backend/utils/time/tqual.c
--- b/src/backend/utils/time/tqual.c
***************
*** 686,693 **** HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
  			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
  				return HeapTupleMayBeUpdated;
  
! 			if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))	/* not deleter */
  				return HeapTupleMayBeUpdated;
  
  			if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
  			{
--- 686,713 ----
  			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
  				return HeapTupleMayBeUpdated;
  
! 			if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
! 			{
! 				/*
! 				 * Careful here: even if this tuple was created by our
! 				 * transaction, it might be locked by other transactions, in
! 				 * case the original version was key-share locked when we
! 				 * updated it.	We cannot simply return MayBeUpdated, because
! 				 * that would lead to those locks being ignored in the future.
! 				 * Therefore we return HeapTupleBeingUpdated here, which
! 				 * causes the caller to recheck those locks.
! 				 *
! 				 * Note we might return BeingUpdated spuriously in some cases,
! 				 * particularly when there's a multixact which has no members
! 				 * outside of this transaction.  This doesn't cause any issues
! 				 * currently, but might need tweaking.
! 				 */
! 				if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
! 					return HeapTupleBeingUpdated;
! 				else if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
! 					return HeapTupleBeingUpdated;
  				return HeapTupleMayBeUpdated;
+ 			}
  
  			if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
  			{
***************
*** 700,706 **** HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
  
  				/* updating subtransaction must have aborted */
  				if (!TransactionIdIsCurrentTransactionId(xmax))
! 					return HeapTupleMayBeUpdated;
  				else
  				{
  					if (HeapTupleHeaderGetCmax(tuple) >= curcid)
--- 720,733 ----
  
  				/* updating subtransaction must have aborted */
  				if (!TransactionIdIsCurrentTransactionId(xmax))
! 				{
! 					/*
! 					 * This would normally be HeapTupleMayBeUpdated, but
! 					 * we do this instead to cause caller to recheck
! 					 * other lockers; see note above in the LOCKED_ONLY case.
! 					 */
! 					return HeapTupleBeingUpdated;
! 				}
  				else
  				{
  					if (HeapTupleHeaderGetCmax(tuple) >= curcid)
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to