0002-Remove-btree-page-items-after-page-unlink.patch
application/octet-stream
Filename: 0002-Remove-btree-page-items-after-page-unlink.patch
Type: application/octet-stream
Part: 1
Message:
Re: Concurrency bug in amcheck
Patch
Format: format-patch
Series: patch 0002
Subject: Remove btree page items after page unlink
| File | + | − |
|---|---|---|
| contrib/amcheck/verify_nbtree.c | 2 | 5 |
| src/backend/access/nbtree/nbtpage.c | 10 | 0 |
From 32080536e312020054ed33f3246d58ab99e9efc0 Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
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