• Alvaro Herrera's avatar
    Avoid serializability errors when locking a tuple with a committed update · 533e9c6b
    Alvaro Herrera authored
    When key-share locking a tuple that has been not-key-updated, and the
    update is a committed transaction, in some cases we raised
    serializability errors:
        ERROR:  could not serialize access due to concurrent update
    
    Because the key-share doesn't conflict with the update, the error is
    unnecessary and inconsistent with the case that the update hasn't
    committed yet.  This causes problems for some usage patterns, even if it
    can be claimed that it's sufficient to retry the aborted transaction:
    given a steady stream of updating transactions and a long locking
    transaction, the long transaction can be starved indefinitely despite
    multiple retries.
    
    To fix, we recognize that HeapTupleSatisfiesUpdate can return
    HeapTupleUpdated when an updating transaction has committed, and that we
    need to deal with that case exactly as if it were a non-committed
    update: verify whether the two operations conflict, and if not, carry on
    normally.  If they do conflict, however, there is a difference: in the
    HeapTupleBeingUpdated case we can just sleep until the concurrent
    transaction is gone, while in the HeapTupleUpdated case this is not
    possible and we must raise an error instead.
    
    Per trouble report from Olivier Dony.
    
    In addition to a couple of test cases that verify the changed behavior,
    I added a test case to verify the behavior that remains unchanged,
    namely that errors are raised when a update that modifies the key is
    used.  That must still generate serializability errors.  One
    pre-existing test case changes behavior; per discussion, the new
    behavior is actually the desired one.
    
    Discussion: https://www.postgresql.org/message-id/560AA479.4080807@odoo.com
      https://www.postgresql.org/message-id/20151014164844.3019.25750@wrigleys.postgresql.org
    
    Backpatch to 9.3, where the problem appeared.
    533e9c6b
lock-committed-keyupdate.spec 3.07 KB