diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index b95c1b886d4..c0ebb95ba8a 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -1303,6 +1303,10 @@ _bt_pagedel(Relation rel, Buffer buf) return ndeleted; } +/* + * First stage of page deletion. Remove the downlink to the top of the + * branch being deleted, and mark the leaf page as half-dead. + */ static bool _bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack) { @@ -1317,6 +1321,7 @@ _bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack) OffsetNumber topoff; OffsetNumber nextoffset; IndexTuple itup; + IndexTupleData trunctuple; page = BufferGetPage(leafbuf); opaque = (BTPageOpaque) PageGetSpecialPointer(page); @@ -1406,12 +1411,17 @@ _bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack) opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque->btpo_flags |= BTP_HALF_DEAD; - itemid = PageGetItemId(page, P_HIKEY); - itup = (IndexTuple) PageGetItem(page, itemid); - if (target == leafblkno) - ItemPointerSetInvalid(&(itup->t_tid)); + PageIndexTupleDelete(page, P_HIKEY); + Assert(PageGetMaxOffsetNumber(page) == 0); + MemSet(&trunctuple, 0, sizeof(IndexTupleData)); + trunctuple.t_info = sizeof(IndexTupleData); + if (target != leafblkno) + ItemPointerSet(&trunctuple.t_tid, target, P_HIKEY); else - ItemPointerSet(&(itup->t_tid), target, P_HIKEY); + ItemPointerSetInvalid(&trunctuple.t_tid); + if (PageAddItem(page, (Item) &trunctuple, sizeof(IndexTupleData), P_HIKEY, + false, false) == InvalidOffsetNumber) + elog(ERROR, "could not add dummy high key to half-dead page"); /* Must mark buffers dirty before XLogInsert */ MarkBufferDirty(topparent); @@ -1427,7 +1437,10 @@ _bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack) xlrec.target.node = rel->rd_node; ItemPointerSet(&(xlrec.target.tid), BufferGetBlockNumber(topparent), topoff); xlrec.leafblk = leafblkno; - xlrec.downlink = target; + if (target != leafblkno) + xlrec.topparent = target; + else + xlrec.topparent = InvalidBlockNumber; page = BufferGetPage(leafbuf); opaque = (BTPageOpaque) PageGetSpecialPointer(page); @@ -1768,7 +1781,7 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty) xlrec.leafblk = leafblkno; xlrec.leafleftsib = leafleftsib; xlrec.leafrightsib = leafrightsib; - xlrec.downlink = nextchild; + xlrec.topparent = nextchild; rdata[0].data = (char *) &xlrec; rdata[0].len = SizeOfBtreeUnlinkPage; diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c index ada2d6691f3..dc73f2a9cd5 100644 --- a/src/backend/access/nbtree/nbtxlog.c +++ b/src/backend/access/nbtree/nbtxlog.c @@ -870,8 +870,8 @@ btree_xlog_mark_page_halfdead(uint8 info, XLogRecPtr lsn, XLogRecord *record) */ MemSet(&trunctuple, 0, sizeof(IndexTupleData)); trunctuple.t_info = sizeof(IndexTupleData); - if (xlrec->downlink != InvalidBlockNumber) - ItemPointerSet(&trunctuple.t_tid, xlrec->downlink, P_HIKEY); + if (xlrec->topparent != InvalidBlockNumber) + ItemPointerSet(&trunctuple.t_tid, xlrec->topparent, P_HIKEY); else ItemPointerSetInvalid(&trunctuple.t_tid); if (PageAddItem(page, (Item) &trunctuple, sizeof(IndexTupleData), P_HIKEY, @@ -1006,8 +1006,8 @@ btree_xlog_unlink_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) /* Add a dummy hikey item */ MemSet(&trunctuple, 0, sizeof(IndexTupleData)); trunctuple.t_info = sizeof(IndexTupleData); - if (xlrec->downlink != InvalidBlockNumber) - ItemPointerSet(&trunctuple.t_tid, xlrec->downlink, P_HIKEY); + if (xlrec->topparent != InvalidBlockNumber) + ItemPointerSet(&trunctuple.t_tid, xlrec->topparent, P_HIKEY); else ItemPointerSetInvalid(&trunctuple.t_tid); if (PageAddItem(page, (Item) &trunctuple, sizeof(IndexTupleData), P_HIKEY, diff --git a/src/backend/access/rmgrdesc/nbtdesc.c b/src/backend/access/rmgrdesc/nbtdesc.c index 89a91a20be1..af7663b8cac 100644 --- a/src/backend/access/rmgrdesc/nbtdesc.c +++ b/src/backend/access/rmgrdesc/nbtdesc.c @@ -130,8 +130,8 @@ btree_desc(StringInfo buf, uint8 xl_info, char *rec) appendStringInfoString(buf, "mark_page_halfdead: "); out_target(buf, &(xlrec->target)); - appendStringInfo(buf, "; downlink %u; leaf %u; left %u; right %u", - xlrec->downlink, xlrec->leafblk, xlrec->leftblk, xlrec->rightblk); + appendStringInfo(buf, "; topparent %u; leaf %u; left %u; right %u", + xlrec->topparent, xlrec->leafblk, xlrec->leftblk, xlrec->rightblk); break; } case XLOG_BTREE_UNLINK_PAGE_META: @@ -143,8 +143,8 @@ btree_desc(StringInfo buf, uint8 xl_info, char *rec) xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode); appendStringInfo(buf, "dead %u; left %u; right %u; btpo_xact %u; ", xlrec->deadblk, xlrec->leftsib, xlrec->rightsib, xlrec->btpo_xact); - appendStringInfo(buf, "leaf %u; leafleft %u; leafright %u; downlink %u", - xlrec->leafblk, xlrec->leafleftsib, xlrec->leafrightsib, xlrec->downlink); + appendStringInfo(buf, "leaf %u; leafleft %u; leafright %u; topparent %u", + xlrec->leafblk, xlrec->leafleftsib, xlrec->leafrightsib, xlrec->topparent); break; } case XLOG_BTREE_NEWROOT: diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 64c6982f50e..1a8b16d45e2 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -379,13 +379,15 @@ typedef struct xl_btree_vacuum typedef struct xl_btree_mark_page_halfdead { xl_btreetid target; /* deleted tuple id in parent page */ + + /* information needed to recreate the leaf page: */ BlockNumber leafblk; /* leaf block ultimately being deleted */ BlockNumber leftblk; /* leaf block's left sibling, if any */ BlockNumber rightblk; /* leaf block's right sibling */ - BlockNumber downlink; /* next child down in the branch */ + BlockNumber topparent; /* topmost internal page in the branch */ } xl_btree_mark_page_halfdead; -#define SizeOfBtreeMarkPageHalfDead (offsetof(xl_btree_mark_page_halfdead, downlink) + sizeof(BlockNumber)) +#define SizeOfBtreeMarkPageHalfDead (offsetof(xl_btree_mark_page_halfdead, topparent) + sizeof(BlockNumber)) /* * This is what we need to know about deletion of a btree page. Note we do @@ -406,7 +408,7 @@ typedef struct xl_btree_unlink_page BlockNumber leafblk; BlockNumber leafleftsib; BlockNumber leafrightsib; - BlockNumber downlink; /* next child down in the branch */ + BlockNumber topparent; /* next child down in the branch */ TransactionId btpo_xact; /* value of btpo.xact for use in recovery */ /* xl_btree_metadata FOLLOWS IF XLOG_BTREE_UNLINK_PAGE_META */