• Heikki Linnakangas's avatar
    Detect internal GiST page splits correctly during index build. · 22251686
    Heikki Linnakangas authored
    As we descend the GiST tree during insertion, we modify any downlinks on
    the way down to include the new tuple we're about to insert (if they don't
    cover it already). Modifying an existing downlink might cause an internal
    page to split, if the new downlink tuple is larger than the old one. If
    that happens, we need to back up to the parent and re-choose a page to
    insert to. We used to detect that situation, thanks to the NSN-LSN
    interlock normally used to detect concurrent page splits, but that got
    broken by commit 9155580f. With that commit, we now use a dummy constant
    LSN value for every page during index build, so the LSN-NSN interlock no
    longer works. I thought that was OK because there can't be any other
    backends modifying the index during index build, but missed that the
    insertion itself can modify the page we're inserting to. The consequence
    was that we would sometimes insert the new tuple to an incorrect page, one
    whose downlink doesn't cover the new tuple.
    
    To fix, add a flag to the stack that keeps track of the state while
    descending tree, to indicate that a page was split, and that we need to
    retry the descend from the parent.
    
    Thomas Munro first reported that the contrib/intarray regression test was
    failing occasionally on the buildfarm after commit 9155580f. The failure
    was intermittent, because the gistchoose() function is not deterministic,
    and would only occasionally create the right circumstances for this bug to
    cause the failure.
    
    Patch by Anastasia Lubennikova, with some changes by me to make it work
    correctly also when the internal page split also causes the "grandparent"
    to be split.
    
    Discussion: https://www.postgresql.org/message-id/CA%2BhUKGJRzLo7tZExWfSbwM3XuK7aAK7FhdBV0FLkbUG%2BW0v0zg%40mail.gmail.com
    22251686
gist.c 51.1 KB