aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/transam/multixact.c33
-rw-r--r--src/backend/utils/time/tqual.c36
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)