Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
nbtree VACUUM: cope with topparent inconsistencies.
authorPeter Geoghegan <pg@bowt.ie>
Thu, 22 Jun 2023 00:41:50 +0000 (17:41 -0700)
committerPeter Geoghegan <pg@bowt.ie>
Thu, 22 Jun 2023 00:41:50 +0000 (17:41 -0700)
Avoid "right sibling %u of block %u is not next child" errors when
vacuuming a corrupt nbtree index.  Just LOG the issue and press on.
That way VACUUM will have a decent chance of finishing off all required
processing for the index (and for the table as a whole).

This is similar to recent work from commit 5abff197, as well as work
from commit 5b861baa (later backpatched as commit 43e409ce), which
taught nbtree VACUUM to keep going when its "re-find" check fails.  The
hardening added by this commit takes place directly after the "re-find"
check, right before the critical section for the first stage of page
deletion.

Author: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/CAH2-Wz=dayg0vjs4+er84TS9ami=csdzjpuiCGbEw=idhwqhzQ@mail.gmail.com
Backpatch: 11- (all supported versions).

src/backend/access/nbtree/nbtpage.c

index 5ebfd845cf8db513a1a582964c9954e23c76a59f..0d731b180167793c6a59704cf8f6f85b09115e90 100644 (file)
@@ -1686,9 +1686,19 @@ _bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack)
    itemid = PageGetItemId(page, nextoffset);
    itup = (IndexTuple) PageGetItem(page, itemid);
    if (BTreeInnerTupleGetDownLink(itup) != rightsib)
-       elog(ERROR, "right sibling %u of block %u is not next child %u of block %u in index \"%s\"",
-            rightsib, target, BTreeInnerTupleGetDownLink(itup),
-            BufferGetBlockNumber(topparent), RelationGetRelationName(rel));
+   {
+       ereport(LOG,
+               (errcode(ERRCODE_INDEX_CORRUPTED),
+                errmsg_internal("right sibling %u of block %u is not next child %u of block %u in index \"%s\"",
+                                rightsib, target,
+                                BTreeInnerTupleGetDownLink(itup),
+                                BufferGetBlockNumber(topparent),
+                                RelationGetRelationName(rel))));
+
+       _bt_relbuf(rel, topparent);
+
+       return false;
+   }
 
    /*
     * Any insert which would have gone on the leaf block will now go to its