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

Commite6799d5

Browse files
committed
Move page initialization from RelationAddExtraBlocks() to use.
Previously we initialized pages when bulk extending inRelationAddExtraBlocks(). That has a major disadvantage: It tiesRelationAddExtraBlocks() to heap, as other types of storage are likelyto need different amounts of special space, have different amount offree space (previously determined by PageGetHeapFreeSpace()).That we're relying on initializing pages, but not WAL logging theinitialization, also means the risk for getting"WARNING: relation \"%s\" page %u is uninitialized --- fixing"style warnings in vacuums after crashes/immediate shutdowns, isconsiderably higher. The warning sounds much more serious than whatthey are.Fix those two issues together by not initializing pages inRelationAddExtraPages() (but continue to do so inRelationGetBufferForTuple(), which is linked much more closely toheap), and accepting uninitialized pages as normal invacuumlazy.c. When vacuumlazy encounters an empty page it now adds itto the FSM, but does nothing else. We chose to not issue a debugmessage, much less a warning in that case - it seems rarely useful,and quite likely to scare people unnecessarily.For now empty pages aren't added to the VM, because standbys would notre-discover such pages after a promotion. In contrast to other sourcesfor empty pages, there's no corresponding WAL records triggering FSMupdates during replay.Author: Andres FreundReviewed-By: Tom LaneDiscussion:https://postgr.es/m/20181219083945.6khtgm36mivonhva@alap3.anarazel.de
1 parentd4316b8 commite6799d5

File tree

2 files changed

+59
-49
lines changed

2 files changed

+59
-49
lines changed

‎src/backend/access/heap/hio.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
204204
/*
205205
* Extend by one page. This should generally match the main-line
206206
* extension code in RelationGetBufferForTuple, except that we hold
207-
* the relation extension lock throughout.
207+
* the relation extension lock throughout, and we don't immediately
208+
* initialize the page (see below).
208209
*/
209210
buffer=ReadBufferBI(relation,P_NEW,bistate);
210211

@@ -216,18 +217,16 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
216217
BufferGetBlockNumber(buffer),
217218
RelationGetRelationName(relation));
218219

219-
PageInit(page,BufferGetPageSize(buffer),0);
220-
221220
/*
222-
* We mark all the new buffers dirty, but do nothing to write them
223-
* out; they'll probably get used soon, and even if they are not, a
224-
* crash will leave an okay all-zeroes page on disk.
221+
* Add the page to the FSM without initializing. If we were to
222+
* initialize here the page would potentially get flushed out to disk
223+
* before we add any useful content. There's no guarantee that that'd
224+
* happen before a potential crash, so we need to deal with
225+
* uninitialized pages anyway, thus avoid the potential for
226+
* unnecessary writes.
225227
*/
226-
MarkBufferDirty(buffer);
227-
228-
/* we'll need this info below */
229228
blockNum=BufferGetBlockNumber(buffer);
230-
freespace=PageGetHeapFreeSpace(page);
229+
freespace=BufferGetPageSize(buffer)-SizeOfPageHeaderData;
231230

232231
UnlockReleaseBuffer(buffer);
233232

