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

Commitfdf9e21

Browse files
committed
Update visibility map in the second phase of vacuum.
There's a high chance that a page becomes all-visible when the second phaseof vacuum removes all the dead tuples on it, so it makes sense to check forthat. Otherwise the visibility map won't get updated until the next vacuum.Pavan Deolasee, reviewed by Jeff Janes.
1 parent0e81ddd commitfdf9e21

File tree

1 file changed

+129
-4
lines changed

1 file changed

+129
-4
lines changed

‎src/backend/commands/vacuumlazy.c

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static void lazy_cleanup_index(Relation indrel,
142142
IndexBulkDeleteResult*stats,
143143
LVRelStats*vacrelstats);
144144
staticintlazy_vacuum_page(Relationonerel,BlockNumberblkno,Bufferbuffer,
145-
inttupindex,LVRelStats*vacrelstats);
145+
inttupindex,LVRelStats*vacrelstats,Buffer*vmbuffer);
146146
staticvoidlazy_truncate_heap(Relationonerel,LVRelStats*vacrelstats);
147147
staticBlockNumbercount_nondeletable_pages(Relationonerel,
148148
LVRelStats*vacrelstats);
@@ -151,6 +151,8 @@ static void lazy_record_dead_tuple(LVRelStats *vacrelstats,
151151
ItemPointeritemptr);
152152
staticboollazy_tid_reaped(ItemPointeritemptr,void*state);
153153
staticintvac_cmp_itemptr(constvoid*left,constvoid*right);
154+
staticboolheap_page_is_all_visible(Bufferbuf,
155+
TransactionId*visibility_cutoff_xid);
154156

155157

156158
/*
@@ -697,6 +699,11 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
697699
hastup= false;
698700
prev_dead_count=vacrelstats->num_dead_tuples;
699701
maxoff=PageGetMaxOffsetNumber(page);
702+
703+
/*
704+
* Note: If you change anything in the loop below, also look at
705+
* heap_page_is_all_visible to see if that needs to be changed.
706+
*/
700707
for (offnum=FirstOffsetNumber;
701708
offnum <=maxoff;
702709
offnum=OffsetNumberNext(offnum))
@@ -881,7 +888,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
881888
vacrelstats->num_dead_tuples>0)
882889
{
883890
/* Remove tuples from heap */
884-
lazy_vacuum_page(onerel,blkno,buf,0,vacrelstats);
891+
lazy_vacuum_page(onerel,blkno,buf,0,vacrelstats,&vmbuffer);
885892

886893
/*
887894
* Forget the now-vacuumed tuples, and press on, but be careful
@@ -1051,6 +1058,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
10511058
inttupindex;
10521059
intnpages;
10531060
PGRUsageru0;
1061+
Buffervmbuffer=InvalidBuffer;
10541062

10551063
pg_rusage_init(&ru0);
10561064
npages=0;
@@ -1074,7 +1082,8 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
10741082
++tupindex;
10751083
continue;
10761084
}
1077-
tupindex=lazy_vacuum_page(onerel,tblk,buf,tupindex,vacrelstats);
1085+
tupindex=lazy_vacuum_page(onerel,tblk,buf,tupindex,vacrelstats,
1086+
&vmbuffer);
10781087

10791088
/* Now that we've compacted the page, record its available space */
10801089
page=BufferGetPage(buf);
@@ -1085,6 +1094,12 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
10851094
npages++;
10861095
}
10871096

