1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Remove faulty nbtree page deletion assertion.

_bt_pagedel only builds a search stack when it needs one to locate the
downlink of the page that it's about to mark half-dead (and when it
doesn't already have one from an earlier sibling deletion that took
place during the same _bt_pagedel call).  _bt_pagedel won't build a
search stack for the page its caller passes whenever it happens to be
one that an earlier interrupted VACUUM left half-dead (since there is no
downlink to remove).  We nevertheless asserted that page deletion could
only build a search stack for that initial caller-passed page.

To fix, remove the assertion, which spuriously failed when a half-dead
leaf page was passed by the _bt_pagedel caller and its right sibling
page was empty/had to be considered for deletion during the same call
(necessitating building a search stack to locate the right sibling's
downlink).

Oversight in commit cd8c73a38, which refactored nbtree page deletion's
INCOMPLETE_SPLIT check.

Author: Peter Geoghegan <pg@bowt.ie>
Reported-by: Iliia Khaprov <i.khaprov@gmail.com>
Discussion: https://postgr.es/m/CAFO+O_p5So4MXwQ1VEcL9+9vGgODu11TTWcYq9RDbxnira8o2w@mail.gmail.com
Backpatch-through: 14
This commit is contained in:
Peter Geoghegan
2026-10-08 14:21:11 -04:00
parent b0e087cfe4
commit 7401a1ec1c

View File

@@ -1900,11 +1900,11 @@ _bt_pagedel(Relation rel, Buffer leafbuf, BTVacState *vstate)
* left half of an incomplete split, but ensuring that it's not the * left half of an incomplete split, but ensuring that it's not the
* right half is more complicated. For that, we have to check that * right half is more complicated. For that, we have to check that
* the left sibling doesn't have its INCOMPLETE_SPLIT flag set using * the left sibling doesn't have its INCOMPLETE_SPLIT flag set using
* _bt_leftsib_splitflag(). On the first iteration, we temporarily * _bt_leftsib_splitflag(). The first time we reach a page that isn't
* release the lock on scanblkno/leafbuf, check the left sibling, and * already half-dead (usually the scanblkno page), we temporarily
* construct a search stack to scanblkno. On subsequent iterations, * release the lock on leafbuf, check the left sibling, and construct
* we know we stepped right from a page that passed these tests, so * a search stack to leafbuf. On subsequent iterations, we know we
* it's OK. * stepped right from a page that passed these tests, so it's OK.
*/ */
if (P_RIGHTMOST(opaque) || P_ISROOT(opaque) || if (P_RIGHTMOST(opaque) || P_ISROOT(opaque) ||
P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page) || P_FIRSTDATAKEY(opaque) <= PageGetMaxOffsetNumber(page) ||
@@ -1959,7 +1959,6 @@ _bt_pagedel(Relation rel, Buffer leafbuf, BTVacState *vstate)
* Check that the left sibling of leafbuf (if any) is not * Check that the left sibling of leafbuf (if any) is not
* marked with INCOMPLETE_SPLIT flag before proceeding * marked with INCOMPLETE_SPLIT flag before proceeding
*/ */
Assert(leafblkno == scanblkno);
if (_bt_leftsib_splitflag(rel, leftsib, leafblkno)) if (_bt_leftsib_splitflag(rel, leftsib, leafblkno))
{ {
ReleaseBuffer(leafbuf); ReleaseBuffer(leafbuf);