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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers