• Teodor Sigaev's avatar
    Re-think predicate locking on GIN indexes. · 0bef1c06
    Teodor Sigaev authored
    The principle behind the locking was not very well thought-out, and not
    documented. Add a section in the README to explain how it's supposed to
    work, and change the code so that it actually works that way.
    
    This fixes two bugs:
    
    1. If fast update was turned on concurrently, subsequent inserts to the
       pending list would not conflict with predicate locks that were acquired
       earlier, on entry pages. The included 'predicate-gin-fastupdate' test
       demonstrates that. To fix, make all scans acquire a predicate lock on
       the metapage. That lock represents a scan of the pending list, whether
       or not there is a pending list at the moment. Forget about the
       optimization to skip locking/checking for locks, when fastupdate=off.
    2. If a scan finds no match, it still needs to lock the entry page. The
       point of predicate locks is to lock the gabs between values, whether
       or not there is a match. The included 'predicate-gin-nomatch' test
       tests that case.
    
    In addition to those two bug fixes, this removes some unnecessary locking,
    following the principle laid out in the README. Because all items in
    a posting tree have the same key value, a lock on the posting tree root is
    enough to cover all the items. (With a very large posting tree, it would
    possibly be better to lock the posting tree leaf pages instead, so that a
    "skip scan" with a query like "A & B", you could avoid unnecessary conflict
    if a new tuple is inserted with A but !B. But let's keep this simple.)
    
    Also, some spelling  fixes.
    
    Author: Heikki Linnakangas with some editorization by me
    Review: Andrey Borodin, Alexander Korotkov
    Discussion: https://www.postgresql.org/message-id/0b3ad2c2-2692-62a9-3a04-5724f2af9114@iki.fi
    0bef1c06
ginbtree.c 21.8 KB