1097+
if (BufferIsValid(vmbuffer))
1098+
{
1099+
ReleaseBuffer(vmbuffer);
1100+
vmbuffer=InvalidBuffer;
1101+
}
1102+
10881103
ereport(elevel,
10891104
(errmsg("\"%s\": removed %d row versions in %d pages",
10901105
RelationGetRelationName(onerel),
@@ -1105,11 +1120,12 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
11051120
*/
11061121
staticint
11071122
lazy_vacuum_page(Relationonerel,BlockNumberblkno,Bufferbuffer,
1108-
inttupindex,LVRelStats*vacrelstats)
1123+
inttupindex,LVRelStats*vacrelstats,Buffer*vmbuffer)
11091124
{
11101125
Pagepage=BufferGetPage(buffer);
11111126
OffsetNumberunused[MaxOffsetNumber];
11121127
intuncnt=0;
1128+
TransactionIdvisibility_cutoff_xid;
11131129

11141130
START_CRIT_SECTION();
11151131

@@ -1130,6 +1146,19 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
11301146

11311147
PageRepairFragmentation(page);
11321148

1149+
/*
1150+
* Now that we have removed the dead tuples from the page, once again check
1151+
* if the page has become all-visible.
1152+
*/
1153+
if (!visibilitymap_test(onerel,blkno,vmbuffer)&&
1154+
heap_page_is_all_visible(buffer,&visibility_cutoff_xid))
1155+
{
1156+
Assert(BufferIsValid(*vmbuffer));
1157+
PageSetAllVisible(page);
1158+
visibilitymap_set(onerel,blkno,InvalidXLogRecPtr,*vmbuffer,
1159+
visibility_cutoff_xid);
1160+
}
1161+
11331162
MarkBufferDirty(buffer);
11341163

11351164
/* XLOG stuff */
@@ -1633,3 +1662,99 @@ vac_cmp_itemptr(const void *left, const void *right)
16331662

16341663
return0;
16351664
}
1665+
1666+
/*
1667+
* Check if every tuple in the given page is visible to all current and future
1668+
* transactions. Also return the visibility_cutoff_xid which is the highest
1669+
* xmin amongst the visible tuples.
1670+
*/
1671+
staticbool
1672+
heap_page_is_all_visible(Bufferbuf,TransactionId*visibility_cutoff_xid)
1673+
{
1674+
Pagepage=BufferGetPage(buf);
1675+
OffsetNumberoffnum,
1676+
maxoff;
1677+
boolall_visible= true;
1678+
1679+
*visibility_cutoff_xid=InvalidTransactionId;
1680+
1681+
/*
1682+
* This is a stripped down version of the line pointer scan in
1683+
* lazy_scan_heap(). So if you change anything here, also check that
1684+
* code.
1685+
*/
1686+
maxoff=PageGetMaxOffsetNumber(page);
1687+
for (offnum=FirstOffsetNumber;
1688+
offnum <=maxoff&&all_visible;
1689+
offnum=OffsetNumberNext(offnum))
1690+
{
1691+
ItemIditemid;
1692+
HeapTupleDatatuple;
1693+
1694+
itemid=PageGetItemId(page,offnum);
1695+
1696+
/* Unused or redirect line pointers are of no interest */
1697+
if (!ItemIdIsUsed(itemid)||ItemIdIsRedirected(itemid))
1698+
continue;
1699+
1700+
ItemPointerSet(&(tuple.t_self),BufferGetBlockNumber(buf),offnum);
1701+
1702+
/*
1703+
* Dead line pointers can have index pointers pointing to them. So they
1704+
* can't be treated as visible
1705+
*/
1706+
if (ItemIdIsDead(itemid))
1707+
{
1708+
all_visible= false;
1709+
break;
1710+
}
1711+
1712+
Assert(ItemIdIsNormal(itemid));
1713+
1714+
tuple.t_data= (HeapTupleHeader)PageGetItem(page,itemid);
1715+
1716+
switch (HeapTupleSatisfiesVacuum(tuple.t_data,OldestXmin,buf))
1717+
{
1718+
caseHEAPTUPLE_LIVE:
1719+
{
1720+
TransactionIdxmin;
1721+
1722+
/* Check comments in lazy_scan_heap. */
1723+
if (!(tuple.t_data->t_infomask&HEAP_XMIN_COMMITTED))
1724+
{
1725+
all_visible= false;
1726+
break;
1727+
}
1728+
1729+
/*
1730+
* The inserter definitely committed. But is it old
1731+
* enough that everyone sees it as committed?
1732+
*/
1733+
xmin=HeapTupleHeaderGetXmin(tuple.t_data);
1734+
if (!TransactionIdPrecedes(xmin,OldestXmin))
1735+
{
1736+
all_visible= false;
1737+
break;
1738+
}
1739+
1740+
/* Track newest xmin on page. */
1741+
if (TransactionIdFollows(xmin,*visibility_cutoff_xid))
1742+
*visibility_cutoff_xid=xmin;
1743+
}
1744+
break;
1745+
1746+
caseHEAPTUPLE_DEAD:
1747+
caseHEAPTUPLE_RECENTLY_DEAD:
1748+
caseHEAPTUPLE_INSERT_IN_PROGRESS:
1749+
caseHEAPTUPLE_DELETE_IN_PROGRESS:
1750+
all_visible= false;
1751+
break;
1752+
1753+
default:
1754+
elog(ERROR,"unexpected HeapTupleSatisfiesVacuum result");
1755+
break;
1756+
}
1757+
}/* scan along page */
1758+
1759+
returnall_visible;
1760+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp