postgres.git / summary / log / commit / refs

commit    28cd57416eb7cb6642eb23bd8acbf2f41ce76844
Author:   Alvaro Herrera <alvherre@alvh.no-ip.org>
Date:     Tue Jan 04 16:01:05 2022 +0000
First released in: 15.0, 10.20, 11.15, 12.10, 13.6, 14.2

    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


src/backend/access/heap/heapam.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 7bcef344b1a..de4204f7550 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -5233,7 +5233,15 @@ failed: { Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated || result == HeapTupleWouldBlock); - Assert(!(tuple->t_data->t_infomask & HEAP_XMAX_INVALID)); + + /* + * When locking a tuple under LockWaitSkip semantics and we fail with + * HeapTupleWouldBlock 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(HeapTupleWouldBlock || !(tuple->t_data->t_infomask & HEAP_XMAX_INVALID)); hufd->ctid = tuple->t_data->t_ctid; hufd->xmax = HeapTupleHeaderGetUpdateXid(tuple->t_data); if (result == HeapTupleSelfUpdated) [parent: ec367452179c]