summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Geoghegan2021-03-23 23:09:51 +0000
committerPeter Geoghegan2021-03-23 23:09:51 +0000
commit5b861baa550a369e04bf67fbe83f3a5a8c742fb4 (patch)
tree3b455ad3782b2b7aefe80f1e63f7f16f48509a9a /src
parent87d90ac61fa113ffc886efcdb391c522c1982991 (diff)
nbtree VACUUM: Cope with buggy opclasses.
Teach nbtree VACUUM to press on with vacuuming in the event of a page deletion attempt that fails to "re-find" a downlink for its child/target page. There is no good reason to treat this as an irrecoverable error. But there is a good reason not to: pressing on at this point removes any question of VACUUM not making progress solely due to misbehavior from user-defined operator class code. Discussion: https://postgr.es/m/CAH2-Wzma5G9CTtMjbrXTwOym+U=aWg-R7=-htySuztgoJLvZXg@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/nbtree/nbtpage.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 530d924bff8..ef48679cc2e 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -2791,10 +2791,26 @@ _bt_lock_subtree_parent(Relation rel, BlockNumber child, BTStack stack,
*/
pbuf = _bt_getstackbuf(rel, stack, child);
if (pbuf == InvalidBuffer)
- ereport(ERROR,
+ {
+ /*
+ * Failed to "re-find" a pivot tuple whose downlink matched our child
+ * block number on the parent level -- the index must be corrupt.
+ * Don't even try to delete the leafbuf subtree. Just report the
+ * issue and press on with vacuuming the index.
+ *
+ * Note: _bt_getstackbuf() recovers from concurrent page splits that
+ * take place on the parent level. Its approach is a near-exhaustive
+ * linear search. This also gives it a surprisingly good chance of
+ * recovering in the event of a buggy or inconsistent opclass. But we
+ * don't rely on that here.
+ */
+ ereport(LOG,
(errcode(ERRCODE_INDEX_CORRUPTED),
errmsg_internal("failed to re-find parent key in index \"%s\" for deletion target page %u",
RelationGetRelationName(rel), child)));
+ return false;
+ }
+
parent = stack->bts_blkno;
parentoffset = stack->bts_offset;