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

Commitab7dbd6

Browse files
committed
Update FSM on WAL replay of page all-visible/frozen
We aren't very strict about keeping FSM up to date on WAL replay,because per-page freespace values aren't critical in replicas (can'twrite to heap in a replica; and if the replica is promoted, the valueswould be updated by VACUUM anyway). However, VACUUM since 9.6 can skipprocessing pages marked all-visible or all-frozen, and if such pages arerecorded in FSM with wrong values, those values are blindly propagatedto FSM's upper layers by VACUUM's FreeSpaceMapVacuum. (This rationaleassumes that crashes are not very frequent, because those would causeoutdated FSM to occur in the primary.)Even when the FSM is outdated in standby, things are not too badnormally, because, most per-page FSM values will be zero (other thanthose propagated with the base-backup that created the standby); onlyonce the remaining free space is less than 0.2*BLCKSZ the per-page valueis maintained by WAL replay of heap ins/upd/del. However, ifwal_log_hints=on causes complete FSM pages to be propagated to a standbyvia full-page images, many too-optimistic per-page values can end upbeing registered in the standby.Incorrect per-page values aren't critical in most cases, since aninserter that is given a page that doesn't actually contain the claimedfree space will update FSM with the correct value, and retry until itfinds a usable page. However, if there are many such updates to do, aninserter can spend a long time doing them before a usable page is found;in a heavily trafficked insert-only table with many concurrent insertersthis has been observed to cause several second stalls, causing visibleapplication malfunction.To fix this problem, it seems sufficient to have heap_xlog_visible(replay of setting all-visible and all-frozen VM bits for a heap page)update the FSM value for the page being processed. This fixes theper-page counters together with making the page skippable to vacuum, sowhen vacuum does FreeSpaceMapVacuum, the values propagated to FSM upperlayers are the correct ones, avoiding the problem.While at it, apply the same fix to heap_xlog_clean (replay of tupleremoval by HOT pruning and vacuum). This makes any space freed by thecleaning available earlier than the next vacuum in the promoted replica.Backpatch to 9.6, where this problem was diagnosed on an insert-onlytable with all-frozen pages, which were introduced as a concept in thatrelease. Theoretically it could apply with all-visible pages to olderbranches, but there's been no report of that and it doesn't backpatchcleanly anyway.Author: Álvaro Herrera <alvherre@alvh.no-ip.org>Discussion:https://postgr.es/m/20180802172857.5skoexsilnjvgruk@alvherre.pgsql
1 parentcc4f6b7 commitab7dbd6

File tree

1 file changed

+40
-12
lines changed

1 file changed

+40
-12
lines changed

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

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8172,15 +8172,14 @@ heap_xlog_cleanup_info(XLogReaderState *record)
81728172
}
81738173

81748174
/*
8175-
* HandlesHEAP2_CLEAN record type
8175+
* HandlesXLOG_HEAP2_CLEAN record type
81768176
*/
81778177
staticvoid
81788178
heap_xlog_clean(XLogReaderState*record)
81798179
{
81808180
XLogRecPtrlsn=record->EndRecPtr;
81818181
xl_heap_clean*xlrec= (xl_heap_clean*)XLogRecGetData(record);
81828182
Bufferbuffer;
8183-
Sizefreespace=0;
81848183
RelFileNodernode;
81858184
BlockNumberblkno;
81868185
XLogRedoActionaction;
@@ -8232,8 +8231,6 @@ heap_xlog_clean(XLogReaderState *record)
82328231
nowdead,ndead,
82338232
nowunused,nunused);
82348233

8235-
freespace=PageGetHeapFreeSpace(page);/* needed to update FSM below */
8236-
82378234
/*
82388235
* Note: we don't worry about updating the page's prunability hints.
82398236
* At worst this will cause an extra prune cycle to occur soon.
@@ -8242,18 +8239,24 @@ heap_xlog_clean(XLogReaderState *record)
82428239
PageSetLSN(page,lsn);
82438240
MarkBufferDirty(buffer);
82448241
}
8242+
82458243
if (BufferIsValid(buffer))
8244+
{
8245+
Sizefreespace=PageGetHeapFreeSpace(BufferGetPage(buffer));
8246+
82468247
UnlockReleaseBuffer(buffer);
82478248

8248-
/*
8249-
* Update the FSM as well.
8250-
*
8251-
* XXX: Don't do this if the page was restored from full page image. We
8252-
* don't bother to update the FSM in that case, it doesn't need to be
8253-
* totally accurate anyway.
8254-
*/
8255-
if (action==BLK_NEEDS_REDO)
8249+
/*
8250+
* After cleaning records from a page, it's useful to update the FSM
8251+
* about it, as it may cause the page become target for insertions
8252+
* later even if vacuum decides not to visit it (which is possible if
8253+
* gets marked all-visible.)
8254+
*
8255+
* Do this regardless of a full-page image being applied, since the
8256+
* FSM data is not in the page anyway.
8257+
*/
82568258
XLogRecordPageWithFreeSpace(rnode,blkno,freespace);
8259+
}
82578260
}
82588261

82598262
/*
@@ -8326,9 +8329,34 @@ heap_xlog_visible(XLogReaderState *record)
83268329
* wal_log_hints enabled.)
83278330
*/
83288331
}
8332+
83298333
if (BufferIsValid(buffer))
8334+
{
8335+
Sizespace=PageGetFreeSpace(BufferGetPage(buffer));
8336+
83308337
UnlockReleaseBuffer(buffer);
83318338

8339+
/*
8340+
* Since FSM is not WAL-logged and only updated heuristically, it
8341+
* easily becomes stale in standbys. If the standby is later promoted
8342+
* and runs VACUUM, it will skip updating individual free space
8343+
* figures for pages that became all-visible (or all-frozen, depending
8344+
* on the vacuum mode,) which is troublesome when FreeSpaceMapVacuum
8345+
* propagates too optimistic free space values to upper FSM layers;
8346+
* later inserters try to use such pages only to find out that they
8347+
* are unusable. This can cause long stalls when there are many such
8348+
* pages.
8349+
*
8350+
* Forestall those problems by updating FSM's idea about a page that
8351+
* is becoming all-visible or all-frozen.
8352+
*
8353+
* Do this regardless of a full-page image being applied, since the
8354+
* FSM data is not in the page anyway.
8355+
*/
8356+
if (xlrec->flags&VISIBILITYMAP_VALID_BITS)
8357+
XLogRecordPageWithFreeSpace(rnode,blkno,space);
8358+
}
8359+
83328360
/*
83338361
* Even if we skipped the heap page update due to the LSN interlock, it's
83348362
* still safe to update the visibility map. Any WAL record that clears

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp