Skip to content

Commit 9ca3100

Browse files
melanieplagemanCommitfest Bot
authored andcommitted
Eliminate XLOG_HEAP2_VISIBLE from vacuum phase I prune/freeze
Vacuum no longer emits a separate WAL record for each page set all-visible or all-frozen during phase I. Instead, visibility map updates are now included in the XLOG_HEAP2_PRUNE_VACUUM_SCAN record that is already emitted for pruning and freezing. Previously, heap_page_prune_and_freeze() determined whether a page was all-visible, but the corresponding VM bits were only set later in lazy_scan_prune(). Now the VM is updated immediately in heap_page_prune_and_freeze(), at the same time as the heap modifications. This change applies only to vacuum phase I, not to pruning performed during normal page access. Reviewed-by: Robert Haas <[email protected]>
1 parent 79f39f8 commit 9ca3100

File tree

4 files changed

+421
-300
lines changed

4 files changed

+421
-300
lines changed

src/backend/access/heap/heapam_xlog.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ heap_xlog_prune_freeze(XLogReaderState *record)
104104
OffsetNumber *frz_offsets;
105105
char *dataptr = XLogRecGetBlockData(record, 0, &datalen);
106106
bool do_prune;
107+
bool set_lsn = false;
108+
bool mark_buffer_dirty = false;
107109

108110
heap_xlog_deserialize_prune_and_freeze(dataptr, xlrec.flags,
109111
&nplans, &plans, &frz_offsets,
@@ -157,17 +159,36 @@ heap_xlog_prune_freeze(XLogReaderState *record)
157159
/* There should be no more data */
158160
Assert((char *) frz_offsets == dataptr + datalen);
159161

160-
if (vmflags & VISIBILITYMAP_VALID_BITS)
161-
PageSetAllVisible(page);
162-
163-
MarkBufferDirty(buffer);
162+
if (do_prune || nplans > 0)
163+
mark_buffer_dirty = set_lsn = true;
164164

165165
/*
166-
* See log_heap_prune_and_freeze() for commentary on when we set the
167-
* heap page LSN.
166+
* The critical integrity requirement here is that we must never end
167+
* up with with the visibility map bit set and the page-level
168+
* PD_ALL_VISIBLE bit clear. If that were to occur, a subsequent page
169+
* modification would fail to clear the visibility map bit.
170+
*
171+
* vmflags may be nonzero with PD_ALL_VISIBLE already set (e.g. when
172+
* marking an all-visible page all-frozen). If only the VM is updated,
173+
* the heap page need not be dirtied.
168174
*/
169-
if (do_prune || nplans > 0 ||
170-
((vmflags & VISIBILITYMAP_VALID_BITS) && XLogHintBitIsNeeded()))
175+
if ((vmflags & VISIBILITYMAP_VALID_BITS) && !PageIsAllVisible(page))
176+
{
177+
PageSetAllVisible(page);
178+
mark_buffer_dirty = true;
179+
180+
/*
181+
* See log_heap_prune_and_freeze() for commentary on when we set
182+
* the heap page LSN.
183+
*/
184+
if (XLogHintBitIsNeeded())
185+
set_lsn = true;
186+
}
187+
188+
if (mark_buffer_dirty)
189+
MarkBufferDirty(buffer);
190+
191+
if (set_lsn)
171192
PageSetLSN(page, lsn);
172193

173194
/*

0 commit comments

Comments
 (0)