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

Commit2f2baf9

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 parenta93840e commit2f2baf9

File tree

1 file changed

+12
-56
lines changed

1 file changed

+12
-56
lines changed

‎src/backend/commands/vacuumlazy.c

Lines changed: 12 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
*
3232
*
3333
* IDENTIFICATION
34-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.20.2.1 2005/05/07 21:33:47 tgl Exp $
34+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.20.2.2 2007/09/16 02:38:31 tgl Exp $
3535
*
3636
*-------------------------------------------------------------------------
3737
*/
@@ -780,15 +780,14 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
780780
}
781781

782782
/*
783-
* Rescan end pages to verify that they are (still) empty ofneededtuples.
783+
* Rescan end pages to verify that they are (still) empty of tuples.
784784
*
785785
* Returns number of nondeletable pages (last nonempty page + 1).
786786
*/
787787
staticBlockNumber
788788
count_nondeletable_pages(Relationonerel,LVRelStats*vacrelstats)
789789
{
790790
BlockNumberblkno;
791-
HeapTupleDatatuple;
792791

793792
/* Strange coding of loop control is needed because blkno is unsigned */
794793
blkno=vacrelstats->rel_pages;
@@ -798,9 +797,7 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
798797
Pagepage;
799798
OffsetNumberoffnum,
800799
maxoff;
801-
boolpgchanged,
802-
tupgone,
803-
hastup;
800+
boolhastup;
804801

805802
CHECK_FOR_INTERRUPTS();
806803

@@ -815,78 +812,37 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
815812

816813
if (PageIsNew(page)||PageIsEmpty(page))
817814
{
818-
/* PageIsNewrobably shouldn't happen... */
815+
/* PageIsNewprobably shouldn't happen... */
819816
LockBuffer(buf,BUFFER_LOCK_UNLOCK);
820817
ReleaseBuffer(buf);
821818
continue;
822819
}
823820

824-
pgchanged= false;
825821
hastup= false;
826822
maxoff=PageGetMaxOffsetNumber(page);
827823
for (offnum=FirstOffsetNumber;
828824
offnum <=maxoff;
829825
offnum=OffsetNumberNext(offnum))
830826
{
831827
ItemIditemid;
832-
uint16sv_infomask;
833828

834829
itemid=PageGetItemId(page,offnum);
835830

836-
if (!ItemIdIsUsed(itemid))
837-
continue;
838-
839-
tuple.t_datamcxt=NULL;
840-
tuple.t_data= (HeapTupleHeader)PageGetItem(page,itemid);
841-
tuple.t_len=ItemIdGetLength(itemid);
842-
ItemPointerSet(&(tuple.t_self),blkno,offnum);
843-
844-
tupgone= false;
845-
sv_infomask=tuple.t_data->t_infomask;
846-
847-
switch (HeapTupleSatisfiesVacuum(tuple.t_data,OldestXmin))
848-
{
849-
caseHEAPTUPLE_DEAD:
850-
tupgone= true;/* we can delete the tuple */
851-
break;
852-
caseHEAPTUPLE_LIVE:
853-
/* Shouldn't be necessary to re-freeze anything */
854-
break;
855-
caseHEAPTUPLE_RECENTLY_DEAD:
856-
857-
/*
858-
* If tuple is recently deleted then we must not
859-
* remove it from relation.
860-
*/
861-
break;
862-
caseHEAPTUPLE_INSERT_IN_PROGRESS:
863-
/* This is an expected case during concurrent vacuum */
864-
break;
865-
caseHEAPTUPLE_DELETE_IN_PROGRESS:
866-
/* This is an expected case during concurrent vacuum */
867-
break;
868-
default:
869-
elog(ERROR,"Unexpected HeapTupleSatisfiesVacuum result");
870-
break;
871-
}
872-
873-
/* check for hint-bit update by HeapTupleSatisfiesVacuum */
874-
if (sv_infomask!=tuple.t_data->t_infomask)
875-
pgchanged= true;
876-
877-
if (!tupgone)
831+
/*
832+
* Note: any non-unused item should be taken as a reason to keep
833+
* this page. We formerly thought that DEAD tuples could be
834+
* thrown away, but that's not so, because we'd not have cleaned
835+
* out their index entries.
836+
*/
837+
if (ItemIdIsUsed(itemid))
878838
{
879839
hastup= true;
880840
break;/* can stop scanning */
881841
}
882842
}/* scan along page */
883843

884844
LockBuffer(buf,BUFFER_LOCK_UNLOCK);
885-
886-
if (pgchanged)
887-
WriteBuffer(buf);
888-
else
889-
ReleaseBuffer(buf);
845+
ReleaseBuffer(buf);
890846

891847
/* Done scanning if we found a tuple here */
892848
if (hastup)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp