Skip to content

Commit e48c817

Browse files
Recycle deleted nbtree pages more aggressively.
Commit 61b313e made nbtree consistently pass down a heaprel to low level routines like _bt_getbuf(). Although this was primarily intended as preparation for logical decoding on standbys, it also made it easy to correct an old deficiency in how nbtree VACUUM determines whether or not it's now safe to recycle deleted pages. Pass the heaprel to GlobalVisTestFor() in nbtree routines that deal with recycle safety. nbtree now makes less pessimistic assumptions about recycle safety within non-catalog relations. This enhancement complements the recycling enhancement added by commit 9dd963a. nbtree remains just as pessimistic as ever when it comes to recycle safety within indexes on catalog relations. There is no fundamental reason why we need to treat catalog relations differently, though. The behavioral inconsistency is a consequence of the way that nbtree uses nextXID values to implement what Lanin and Shasha call "the drain technique". Note in particular that it has nothing to do with whether or not index tuples might still be required for an older MVCC snapshot. Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Discussion: https://postgr.es/m/CAH2-WzkaiDxCje0yPuH=3Uh2p1V_2pFGY==xfbZoZu7Ax_NB8g@mail.gmail.com
1 parent a349b86 commit e48c817

File tree

3 files changed

+8
-10
lines changed

3 files changed

+8
-10
lines changed

src/backend/access/nbtree/nbtpage.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,7 @@ _bt_getbuf(Relation rel, Relation heaprel, BlockNumber blkno, int access)
935935
return buf;
936936
}
937937

938-
if (BTPageIsRecyclable(page))
938+
if (BTPageIsRecyclable(page, heaprel))
939939
{
940940
/*
941941
* If we are generating WAL for Hot Standby then create a
@@ -2963,6 +2963,7 @@ void
29632963
_bt_pendingfsm_finalize(Relation rel, BTVacState *vstate)
29642964
{
29652965
IndexBulkDeleteResult *stats = vstate->stats;
2966+
Relation heaprel = vstate->info->heaprel;
29662967

29672968
Assert(stats->pages_newly_deleted >= vstate->npendingpages);
29682969

@@ -2995,7 +2996,7 @@ _bt_pendingfsm_finalize(Relation rel, BTVacState *vstate)
29952996
* essential; GlobalVisCheckRemovableFullXid() will not reliably recognize
29962997
* that it is now safe to recycle newly deleted pages without this step.
29972998
*/
2998-
GetOldestNonRemovableTransactionId(NULL);
2999+
GetOldestNonRemovableTransactionId(heaprel);
29993000

30003001
for (int i = 0; i < vstate->npendingpages; i++)
30013002
{
@@ -3010,7 +3011,7 @@ _bt_pendingfsm_finalize(Relation rel, BTVacState *vstate)
30103011
* must be non-recyclable too, since _bt_pendingfsm_add() adds pages
30113012
* to the array in safexid order.
30123013
*/
3013-
if (!GlobalVisCheckRemovableFullXid(NULL, safexid))
3014+
if (!GlobalVisCheckRemovableFullXid(heaprel, safexid))
30143015
break;
30153016

30163017
RecordFreeIndexPage(rel, target);

src/backend/access/nbtree/nbtree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,7 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno)
10391039
IndexBulkDeleteCallback callback = vstate->callback;
10401040
void *callback_state = vstate->callback_state;
10411041
Relation rel = info->index;
1042+
Relation heaprel = info->heaprel;
10421043
bool attempt_pagedel;
10431044
BlockNumber blkno,
10441045
backtrack_to;
@@ -1124,7 +1125,7 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno)
11241125
}
11251126
}
11261127

1127-
if (!opaque || BTPageIsRecyclable(page))
1128+
if (!opaque || BTPageIsRecyclable(page, heaprel))
11281129
{
11291130
/* Okay to recycle this page (which could be leaf or internal) */
11301131
RecordFreeIndexPage(rel, blkno);

src/include/access/nbtree.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ BTPageGetDeleteXid(Page page)
288288
* well need special handling for new pages anyway.
289289
*/
290290
static inline bool
291-
BTPageIsRecyclable(Page page)
291+
BTPageIsRecyclable(Page page, Relation heaprel)
292292
{
293293
BTPageOpaque opaque;
294294

@@ -307,12 +307,8 @@ BTPageIsRecyclable(Page page)
307307
* For that check if the deletion XID could still be visible to
308308
* anyone. If not, then no scan that's still in progress could have
309309
* seen its downlink, and we can recycle it.
310-
*
311-
* XXX: If we had the heap relation we could be more aggressive about
312-
* recycling deleted pages in non-catalog relations. For now we just
313-
* pass NULL. That is at least simple and consistent.
314310
*/
315-
return GlobalVisCheckRemovableFullXid(NULL, BTPageGetDeleteXid(page));
311+
return GlobalVisCheckRemovableFullXid(heaprel, BTPageGetDeleteXid(page));
316312
}
317313

318314
return false;

0 commit comments

Comments
 (0)