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

Commit43b0c91

Browse files
committed
Fix aboriginal mistake in lazy VACUUM's code for truncating away
no-longer-needed pages at the end of a table. We thought we could throw awaypages containing HEAPTUPLE_DEAD tuples; but this is not so, because suchtuples very likely have index entries pointing at them, and we wouldn't haveremoved the index entries. The problem only emerges in a somewhat unlikelyrace condition: the dead tuples have to have been inserted by a transactionthat later aborted, and this has to have happened between VACUUM's initialscan of the page and then rechecking it for empty in count_nondeletable_pages.But that timespan will include an index-cleaning pass, so it's not all thathard to hit. This seems to explain a couple of previously unsolved bugreports.
1 parent9a36a09 commit43b0c91

File tree

1 file changed

+14
-45
lines changed

1 file changed

+14
-45
lines changed

‎src/backend/commands/vacuumlazy.c

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*
3737
*
3838
* IDENTIFICATION
39-
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.95 2007/09/12 22:10:26 tgl Exp $
39+
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.96 2007/09/16 02:37:46 tgl Exp $
4040
*
4141
*-------------------------------------------------------------------------
4242
*/
@@ -784,9 +784,9 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
784784

785785
/*
786786
* Scan backwards from the end to verify that the end pages actually
787-
* containnothing we need to keep. This is *necessary*, not optional,
788-
*because otherbackends could have added tuples to these pages whilst we
789-
*werevacuuming.
787+
* containno tuples. This is *necessary*, not optional, because other
788+
* backends could have added tuples to these pages whilst we were
789+
* vacuuming.
790790
*/
791791
new_rel_pages=count_nondeletable_pages(onerel,vacrelstats);
792792

@@ -846,15 +846,14 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
846846
}
847847

848848
/*
849-
* Rescan end pages to verify that they are (still) empty ofneededtuples.
849+
* Rescan end pages to verify that they are (still) empty of tuples.
850850
*
851851
* Returns number of nondeletable pages (last nonempty page + 1).
852852
*/
853853
staticBlockNumber
854854
count_nondeletable_pages(Relationonerel,LVRelStats*vacrelstats)
855855
{
856856
BlockNumberblkno;
857-
HeapTupleDatatuple;
858857

859858
/* Strange coding of loop control is needed because blkno is unsigned */
860859
blkno=vacrelstats->rel_pages;
@@ -864,8 +863,7 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
864863
Pagepage;
865864
OffsetNumberoffnum,
866865
maxoff;
867-
booltupgone,
868-
hastup;
866+
boolhastup;
869867

870868
/*
871869
* We don't insert a vacuum delay point here, because we have an
@@ -901,42 +899,13 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
901899

902900
itemid=PageGetItemId(page,offnum);
903901

904-
if (!ItemIdIsUsed(itemid))
905-
continue;
906-
907-
tuple.t_data= (HeapTupleHeader)PageGetItem(page,itemid);
908-
tuple.t_len=ItemIdGetLength(itemid);
909-
ItemPointerSet(&(tuple.t_self),blkno,offnum);
910-
911-
tupgone= false;
912-
913-
switch (HeapTupleSatisfiesVacuum(tuple.t_data,OldestXmin,buf))
914-
{
915-
caseHEAPTUPLE_DEAD:
916-
tupgone= true;/* we can delete the tuple */
917-
break;
918-
caseHEAPTUPLE_LIVE:
919-
/* Shouldn't be necessary to re-freeze anything */
920-
break;
921-
caseHEAPTUPLE_RECENTLY_DEAD:
922-
923-
/*
924-
* If tuple is recently deleted then we must not remove it
925-
* from relation.
926-
*/
927-
break;
928-
caseHEAPTUPLE_INSERT_IN_PROGRESS:
929-
/* This is an expected case during concurrent vacuum */
930-
break;
931-
caseHEAPTUPLE_DELETE_IN_PROGRESS:
932-
/* This is an expected case during concurrent vacuum */
933-
break;
934-
default:
935-
elog(ERROR,"unexpected HeapTupleSatisfiesVacuum result");
936-
break;
937-
}
938-
939-
if (!tupgone)
902+
/*
903+
* Note: any non-unused item should be taken as a reason to keep
904+
* this page. We formerly thought that DEAD tuples could be
905+
* thrown away, but that's not so, because we'd not have cleaned
906+
* out their index entries.
907+
*/
908+
if (ItemIdIsUsed(itemid))
940909
{
941910
hastup= true;
942911
break;/* can stop scanning */
@@ -952,7 +921,7 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
952921

953922
/*
954923
* If we fall out of the loop, all the previously-thought-to-be-empty
955-
* pagesreally are; we need not bother to look at the last known-nonempty
924+
* pagesstill are; we need not bother to look at the last known-nonempty
956925
* page.
957926
*/
958927
returnvacrelstats->nonempty_pages;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp