aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Geoghegan <pg@bowt.ie>2022-09-05 11:20:03 -0700
committerPeter Geoghegan <pg@bowt.ie>2022-09-05 11:20:03 -0700
commit7adc34832f24a247197899324e99ad042123ab09 (patch)
treebadc4d4d3b4a1d2e6088136f2c6f675d08066968 /src
parent844ac0967e390583f589832d084f102e0791d0d6 (diff)
downloadpostgresql-7adc34832f24a247197899324e99ad042123ab09.tar.gz
postgresql-7adc34832f24a247197899324e99ad042123ab09.zip
Backpatch nbtree page deletion hardening.
Postgres 14 commit 5b861baa taught nbtree VACUUM to tolerate buggy opclasses. VACUUM's inability to locate a to-be-deleted page's downlink in the parent page was logged instead of throwing an error. VACUUM could just press on with vacuuming the index, and vacuuming the table as a whole. There are now anecdotal reports of this error causing problems that were much more disruptive than the underlying index corruption ever could be. Anything that makes VACUUM unable to make forward progress against one table/index ultimately risks making the system enter xidStopLimit mode. There is no good reason to take any chances here, so backpatch the hardening commit. Author: Peter Geoghegan <pg@bowt.ie> Discussion: https://postgr.es/m/CAH2-Wzm9HR6Pow=t-iQa57zT8qmX6_M4h14F-pTtb=xFDW5FBA@mail.gmail.com Backpatch: 10-13 (all supported versions that lacked the hardening)
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/nbtree/nbtpage.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 1e1d8a7e2f8..a4f2ae09d95 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1198,8 +1198,25 @@ _bt_lock_branch_parent(Relation rel, BlockNumber child, BTStack stack,
stack->bts_btentry = child;
pbuf = _bt_getstackbuf(rel, stack);
if (pbuf == InvalidBuffer)
- elog(ERROR, "failed to re-find parent key in index \"%s\" for deletion target page %u",
- RelationGetRelationName(rel), child);
+ {
+ /*
+ * 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;
poffset = stack->bts_offset;