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

Commit8f876d1

Browse files
nbtree VACUUM: cope with right sibling link corruption.
Avoid "right sibling's left-link doesn't match" errors when vacuuming acorrupt nbtree index. Just LOG the issue and press on. That way VACUUMwill have a decent chance of finishing off all required processing forthe index (and for the table as a whole).This error was seen in the field from time to time (it's more than atheoretical risk), so giving VACUUM the ability to press on like thishas real value. Nothing short of a REINDEX is expected to fix theunderlying index corruption, so giving up (by throwing an error) risksmaking a bad situation far worse. Anything that blocks forward progressby VACUUM like this might go unnoticed for a long time. This couldeventually lead to a wraparound/xidStopLimit outage.Note that _bt_unlink_halfdead_page() has always been able to bail onpage deletion when the target page's left sibling page was in aninconsistent state. It now does the same thing (returns false to backout of the second phase of deletion) when it notices sibling linkcorruption in the target page's right sibling page.This is similar to the work from commit5b861ba (later backpatched ascommit43e409c), which taught nbtree to press on with vacuuming anindex when page deletion fails to "re-find" a downlink in the targetpage's parent page. The "re-find" check seems to make VACUUM bail onpage deletion more often in practice, but there is no reason to take anychances here.Author: Peter Geoghegan <pg@bowt.ie>Reviewed-By: Heikki Linnakangas <hlinnaka@iki.fi>Discussion:https://postgr.es/m/CAH2-Wzko2q2kP1+UvgJyP9g0mF4hopK0NtQZcxwvMv9_ytGhkQ@mail.gmail.comBackpatch: 11- (all supported versions).
1 parent956c625 commit8f876d1

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

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

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,13 +2032,6 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno,
20322032
leftsib=opaque->btpo_next;
20332033
_bt_relbuf(rel,lbuf);
20342034

2035-
/*
2036-
* It'd be good to check for interrupts here, but it's not easy to
2037-
* do so because a lock is always held. This block isn't
2038-
* frequently reached, so hopefully the consequences of not
2039-
* checking interrupts aren't too bad.
2040-
*/
2041-
20422035
if (leftsib==P_NONE)
20432036
{
20442037
elog(LOG,"no left sibling (concurrent deletion?) of block %u in \"%s\"",
@@ -2057,6 +2050,9 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno,
20572050
}
20582051
return false;
20592052
}
2053+
2054+
CHECK_FOR_INTERRUPTS();
2055+
20602056
lbuf=_bt_getbuf(rel,leftsib,BT_WRITE);
20612057
page=BufferGetPage(lbuf);
20622058
opaque= (BTPageOpaque)PageGetSpecialPointer(page);
@@ -2118,13 +2114,40 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno,
21182114
rbuf=_bt_getbuf(rel,rightsib,BT_WRITE);
21192115
page=BufferGetPage(rbuf);
21202116
opaque= (BTPageOpaque)PageGetSpecialPointer(page);
2117+
2118+
/*
2119+
* Validate target's right sibling page. Its left link must point back to
2120+
* the target page.
2121+
*/
21212122
if (opaque->btpo_prev!=target)
2122-
ereport(ERROR,
2123+
{
2124+
/*
2125+
* This is known to fail in the field; sibling link corruption is
2126+
* relatively common. Press on with vacuuming rather than just
2127+
* throwing an ERROR (same approach used for left-sibling's-right-link
2128+
* validation check a moment ago).
2129+
*/
2130+
ereport(LOG,
21232131
(errcode(ERRCODE_INDEX_CORRUPTED),
21242132
errmsg_internal("right sibling's left-link doesn't match: "
2125-
"block %u links to %u instead of expected %u in index \"%s\"",
2126-
rightsib,opaque->btpo_prev,target,
2127-
RelationGetRelationName(rel))));
2133+
"right sibling %u of target %u with leafblkno %u "
2134+
"and scanblkno %u spuriously links to non-target %u "
2135+
"on level %u of index \"%s\"",
2136+
rightsib,target,leafblkno,
2137+
scanblkno,opaque->btpo_prev,
2138+
targetlevel,RelationGetRelationName(rel))));
2139+
2140+
/* Must release all pins and locks on failure exit */
2141+
if (BufferIsValid(lbuf))
2142+
_bt_relbuf(rel,lbuf);
2143+
_bt_relbuf(rel,rbuf);
2144+
_bt_relbuf(rel,buf);
2145+
if (target!=leafblkno)
2146+
_bt_relbuf(rel,leafbuf);
2147+
2148+
return false;
2149+
}
2150+
21282151
rightsib_is_rightmost=P_RIGHTMOST(opaque);
21292152
*rightsib_empty= (P_FIRSTDATAKEY(opaque)>PageGetMaxOffsetNumber(page));
21302153

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,8 +1141,7 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno)
11411141
* can't be half-dead because only an interrupted VACUUM process can
11421142
* leave pages in that state, so we'd definitely have dealt with it
11431143
* back when the page was the scanblkno page (half-dead pages are
1144-
* always marked fully deleted by _bt_pagedel()). This assumes that
1145-
* there can be only one vacuum process running at a time.
1144+
* always marked fully deleted by _bt_pagedel(), barring corruption).
11461145
*/
11471146
if (!opaque|| !P_ISLEAF(opaque)||P_ISHALFDEAD(opaque))
11481147
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp