• Tom Lane's avatar
    Fix bogus concurrent use of _hash_getnewbuf() in bucket split code. · ed9cc2b5
    Tom Lane authored
    _hash_splitbucket() obtained the base page of the new bucket by calling
    _hash_getnewbuf(), but it held no exclusive lock that would prevent some
    other process from calling _hash_getnewbuf() at the same time.  This is
    contrary to _hash_getnewbuf()'s API spec and could in fact cause failures.
    In practice, we must only call that function while holding write lock on
    the hash index's metapage.
    
    An additional problem was that we'd already modified the metapage's bucket
    mapping data, meaning that failure to extend the index would leave us with
    a corrupt index.
    
    Fix both issues by moving the _hash_getnewbuf() call to just before we
    modify the metapage in _hash_expandtable().
    
    Unfortunately there's still a large problem here, which is that we could
    also incur ENOSPC while trying to get an overflow page for the new bucket.
    That would leave the index corrupt in a more subtle way, namely that some
    index tuples that should be in the new bucket might still be in the old
    one.  Fixing that seems substantially more difficult; even preallocating as
    many pages as we could possibly need wouldn't entirely guarantee that the
    bucket split would complete successfully.  So for today let's just deal
    with the base case.
    
    Per report from Antonin Houska.  Back-patch to all active branches.
    ed9cc2b5
hashpage.c 28.1 KB