diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/transam/multixact.c | 33 | ||||
-rw-r--r-- | src/backend/utils/time/tqual.c | 36 |
2 files changed, 67 insertions, 2 deletions
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 55a8ca7ac49..03581bea663 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1275,6 +1275,39 @@ retry: } /* + * MultiXactHasRunningRemoteMembers + * Does the given multixact have still-live members from + * transactions other than our own? + */ +bool +MultiXactHasRunningRemoteMembers(MultiXactId multi) +{ + MultiXactMember *members; + int nmembers; + int i; + + nmembers = GetMultiXactIdMembers(multi, &members, true); + if (nmembers <= 0) + return false; + + for (i = 0; i < nmembers; i++) + { + /* not interested in our own members */ + if (TransactionIdIsCurrentTransactionId(members[i].xid)) + continue; + + if (TransactionIdIsInProgress(members[i].xid)) + { + pfree(members); + return true; + } + } + + pfree(members); + return false; +} + +/* * mxactMemberComparator * qsort comparison function for MultiXactMember * diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index e5d0b0a666e..1ff1da2f076 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -493,8 +493,36 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, 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) { @@ -507,7 +535,11 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, /* updating subtransaction must have aborted */ if (!TransactionIdIsCurrentTransactionId(xmax)) + { + if (MultiXactHasRunningRemoteMembers(HeapTupleHeaderGetRawXmax(tuple))) + return HeapTupleBeingUpdated; return HeapTupleMayBeUpdated; + } else { if (HeapTupleHeaderGetCmax(tuple) >= curcid) |