summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Geoghegan2023-06-22 00:41:58 +0000
committerPeter Geoghegan2023-06-22 00:41:58 +0000
commit5f0762f14754597724c24cf6517fe4fe6412a6f9 (patch)
tree991195ef3f8c795f8ea349bb84d64a431e6e7fe6
parent05ffc1fadbe0ce7762b209061634b5857b36e1b8 (diff)
nbtree VACUUM: cope with topparent inconsistencies.
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 <[email protected]> Discussion: https://postgr.es/m/CAH2-Wz=dayg0vjs4+er84TS9ami=csdzjpuiCGbEw=idhwqhzQ@mail.gmail.com Backpatch: 11- (all supported versions).
-rw-r--r--src/backend/access/nbtree/nbtpage.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index c2050656e43..d78971bfe88 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -2147,12 +2147,6 @@ _bt_mark_page_halfdead(Relation rel, Relation heaprel, Buffer leafbuf,
&topparent, &topparentrightsib))
return false;
- /*
- * Check that the parent-page index items we're about to delete/overwrite
- * in subtree parent page contain what we expect. This can fail if the
- * index has become corrupt for some reason. We want to throw any error
- * before entering the critical section --- otherwise it'd be a PANIC.
- */
page = BufferGetPage(subtreeparent);
opaque = BTPageGetOpaque(page);
@@ -2170,8 +2164,17 @@ _bt_mark_page_halfdead(Relation rel, Relation heaprel, Buffer leafbuf,
nextoffset = OffsetNumberNext(poffset);
itemid = PageGetItemId(page, nextoffset);
itup = (IndexTuple) PageGetItem(page, itemid);
+
+ /*
+ * Check that the parent-page index items we're about to delete/overwrite
+ * in subtree parent page contain what we expect. This can fail if the
+ * index has become corrupt for some reason. When that happens we back
+ * out of deletion of the leafbuf subtree. (This is just like the case
+ * where _bt_lock_subtree_parent() cannot "re-find" leafbuf's downlink.)
+ */
if (BTreeTupleGetDownLink(itup) != topparentrightsib)
- ereport(ERROR,
+ {
+ 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\"",
topparentrightsib, topparent,
@@ -2179,6 +2182,11 @@ _bt_mark_page_halfdead(Relation rel, Relation heaprel, Buffer leafbuf,
BufferGetBlockNumber(subtreeparent),
RelationGetRelationName(rel))));
+ _bt_relbuf(rel, subtreeparent);
+ Assert(false);
+ return false;
+ }
+
/*
* Any insert which would have gone on the leaf block will now go to its
* right sibling. In other words, the key space moves right.
@@ -2834,6 +2842,7 @@ _bt_lock_subtree_parent(Relation rel, Relation heaprel, BlockNumber child,
(errcode(ERRCODE_INDEX_CORRUPTED),
errmsg_internal("failed to re-find parent key in index \"%s\" for deletion target page %u",
RelationGetRelationName(rel), child)));
+ Assert(false);
return false;
}