mirror of
https://github.com/postgres/postgres.git
synced 2026-05-27 20:27:28 -04:00
Update FSM during prune/freeze replay even if freespace is zero
add323da40started updating the visibility map in the same WAL record as pruning and freezing. This included updating the freespace map during replay of a record setting the VM, which we've done sinceab7dbd681.add323da40, however, conditioned doing so on there being > 0 freespace on the page, which differed from the previous state for records updating the VM. The FSM is not WAL-logged and is instead updated heuristically on standbys. In rare cases, this heuristic could lead to pages with 0 freespace having outdated entries in the FSM. If the standby is later promoted and vacuum skips these pages because they are marked all-visible/all-frozen, overly optimistic values would be propagated up the FSM tree, causing slowness when searching for freespace for new tuples. Fix it by always updating the FSM during replay when setting VM bits. Author: Melanie Plageman <melanieplageman@gmail.com> Reported-by: Alexey Makhmutov <a.makhmutov@postgrespro.ru> Discussion: https://postgr.es/m/ead2f110-c736-48f5-99e1-023dc9acbf0b%40postgrespro.ru
This commit is contained in:
parent
af1ed03739
commit
b4c1b2be30
1 changed files with 5 additions and 1 deletions
|
|
@ -38,6 +38,7 @@ heap_xlog_prune_freeze(XLogReaderState *record)
|
|||
Buffer vmbuffer = InvalidBuffer;
|
||||
uint8 vmflags = 0;
|
||||
Size freespace = 0;
|
||||
bool do_update_fsm = false;
|
||||
|
||||
XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno);
|
||||
memcpy(&xlrec, maindataptr, SizeOfHeapPrune);
|
||||
|
|
@ -211,7 +212,10 @@ heap_xlog_prune_freeze(XLogReaderState *record)
|
|||
XLHP_HAS_DEAD_ITEMS |
|
||||
XLHP_HAS_NOW_UNUSED_ITEMS)) ||
|
||||
(vmflags & VISIBILITYMAP_VALID_BITS))
|
||||
{
|
||||
freespace = PageGetHeapFreeSpace(BufferGetPage(buffer));
|
||||
do_update_fsm = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to avoid holding an exclusive lock on the heap buffer while
|
||||
|
|
@ -248,7 +252,7 @@ heap_xlog_prune_freeze(XLogReaderState *record)
|
|||
if (BufferIsValid(vmbuffer))
|
||||
UnlockReleaseBuffer(vmbuffer);
|
||||
|
||||
if (freespace > 0)
|
||||
if (do_update_fsm)
|
||||
XLogRecordPageWithFreeSpace(rlocator, blkno, freespace);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue