summaryrefslogtreecommitdiff
path: root/src/backend/utils/time/tqual.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2013-12-05 12:21:55 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2013-12-05 12:21:55 -0300
commit07aeb1fec571920839822c11851d38ef48952d6c (patch)
tree69d37e25fb835f9a1270c998951effdfbb4860db /src/backend/utils/time/tqual.c
parent86ef4796f5120c55d1a48cfab52e51df8ed271b5 (diff)
Avoid resetting Xmax when it's a multi with an aborted update
HeapTupleSatisfiesUpdate can very easily "forget" tuple locks while checking the contents of a multixact and finding it contains an aborted update, by setting the HEAP_XMAX_INVALID bit. This would lead to concurrent transactions not noticing any previous locks held by transactions that might still be running, and thus being able to acquire subsequent locks they wouldn't be normally able to acquire. This bug was introduced in commit 1ce150b7bb; backpatch this fix to 9.3, like that commit. This change reverts the change to the delete-abort-savept isolation test in 1ce150b7bb, because that behavior change was caused by this bug. Noticed by Andres Freund while investigating a different issue reported by Noah Misch.
Diffstat (limited to 'src/backend/utils/time/tqual.c')
-rw-r--r--src/backend/utils/time/tqual.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 1ebc5ff8795..e5d0b0a666e 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -596,13 +596,26 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
if (TransactionIdDidCommit(xmax))
return HeapTupleUpdated;
- /* no member, even just a locker, alive anymore */
+ /*
+ * By here, the update in the Xmax is either aborted or crashed, but
+ * what about the other members?
+ */
+
if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
+ {
+ /*
+ * There's no member, even just a locker, alive anymore, so we can
+ * mark the Xmax as invalid.
+ */
SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
InvalidTransactionId);
-
- /* it must have aborted or crashed */
- return HeapTupleMayBeUpdated;
+ return HeapTupleMayBeUpdated;
+ }
+ else
+ {
+ /* There are lockers running */
+ return HeapTupleBeingUpdated;
+ }
}
if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))