aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2022-01-04 13:01:05 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2022-01-04 13:01:05 -0300
commit6b681cd056bb8c821f8853463938070ce0dade8f (patch)
tree62afeed4beff04ea064efe892d3833a7742ceb63
parent9c4f38908447c1c6a910e4a16e0644e0ccade204 (diff)
downloadpostgresql-6b681cd056bb8c821f8853463938070ce0dade8f.tar.gz
postgresql-6b681cd056bb8c821f8853463938070ce0dade8f.zip
Allow special SKIP LOCKED condition in Assert()
Under concurrency, it is possible for two sessions to be merrily locking and releasing a tuple and marking it again as HEAP_XMAX_INVALID all the while a third session attempts to lock it, miserably fails at it, and then contemplates life, the universe and everything only to eventually fail an assertion that said bit is not set. Before SKIP LOCKED that was indeed a reasonable expectation, but alas! commit df630b0dd5ea falsified it. This bug is as old as time itself, and even older, if you think time begins with the oldest supported branch. Therefore, backpatch to all supported branches. Author: Simon Riggs <simon.riggs@enterprisedb.com> Discussion: https://postgr.es/m/CANbhV-FeEwMnN8yuMyss7if1ZKjOKfjcgqB26n8pqu1e=q0ebg@mail.gmail.com
-rw-r--r--src/backend/access/heap/heapam.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c2a38b55f19..a9ea6d83eae 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -4528,7 +4528,15 @@ failed:
{
Assert(result == TM_SelfModified || result == TM_Updated ||
result == TM_Deleted || result == TM_WouldBlock);
- Assert(!(tuple->t_data->t_infomask & HEAP_XMAX_INVALID));
+
+ /*
+ * When locking a tuple under LockWaitSkip semantics and we fail with
+ * TM_WouldBlock above, it's possible for concurrent transactions to
+ * release the lock and set HEAP_XMAX_INVALID in the meantime. So
+ * this assert is slightly different from the equivalent one in
+ * heap_delete and heap_update.
+ */
+ Assert(TM_WouldBlock || !(tuple->t_data->t_infomask & HEAP_XMAX_INVALID));
Assert(result != TM_Updated ||
!ItemPointerEquals(&tuple->t_self, &tuple->t_data->t_ctid));
tmfd->ctid = tuple->t_data->t_ctid;