Commit 7e453634 authored by Amit Kapila's avatar Amit Kapila

Add additional information in the vacuum error context.

The additional information added will be an offset number for heap
operations. This information will help us in finding the exact tuple due
to which the error has occurred.

Author: Mahendra Singh Thalor and Amit Kapila
Reviewed-by: Sawada Masahiko, Justin Pryzby and Amit Kapila
Discussion: https://postgr.es/m/CAKYtNApK488TDF4bMbw+1QH8HJf9cxdNDXquhU50TK5iv_FtCQ@mail.gmail.com
parent 808e13b2
...@@ -188,7 +188,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer) ...@@ -188,7 +188,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
/* OK to prune */ /* OK to prune */
(void) heap_page_prune(relation, buffer, vistest, (void) heap_page_prune(relation, buffer, vistest,
limited_xmin, limited_ts, limited_xmin, limited_ts,
true, &ignore); true, &ignore, NULL);
} }
/* And release buffer lock */ /* And release buffer lock */
...@@ -213,6 +213,9 @@ heap_page_prune_opt(Relation relation, Buffer buffer) ...@@ -213,6 +213,9 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
* send its own new total to pgstats, and we don't want this delta applied * send its own new total to pgstats, and we don't want this delta applied
* on top of that.) * on top of that.)
* *
* off_loc is the offset location required by the caller to use in error
* callback.
*
* Returns the number of tuples deleted from the page and sets * Returns the number of tuples deleted from the page and sets
* latestRemovedXid. * latestRemovedXid.
*/ */
...@@ -221,7 +224,8 @@ heap_page_prune(Relation relation, Buffer buffer, ...@@ -221,7 +224,8 @@ heap_page_prune(Relation relation, Buffer buffer,
GlobalVisState *vistest, GlobalVisState *vistest,
TransactionId old_snap_xmin, TransactionId old_snap_xmin,
TimestampTz old_snap_ts, TimestampTz old_snap_ts,
bool report_stats, TransactionId *latestRemovedXid) bool report_stats, TransactionId *latestRemovedXid,
OffsetNumber *off_loc)
{ {
int ndeleted = 0; int ndeleted = 0;
Page page = BufferGetPage(buffer); Page page = BufferGetPage(buffer);
...@@ -262,6 +266,13 @@ heap_page_prune(Relation relation, Buffer buffer, ...@@ -262,6 +266,13 @@ heap_page_prune(Relation relation, Buffer buffer,
if (prstate.marked[offnum]) if (prstate.marked[offnum])
continue; continue;
/*
* Set the offset number so that we can display it along with any
* error that occurred while processing this tuple.
*/
if (off_loc)
*off_loc = offnum;
/* Nothing to do if slot is empty or already dead */ /* Nothing to do if slot is empty or already dead */
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
if (!ItemIdIsUsed(itemid) || ItemIdIsDead(itemid)) if (!ItemIdIsUsed(itemid) || ItemIdIsDead(itemid))
...@@ -271,6 +282,10 @@ heap_page_prune(Relation relation, Buffer buffer, ...@@ -271,6 +282,10 @@ heap_page_prune(Relation relation, Buffer buffer,
ndeleted += heap_prune_chain(buffer, offnum, &prstate); ndeleted += heap_prune_chain(buffer, offnum, &prstate);
} }
/* Clear the offset information once we have processed the given page. */
if (off_loc)
*off_loc = InvalidOffsetNumber;
/* Any error while applying the changes is critical */ /* Any error while applying the changes is critical */
START_CRIT_SECTION(); START_CRIT_SECTION();
......
...@@ -316,6 +316,7 @@ typedef struct LVRelStats ...@@ -316,6 +316,7 @@ typedef struct LVRelStats
/* Used for error callback */ /* Used for error callback */
char *indname; char *indname;
BlockNumber blkno; /* used only for heap operations */ BlockNumber blkno; /* used only for heap operations */
OffsetNumber offnum; /* used only for heap operations */
VacErrPhase phase; VacErrPhase phase;
} LVRelStats; } LVRelStats;
...@@ -323,6 +324,7 @@ typedef struct LVRelStats ...@@ -323,6 +324,7 @@ typedef struct LVRelStats
typedef struct LVSavedErrInfo typedef struct LVSavedErrInfo
{ {
BlockNumber blkno; BlockNumber blkno;
OffsetNumber offnum;
VacErrPhase phase; VacErrPhase phase;
} LVSavedErrInfo; } LVSavedErrInfo;
...@@ -341,7 +343,8 @@ static void lazy_scan_heap(Relation onerel, VacuumParams *params, ...@@ -341,7 +343,8 @@ static void lazy_scan_heap(Relation onerel, VacuumParams *params,
LVRelStats *vacrelstats, Relation *Irel, int nindexes, LVRelStats *vacrelstats, Relation *Irel, int nindexes,
bool aggressive); bool aggressive);
static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats); static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
static bool lazy_check_needs_freeze(Buffer buf, bool *hastup); static bool lazy_check_needs_freeze(Buffer buf, bool *hastup,
LVRelStats *vacrelstats);
static void lazy_vacuum_all_indexes(Relation onerel, Relation *Irel, static void lazy_vacuum_all_indexes(Relation onerel, Relation *Irel,
IndexBulkDeleteResult **stats, IndexBulkDeleteResult **stats,
LVRelStats *vacrelstats, LVParallelState *lps, LVRelStats *vacrelstats, LVParallelState *lps,
...@@ -364,6 +367,7 @@ static void lazy_record_dead_tuple(LVDeadTuples *dead_tuples, ...@@ -364,6 +367,7 @@ static void lazy_record_dead_tuple(LVDeadTuples *dead_tuples,
static bool lazy_tid_reaped(ItemPointer itemptr, void *state); static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
static int vac_cmp_itemptr(const void *left, const void *right); static int vac_cmp_itemptr(const void *left, const void *right);
static bool heap_page_is_all_visible(Relation rel, Buffer buf, static bool heap_page_is_all_visible(Relation rel, Buffer buf,
LVRelStats *vacrelstats,
TransactionId *visibility_cutoff_xid, bool *all_frozen); TransactionId *visibility_cutoff_xid, bool *all_frozen);
static void lazy_parallel_vacuum_indexes(Relation *Irel, IndexBulkDeleteResult **stats, static void lazy_parallel_vacuum_indexes(Relation *Irel, IndexBulkDeleteResult **stats,
LVRelStats *vacrelstats, LVParallelState *lps, LVRelStats *vacrelstats, LVParallelState *lps,
...@@ -396,7 +400,8 @@ static LVSharedIndStats *get_indstats(LVShared *lvshared, int n); ...@@ -396,7 +400,8 @@ static LVSharedIndStats *get_indstats(LVShared *lvshared, int n);
static bool skip_parallel_vacuum_index(Relation indrel, LVShared *lvshared); static bool skip_parallel_vacuum_index(Relation indrel, LVShared *lvshared);
static void vacuum_error_callback(void *arg); static void vacuum_error_callback(void *arg);
static void update_vacuum_error_info(LVRelStats *errinfo, LVSavedErrInfo *saved_err_info, static void update_vacuum_error_info(LVRelStats *errinfo, LVSavedErrInfo *saved_err_info,
int phase, BlockNumber blkno); int phase, BlockNumber blkno,
OffsetNumber offnum);
static void restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedErrInfo *saved_err_info); static void restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedErrInfo *saved_err_info);
...@@ -547,7 +552,8 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params, ...@@ -547,7 +552,8 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
* revert to the previous phase. * revert to the previous phase.
*/ */
update_vacuum_error_info(vacrelstats, NULL, VACUUM_ERRCB_PHASE_TRUNCATE, update_vacuum_error_info(vacrelstats, NULL, VACUUM_ERRCB_PHASE_TRUNCATE,
vacrelstats->nonempty_pages); vacrelstats->nonempty_pages,
InvalidOffsetNumber);
lazy_truncate_heap(onerel, vacrelstats); lazy_truncate_heap(onerel, vacrelstats);
} }
...@@ -960,7 +966,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, ...@@ -960,7 +966,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno);
update_vacuum_error_info(vacrelstats, NULL, VACUUM_ERRCB_PHASE_SCAN_HEAP, update_vacuum_error_info(vacrelstats, NULL, VACUUM_ERRCB_PHASE_SCAN_HEAP,
blkno); blkno, InvalidOffsetNumber);
if (blkno == next_unskippable_block) if (blkno == next_unskippable_block)
{ {
...@@ -1129,7 +1135,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, ...@@ -1129,7 +1135,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
* to use lazy_check_needs_freeze() for both situations, though. * to use lazy_check_needs_freeze() for both situations, though.
*/ */
LockBuffer(buf, BUFFER_LOCK_SHARE); LockBuffer(buf, BUFFER_LOCK_SHARE);
if (!lazy_check_needs_freeze(buf, &hastup)) if (!lazy_check_needs_freeze(buf, &hastup, vacrelstats))
{ {
UnlockReleaseBuffer(buf); UnlockReleaseBuffer(buf);
vacrelstats->scanned_pages++; vacrelstats->scanned_pages++;
...@@ -1244,7 +1250,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, ...@@ -1244,7 +1250,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
*/ */
tups_vacuumed += heap_page_prune(onerel, buf, vistest, false, tups_vacuumed += heap_page_prune(onerel, buf, vistest, false,
InvalidTransactionId, 0, InvalidTransactionId, 0,
&vacrelstats->latestRemovedXid); &vacrelstats->latestRemovedXid,
&vacrelstats->offnum);
/* /*
* Now scan the page to collect vacuumable items and check for tuples * Now scan the page to collect vacuumable items and check for tuples
...@@ -1267,6 +1274,11 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, ...@@ -1267,6 +1274,11 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
{ {
ItemId itemid; ItemId itemid;
/*
* Set the offset number so that we can display it along with any
* error that occurred while processing this tuple.
*/
vacrelstats->offnum = offnum;
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
/* Unused items require no processing, but we count 'em */ /* Unused items require no processing, but we count 'em */
...@@ -1468,6 +1480,12 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, ...@@ -1468,6 +1480,12 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
} }
} /* scan along page */ } /* scan along page */
/*
* Clear the offset information once we have processed all the tuples
* on the page.
*/
vacrelstats->offnum = InvalidOffsetNumber;
/* /*
* If we froze any tuples, mark the buffer dirty, and write a WAL * If we froze any tuples, mark the buffer dirty, and write a WAL
* record recording the changes. We must log the changes to be * record recording the changes. We must log the changes to be
...@@ -1845,7 +1863,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) ...@@ -1845,7 +1863,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
/* Update error traceback information */ /* Update error traceback information */
update_vacuum_error_info(vacrelstats, &saved_err_info, VACUUM_ERRCB_PHASE_VACUUM_HEAP, update_vacuum_error_info(vacrelstats, &saved_err_info, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
InvalidBlockNumber); InvalidBlockNumber, InvalidOffsetNumber);
pg_rusage_init(&ru0); pg_rusage_init(&ru0);
npages = 0; npages = 0;
...@@ -1927,7 +1945,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, ...@@ -1927,7 +1945,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
/* Update error traceback information */ /* Update error traceback information */
update_vacuum_error_info(vacrelstats, &saved_err_info, VACUUM_ERRCB_PHASE_VACUUM_HEAP, update_vacuum_error_info(vacrelstats, &saved_err_info, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
blkno); blkno, InvalidOffsetNumber);
START_CRIT_SECTION(); START_CRIT_SECTION();
...@@ -1979,7 +1997,8 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, ...@@ -1979,7 +1997,8 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
* dirty, exclusively locked, and, if needed, a full page image has been * dirty, exclusively locked, and, if needed, a full page image has been
* emitted in the log_heap_clean() above. * emitted in the log_heap_clean() above.
*/ */
if (heap_page_is_all_visible(onerel, buffer, &visibility_cutoff_xid, if (heap_page_is_all_visible(onerel, buffer, vacrelstats,
&visibility_cutoff_xid,
&all_frozen)) &all_frozen))
PageSetAllVisible(page); PageSetAllVisible(page);
...@@ -2018,7 +2037,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, ...@@ -2018,7 +2037,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
* Also returns a flag indicating whether page contains any tuples at all. * Also returns a flag indicating whether page contains any tuples at all.
*/ */
static bool static bool
lazy_check_needs_freeze(Buffer buf, bool *hastup) lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats)
{ {
Page page = BufferGetPage(buf); Page page = BufferGetPage(buf);
OffsetNumber offnum, OffsetNumber offnum,
...@@ -2043,6 +2062,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup) ...@@ -2043,6 +2062,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
{ {
ItemId itemid; ItemId itemid;
/*
* Set the offset number so that we can display it along with any
* error that occurred while processing this tuple.
*/
vacrelstats->offnum = offnum;
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
/* this should match hastup test in count_nondeletable_pages() */ /* this should match hastup test in count_nondeletable_pages() */
...@@ -2057,10 +2081,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup) ...@@ -2057,10 +2081,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, if (heap_tuple_needs_freeze(tupleheader, FreezeLimit,
MultiXactCutoff, buf)) MultiXactCutoff, buf))
return true; break;
} /* scan along page */ } /* scan along page */
return false; /* Clear the offset information once we have processed the given page. */
vacrelstats->offnum = InvalidOffsetNumber;
return (offnum <= maxoff);
} }
/* /*
...@@ -2438,7 +2465,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats, ...@@ -2438,7 +2465,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
vacrelstats->indname = pstrdup(RelationGetRelationName(indrel)); vacrelstats->indname = pstrdup(RelationGetRelationName(indrel));
update_vacuum_error_info(vacrelstats, &saved_err_info, update_vacuum_error_info(vacrelstats, &saved_err_info,
VACUUM_ERRCB_PHASE_VACUUM_INDEX, VACUUM_ERRCB_PHASE_VACUUM_INDEX,
InvalidBlockNumber); InvalidBlockNumber, InvalidOffsetNumber);
/* Do bulk deletion */ /* Do bulk deletion */
*stats = index_bulk_delete(&ivinfo, *stats, *stats = index_bulk_delete(&ivinfo, *stats,
...@@ -2498,7 +2525,7 @@ lazy_cleanup_index(Relation indrel, ...@@ -2498,7 +2525,7 @@ lazy_cleanup_index(Relation indrel,
vacrelstats->indname = pstrdup(RelationGetRelationName(indrel)); vacrelstats->indname = pstrdup(RelationGetRelationName(indrel));
update_vacuum_error_info(vacrelstats, &saved_err_info, update_vacuum_error_info(vacrelstats, &saved_err_info,
VACUUM_ERRCB_PHASE_INDEX_CLEANUP, VACUUM_ERRCB_PHASE_INDEX_CLEANUP,
InvalidBlockNumber); InvalidBlockNumber, InvalidOffsetNumber);
*stats = index_vacuum_cleanup(&ivinfo, *stats); *stats = index_vacuum_cleanup(&ivinfo, *stats);
...@@ -2522,7 +2549,7 @@ lazy_cleanup_index(Relation indrel, ...@@ -2522,7 +2549,7 @@ lazy_cleanup_index(Relation indrel,
pg_rusage_show(&ru0)))); pg_rusage_show(&ru0))));
} }
/* Revert back to the old phase information for error traceback */ /* Revert to the previous phase information for error traceback */
restore_vacuum_error_info(vacrelstats, &saved_err_info); restore_vacuum_error_info(vacrelstats, &saved_err_info);
pfree(vacrelstats->indname); pfree(vacrelstats->indname);
vacrelstats->indname = NULL; vacrelstats->indname = NULL;
...@@ -2964,6 +2991,7 @@ vac_cmp_itemptr(const void *left, const void *right) ...@@ -2964,6 +2991,7 @@ vac_cmp_itemptr(const void *left, const void *right)
*/ */
static bool static bool
heap_page_is_all_visible(Relation rel, Buffer buf, heap_page_is_all_visible(Relation rel, Buffer buf,
LVRelStats *vacrelstats,
TransactionId *visibility_cutoff_xid, TransactionId *visibility_cutoff_xid,
bool *all_frozen) bool *all_frozen)
{ {
...@@ -2988,6 +3016,11 @@ heap_page_is_all_visible(Relation rel, Buffer buf, ...@@ -2988,6 +3016,11 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
ItemId itemid; ItemId itemid;
HeapTupleData tuple; HeapTupleData tuple;
/*
* Set the offset number so that we can display it along with any
* error that occurred while processing this tuple.
*/
vacrelstats->offnum = offnum;
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
/* Unused or redirect line pointers are of no interest */ /* Unused or redirect line pointers are of no interest */
...@@ -3065,6 +3098,9 @@ heap_page_is_all_visible(Relation rel, Buffer buf, ...@@ -3065,6 +3098,9 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
} }
} /* scan along page */ } /* scan along page */
/* Clear the offset information once we have processed the given page. */
vacrelstats->offnum = InvalidOffsetNumber;
return all_visible; return all_visible;
} }
...@@ -3586,8 +3622,14 @@ vacuum_error_callback(void *arg) ...@@ -3586,8 +3622,14 @@ vacuum_error_callback(void *arg)
{ {
case VACUUM_ERRCB_PHASE_SCAN_HEAP: case VACUUM_ERRCB_PHASE_SCAN_HEAP:
if (BlockNumberIsValid(errinfo->blkno)) if (BlockNumberIsValid(errinfo->blkno))
errcontext("while scanning block %u of relation \"%s.%s\"", {
errinfo->blkno, errinfo->relnamespace, errinfo->relname); if (OffsetNumberIsValid(errinfo->offnum))
errcontext("while scanning block %u and offset %u of relation \"%s.%s\"",
errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname);
else
errcontext("while scanning block %u of relation \"%s.%s\"",
errinfo->blkno, errinfo->relnamespace, errinfo->relname);
}
else else
errcontext("while scanning relation \"%s.%s\"", errcontext("while scanning relation \"%s.%s\"",
errinfo->relnamespace, errinfo->relname); errinfo->relnamespace, errinfo->relname);
...@@ -3595,8 +3637,14 @@ vacuum_error_callback(void *arg) ...@@ -3595,8 +3637,14 @@ vacuum_error_callback(void *arg)
case VACUUM_ERRCB_PHASE_VACUUM_HEAP: case VACUUM_ERRCB_PHASE_VACUUM_HEAP:
if (BlockNumberIsValid(errinfo->blkno)) if (BlockNumberIsValid(errinfo->blkno))
errcontext("while vacuuming block %u of relation \"%s.%s\"", {
errinfo->blkno, errinfo->relnamespace, errinfo->relname); if (OffsetNumberIsValid(errinfo->offnum))
errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"",
errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname);
else
errcontext("while vacuuming block %u of relation \"%s.%s\"",
errinfo->blkno, errinfo->relnamespace, errinfo->relname);
}
else else
errcontext("while vacuuming relation \"%s.%s\"", errcontext("while vacuuming relation \"%s.%s\"",
errinfo->relnamespace, errinfo->relname); errinfo->relnamespace, errinfo->relname);
...@@ -3631,15 +3679,17 @@ vacuum_error_callback(void *arg) ...@@ -3631,15 +3679,17 @@ vacuum_error_callback(void *arg)
*/ */
static void static void
update_vacuum_error_info(LVRelStats *errinfo, LVSavedErrInfo *saved_err_info, int phase, update_vacuum_error_info(LVRelStats *errinfo, LVSavedErrInfo *saved_err_info, int phase,
BlockNumber blkno) BlockNumber blkno, OffsetNumber offnum)
{ {
if (saved_err_info) if (saved_err_info)
{ {
saved_err_info->offnum = errinfo->offnum;
saved_err_info->blkno = errinfo->blkno; saved_err_info->blkno = errinfo->blkno;
saved_err_info->phase = errinfo->phase; saved_err_info->phase = errinfo->phase;
} }
errinfo->blkno = blkno; errinfo->blkno = blkno;
errinfo->offnum = offnum;
errinfo->phase = phase; errinfo->phase = phase;
} }
...@@ -3650,5 +3700,6 @@ static void ...@@ -3650,5 +3700,6 @@ static void
restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedErrInfo *saved_err_info) restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedErrInfo *saved_err_info)
{ {
errinfo->blkno = saved_err_info->blkno; errinfo->blkno = saved_err_info->blkno;
errinfo->offnum = saved_err_info->offnum;
errinfo->phase = saved_err_info->phase; errinfo->phase = saved_err_info->phase;
} }
...@@ -178,7 +178,8 @@ extern int heap_page_prune(Relation relation, Buffer buffer, ...@@ -178,7 +178,8 @@ extern int heap_page_prune(Relation relation, Buffer buffer,
struct GlobalVisState *vistest, struct GlobalVisState *vistest,
TransactionId limited_oldest_xmin, TransactionId limited_oldest_xmin,
TimestampTz limited_oldest_ts, TimestampTz limited_oldest_ts,
bool report_stats, TransactionId *latestRemovedXid); bool report_stats, TransactionId *latestRemovedXid,
OffsetNumber *off_loc);
extern void heap_page_prune_execute(Buffer buffer, extern void heap_page_prune_execute(Buffer buffer,
OffsetNumber *redirected, int nredirected, OffsetNumber *redirected, int nredirected,
OffsetNumber *nowdead, int ndead, OffsetNumber *nowdead, int ndead,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment