From 32080536e312020054ed33f3246d58ab99e9efc0 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Wed, 6 May 2020 15:55:33 +0300 Subject: [PATCH 2/2] Remove btree page items after page unlink Currently, page unlink leaves remaining items "as is", but replay of corresponding WAL-record re-initializes page leaving it with no items. For the sake of consistency, this commit makes primary delete all the items during page unlink as well. Discussion: https://postgr.es/m/CAPpHfdt_OTyQpXaPJcWzV2N-LNeNJseNB-K_A66qG%3DL518VTFw%40mail.gmail.com --- contrib/amcheck/verify_nbtree.c | 7 ++----- src/backend/access/nbtree/nbtpage.c | 10 ++++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index e4d501a85d1..c9f9e755dcc 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -2864,11 +2864,8 @@ palloc_btree_page(BtreeCheckState *state, BlockNumber blocknum) * As noted at the beginning of _bt_binsrch(), an internal page must have * children, since there must always be a negative infinity downlink * (there may also be a highkey). In the case of non-rightmost leaf - * pages, there must be at least a highkey. Deleted pages on replica - * might contain no items, because page unlink re-initializes - * page-to-be-deleted. Deleted pages with no items might be on primary - * too due to preceding recovery, but on primary new deletions can't - * happen concurrently to amcheck. + * pages, there must be at least a highkey. The exceptions are deleted + * pages, which contain no items. * * This is correct when pages are half-dead, since internal pages are * never half-dead, and leaf pages must have a high key when half-dead diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index e146cc326c9..4963d8b0fc4 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -2019,6 +2019,7 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno, BTMetaPageData *metad = NULL; ItemId itemid; Page page; + PageHeader header; BTPageOpaque opaque; bool rightsib_is_rightmost; int targetlevel; @@ -2293,6 +2294,15 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno, opaque->btpo_flags |= BTP_DELETED; opaque->btpo.xact = ReadNewTransactionId(); + /* + * Replaying page unlink on replica will re-initialize the target page + * leaving it with no items. For consistency, we remove all the items on + * primary too. + */ + header = (PageHeader) page; + header->pd_lower = SizeOfPageHeaderData; + header->pd_upper = header->pd_special; + /* And update the metapage, if needed */ if (BufferIsValid(metabuf)) { -- 2.14.3