summaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtpage.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-11-01 19:50:08 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-11-01 19:50:08 +0000
commitb4f5429fa84d08a6466f49b15d2586df9f183eb5 (patch)
tree44827c665fbe6c69694531de2dcfeb76470f3a45 /src/backend/access/nbtree/nbtpage.c
parent3aba3aa5b442213c2ab6fef079c9ce9356a96f91 (diff)
Fix "failed to re-find parent key" btree VACUUM failure by tweaking
_bt_pagedel to recover from the failure: just search the whole parent level if searching to the right fails. This does nothing for the underlying problem that index keys became out-of-order in the grandparent level. However, we believe that there is no other consequence worse than slightly inefficient searching, so this narrow patch seems like the safest solution for the back branches.
Diffstat (limited to 'src/backend/access/nbtree/nbtpage.c')
-rw-r--r--src/backend/access/nbtree/nbtpage.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 378c5f9d36f..03b8ca3b4ab 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.81.4.1 2005/05/07 21:32:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.81.4.2 2006/11/01 19:50:08 tgl Exp $
*
* NOTES
* Postgres btree pages look like ordinary relation pages. The opaque
@@ -867,16 +867,28 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
rbuf = _bt_getbuf(rel, rightsib, BT_WRITE);
/*
- * Next find and write-lock the current parent of the target page.
- * This is essentially the same as the corresponding step of
- * splitting.
+ * Next find and write-lock the current parent of the target page. This is
+ * essentially the same as the corresponding step of splitting. However,
+ * it's possible for the search to fail (for reasons explained in README).
+ * If that happens, we recover by searching the whole parent level, which
+ * is a tad inefficient but doesn't happen often enough to be a problem.
*/
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid),
target, P_HIKEY);
pbuf = _bt_getstackbuf(rel, stack, BT_WRITE);
if (pbuf == InvalidBuffer)
- elog(ERROR, "failed to re-find parent key in \"%s\"",
- RelationGetRelationName(rel));
+ {
+ /* Find the leftmost page in the parent level */
+ pbuf = _bt_get_endpoint(rel, opaque->btpo.level + 1, false);
+ stack->bts_blkno = BufferGetBlockNumber(pbuf);
+ stack->bts_offset = InvalidOffsetNumber;
+ _bt_relbuf(rel, pbuf);
+ /* and repeat search from there */
+ pbuf = _bt_getstackbuf(rel, stack, BT_WRITE);
+ if (pbuf == InvalidBuffer)
+ elog(ERROR, "failed to re-find parent key in \"%s\" for deletion target page %u",
+ RelationGetRelationName(rel), target);
+ }
parent = stack->bts_blkno;
poffset = stack->bts_offset;