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