vacuum-secondphase-setvm-v2.patch
application/octet-stream
Filename: vacuum-secondphase-setvm-v2.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/commands/vacuumlazy.c | 121 | 0 |
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 5036849..fdbc8e5 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -136,6 +136,7 @@ static void lazy_record_dead_tuple(LVRelStats *vacrelstats,
ItemPointer itemptr);
static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
static int vac_cmp_itemptr(const void *left, const void *right);
+static bool heap_page_is_all_visible(Buffer buf, TransactionId *visibility_cutoff_xid);
/*
@@ -666,6 +667,11 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
hastup = false;
prev_dead_count = vacrelstats->num_dead_tuples;
maxoff = PageGetMaxOffsetNumber(page);
+
+ /*
+ * Note: If you change anything below, also look at
+ * heap_page_is_all_visible to see if that needs to be changed
+ */
for (offnum = FirstOffsetNumber;
offnum <= maxoff;
offnum = OffsetNumberNext(offnum))
@@ -1078,6 +1084,8 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
Page page = BufferGetPage(buffer);
OffsetNumber unused[MaxOffsetNumber];
int uncnt = 0;
+ Buffer vmbuffer = InvalidBuffer;
+ TransactionId visibility_cutoff_xid;
START_CRIT_SECTION();
@@ -1098,6 +1106,22 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
PageRepairFragmentation(page);
+ /*
+ * Now that we have removed the dead tuples from the page, once again check
+ * if the page has become all-visible.
+ */
+ if (!visibilitymap_test(onerel, blkno, &vmbuffer) &&
+ heap_page_is_all_visible(buffer, &visibility_cutoff_xid))
+ {
+ Assert(BufferIsValid(vmbuffer));
+ PageSetAllVisible(page);
+ visibilitymap_set(onerel, blkno, InvalidXLogRecPtr, vmbuffer,
+ visibility_cutoff_xid);
+ }
+
+ if (BufferIsValid(vmbuffer))
+ ReleaseBuffer(vmbuffer);
+
MarkBufferDirty(buffer);
/* XLOG stuff */
@@ -1519,3 +1543,100 @@ vac_cmp_itemptr(const void *left, const void *right)
return 0;
}
+
+/*
+ * Check if every tuple in the given page is visible to all current and future
+ * transactions. Also return the visibility_cutoff_xid which is the highest
+ * xmin amongst the visible tuples
+ */
+static bool
+heap_page_is_all_visible(Buffer buf, TransactionId *visibility_cutoff_xid)
+{
+ Page page = BufferGetPage(buf);
+ OffsetNumber offnum,
+ maxoff;
+ bool all_visible = true;
+
+ *visibility_cutoff_xid = InvalidTransactionId;
+
+ /*
+ * This is strip down version of the line pointer scan in lazy_scan_heap().
+ * So if you change anything there, also check this code
+ */
+ maxoff = PageGetMaxOffsetNumber(page);
+ for (offnum = FirstOffsetNumber;
+ offnum <= maxoff && all_visible;
+ offnum = OffsetNumberNext(offnum))
+ {
+ ItemId itemid;
+ HeapTupleData tuple;
+
+ itemid = PageGetItemId(page, offnum);
+
+ /* Unused or redirect line pointers are of no interest */
+ if (!ItemIdIsUsed(itemid) || ItemIdIsRedirected(itemid))
+ continue;
+
+ ItemPointerSet(&(tuple.t_self), BufferGetBlockNumber(buf), offnum);
+
+ /*
+ * Dead line pointers can have index pointers pointing to them. So they
+ * can't be treated as visible
+ */
+ if (ItemIdIsDead(itemid))
+ {
+ all_visible = false;
+ break;
+ }
+
+ Assert(ItemIdIsNormal(itemid));
+
+ tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
+
+ switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
+ {
+ case HEAPTUPLE_LIVE:
+ {
+ TransactionId xmin;
+
+ /* Check comments in lazy_scan_heap */
+ if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
+ {
+ all_visible = false;
+ break;
+ }
+
+ /*
+ * The inserter definitely committed. But is it old
+ * enough that everyone sees it as committed?
+ */
+ xmin = HeapTupleHeaderGetXmin(tuple.t_data);
+ if (!TransactionIdPrecedes(xmin, OldestXmin))
+ {
+ all_visible = false;
+ break;
+ }
+
+ /* Track newest xmin on page. */
+ if (TransactionIdFollows(xmin, *visibility_cutoff_xid))
+ *visibility_cutoff_xid = xmin;
+ }
+ break;
+
+ case HEAPTUPLE_DEAD:
+ /* fall through */
+ case HEAPTUPLE_RECENTLY_DEAD:
+ /* fall through */
+ case HEAPTUPLE_INSERT_IN_PROGRESS:
+ /* fall through */
+ case HEAPTUPLE_DELETE_IN_PROGRESS:
+ all_visible = false;
+ break;
+ default:
+ elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
+ break;
+ }
+ } /* scan along page */
+
+ return all_visible;
+}