diff options
Diffstat (limited to 'src/backend/utils/time/tqual.c')
-rw-r--r-- | src/backend/utils/time/tqual.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index f787f2cbdc9..44b4ddcb02f 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -686,8 +686,36 @@ 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 (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) + { + TransactionId xmax; + + xmax = HeapTupleHeaderGetRawXmax(tuple); + + /* + * Careful here: even though this tuple was created by our own + * transaction, it might be locked by other transactions, if + * the original version was key-share locked when we updated + * it. + */ + + if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) + { + if (MultiXactHasRunningRemoteMembers(xmax)) + return HeapTupleBeingUpdated; + else + return HeapTupleMayBeUpdated; + } + + /* if locker is gone, all's well */ + if (!TransactionIdIsInProgress(xmax)) + return HeapTupleMayBeUpdated; + + if (!TransactionIdIsCurrentTransactionId(xmax)) + return HeapTupleBeingUpdated; + else + return HeapTupleMayBeUpdated; + } if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { @@ -700,7 +728,11 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, /* updating subtransaction must have aborted */ if (!TransactionIdIsCurrentTransactionId(xmax)) + { + if (MultiXactHasRunningRemoteMembers(HeapTupleHeaderGetRawXmax(tuple))) + return HeapTupleBeingUpdated; return HeapTupleMayBeUpdated; + } else { if (HeapTupleHeaderGetCmax(tuple) >= curcid) |