Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3f58cc6

Browse files
Remove extra nbtree half-dead internal page check.
It's not safe for nbtree VACUUM to attempt to delete a target page whoseright sibling is already half-dead, since that would fail thecross-check when VACUUM attempts to re-find a downlink to the rightsibling in the parent page. Logic to prevent this from happening wasadded by commit8da3183, which addressed a bug in the overhaul ofpage deletion that went into PostgreSQL 9.4 (commitefada2b).VACUUM was made to check the right sibling page, and back off when ithappened to be half-dead already.However, it is only truly necessary to do the right sibling check on theleaf level, since that transitively determines if the deletion target'sparent's right sibling page is itself undergoing deletion. Remove theinternal page level check, and add a comment explaining why the leaflevel check alone suffices.The extra check is also unnecessary due to the fact that internal pagesthat are marked half-dead are generally considered corrupt. Commitefada2b established the principle that there should never behalf-dead internal pages (internal pages pending deletion are possible,but that status is never directly represented in the internal page).VACUUM will complain about corruption when it encounters half-deadinternal pages, so VACUUM is bound to raise an error one way or anotherwhen an nbtree index has a half-dead internal page (contrib/amcheck willalso report that the page is corrupt).It's possible that a pg_upgrade'd 9.3 database will still have half-deadinternal pages, so it may seem like there is an argument for leaving thecheck in place to reliably get a cleaner error message that advises theuser to REINDEX. However, leaf pages are also deleted in the firstphase of deletion prior to PostgreSQL 9.4, so I believe we won't evenattempt to re-find the parent page anyway (we won't have the fullydeleted leaf page as the right sibling of our target page, so we won'teven try to find a downlink for it).Discussion:https://postgr.es/m/CAH2-Wzm_ntmqJjWLRyKzimFmFvk+BnVAvUpaA4s1h9Ja58woaQ@mail.gmail.com
1 parent3922f10 commit3f58cc6

File tree

2 files changed

+20
-17
lines changed

2 files changed

+20
-17
lines changed

‎src/backend/access/nbtree/README

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,15 @@ long as we're keeping the leaf locked. The internal pages in the chain
262262
cannot acquire new children afterwards either, because the leaf page is
263263
marked as half-dead and won't be split.
264264

265-
Removing the downlink to the top of the to-be-deleted chain effectively
266-
transfers the key space to the right sibling for all the intermediate levels
267-
too, in one atomic operation. A concurrent search might still visit the
268-
intermediate pages, but it will move right when it reaches the half-dead page
269-
at the leaf level.
265+
Removing the downlink to the top of the to-be-deleted subtree/chain
266+
effectively transfers the key space to the right sibling for all the
267+
intermediate levels too, in one atomic operation. A concurrent search might
268+
still visit the intermediate pages, but it will move right when it reaches
269+
the half-dead page at the leaf level. In particular, the search will move to
270+
the subtree to the right of the half-dead leaf page/to-be-deleted subtree,
271+
since the half-dead leaf page's right sibling must be a "cousin" page, not a
272+
"true" sibling page (or a second cousin page when the to-be-deleted chain
273+
starts at leaf page's grandparent page, and so on).
270274

271275
In the second stage, the topmost page in the chain is unlinked from its
272276
siblings, and the half-dead leaf page is updated to point to the next page

‎src/backend/access/nbtree/nbtpage.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,17 +1301,6 @@ _bt_lock_branch_parent(Relation rel, BlockNumber child, BTStack stack,
13011301
_bt_relbuf(rel,lbuf);
13021302
}
13031303

1304-
/*
1305-
* Perform the same check on this internal level that
1306-
* _bt_mark_page_halfdead performed on the leaf level.
1307-
*/
1308-
if (_bt_is_page_halfdead(rel,*rightsib))
1309-
{
1310-
elog(DEBUG1,"could not delete page %u because its right sibling %u is half-dead",
1311-
parent,*rightsib);
1312-
return false;
1313-
}
1314-
13151304
return_bt_lock_branch_parent(rel,parent,stack->bts_parent,
13161305
topparent,topoff,target,rightsib);
13171306
}
@@ -1621,7 +1610,17 @@ _bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack)
16211610
* parent, unless it is the only child --- in which case the parent has to
16221611
* be deleted too, and the same condition applies recursively to it. We
16231612
* have to check this condition all the way up before trying to delete,
1624-
* and lock the final parent of the to-be-deleted branch.
1613+
* and lock the final parent of the to-be-deleted subtree.
1614+
*
1615+
* However, we won't need to repeat the above _bt_is_page_halfdead() check
1616+
* for parent/ancestor pages because of the rightmost restriction. The
1617+
* leaf check will apply to a right "cousin" leaf page rather than a
1618+
* simple right sibling leaf page in cases where we actually go on to
1619+
* perform internal page deletion. The right cousin leaf page is
1620+
* representative of the left edge of the subtree to the right of the
1621+
* to-be-deleted subtree as a whole. (Besides, internal pages are never
1622+
* marked half-dead, so it isn't even possible to directly assess if an
1623+
* internal page is part of some other to-be-deleted subtree.)
16251624
*/
16261625
rightsib=leafrightsib;
16271626
target=leafblkno;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp