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:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user