@@ -479,6 +478,18 @@ RelationGetBufferForTuple(Relation relation, Size len,
479478
* we're done.
480479
*/
481480
page=BufferGetPage(buffer);
481+
482+
/*
483+
* Initialize page, it'll be used soon. We could avoid dirtying the
484+
* buffer here, and rely on the caller to do so whenever it puts a
485+
* tuple onto the page, but there seems not much benefit in doing so.
486+
*/
487+
if (PageIsNew(page))
488+
{
489+
PageInit(page,BufferGetPageSize(buffer),0);
490+
MarkBufferDirty(buffer);
491+
}
492+
482493
pageFreeSpace=PageGetHeapFreeSpace(page);
483494
if (len+saveFreeSpace <=pageFreeSpace)
484495
{

‎src/backend/access/heap/vacuumlazy.c

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -861,42 +861,38 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
861861
if (PageIsNew(page))
862862
{
863863
/*
864-
* An all-zeroes page could be left over if a backend extends the
865-
* relation but crashes before initializing the page. Reclaim such
866-
* pages for use.
864+
* All-zeroes pages can be left over if either a backend extends
865+
* the relation by a single page, but crashes before the newly
866+
* initialized page has been written out, or when bulk-extending
867+
* the relation (which creates a number of empty pages at the tail
868+
* end of the relation, but enters them into the FSM).
867869
*
868-
* We have to be careful here because we could be looking at a
869-
* page that someone has just added to the relation and not yet
870-
* been able to initialize (see RelationGetBufferForTuple). To
871-
* protect against that, release the buffer lock, grab the
872-
* relation extension lock momentarily, and re-lock the buffer. If
873-
* the page is still uninitialized by then, it must be left over
874-
* from a crashed backend, and we can initialize it.
870+
* Make sure these pages are in the FSM, to ensure they can be
871+
* reused. Do that by testing if there's any space recorded for
872+
* the page. If not, enter it.
875873
*
876-
* We don't really need the relation lock when this is a new or
877-
* temp relation, but it's probably not worth the code space to
878-
* check that, since this surely isn't a critical path.
879-
*
880-
* Note: the comparable code in vacuum.c need not worry because
881-
* it's got exclusive lock on the whole relation.
874+
* Note we do not enter the page into the visibilitymap. That has
875+
* the downside that we repeatedly visit this page in subsequent
876+
* vacuums, but otherwise we'll never not discover the space on a
877+
* promoted standby. The harm of repeated checking ought to
878+
* normally not be too bad - the space usually should be used at
879+
* some point, otherwise there wouldn't be any regular vacuums.
880+
*/
881+
empty_pages++;
882+
883+
/*
884+
* Perform checking of FSM after releasing lock, the fsm is
885+
* approximate, after all.
882886
*/
883-
LockBuffer(buf,BUFFER_LOCK_UNLOCK);
884-
LockRelationForExtension(onerel,ExclusiveLock);
885-
UnlockRelationForExtension(onerel,ExclusiveLock);
886-
LockBufferForCleanup(buf);
887-
if (PageIsNew(page))
888-
{
889-
ereport(WARNING,
890-
(errmsg("relation \"%s\" page %u is uninitialized --- fixing",
891-
relname,blkno)));
892-
PageInit(page,BufferGetPageSize(buf),0);
893-
empty_pages++;
894-
}
895-
freespace=PageGetHeapFreeSpace(page);
896-
MarkBufferDirty(buf);
897887
UnlockReleaseBuffer(buf);
898888

899-
RecordPageWithFreeSpace(onerel,blkno,freespace);
889+
if (GetRecordedFreeSpace(onerel,blkno)==0)
890+
{
891+
Sizefreespace;
892+
893+
freespace=BufferGetPageSize(buf)-SizeOfPageHeaderData;
894+
RecordPageWithFreeSpace(onerel,blkno,freespace);
895+
}
900896
continue;
901897
}
902898

@@ -905,7 +901,10 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
905901
empty_pages++;
906902
freespace=PageGetHeapFreeSpace(page);
907903

908-
/* empty pages are always all-visible and all-frozen */
904+
/*
905+
* Empty pages are always all-visible and all-frozen (note that
906+
* the same is currently not true for new pages, see above).
907+
*/
909908
if (!PageIsAllVisible(page))
910909
{
911910
START_CRIT_SECTION();
@@ -1639,12 +1638,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
16391638

16401639
*hastup= false;
16411640

1642-
/* If we hit an uninitialized page, we want to force vacuuming it. */
1643-
if (PageIsNew(page))
1644-
return true;
1645-
1646-
/* Quick out for ordinary empty page. */
1647-
if (PageIsEmpty(page))
1641+
/*
1642+
* New and empty pages, obviously, don't contain tuples. We could make
1643+
* sure that the page is registered in the FSM, but it doesn't seem worth
1644+
* waiting for a cleanup lock just for that, especially because it's
1645+
* likely that the pin holder will do so.
1646+
*/
1647+
if (PageIsNew(page)||PageIsEmpty(page))
16481648
return false;
16491649

16501650
maxoff=PageGetMaxOffsetNumber(page);
@@ -2029,7 +2029,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
20292029

20302030
if (PageIsNew(page)||PageIsEmpty(page))
20312031
{
2032-
/* PageIsNew probably shouldn't happen... */
20332032
UnlockReleaseBuffer(buf);
20342033
continue;
20352034
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp