Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7e45363

Browse files
author
Amit Kapila
committed
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
1 parent 808e13b commit 7e45363

File tree

3 files changed

+90
-23
lines changed

3 files changed

+90
-23
lines changed

src/backend/access/heap/pruneheap.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
188188
/* OK to prune */
189189
(void) heap_page_prune(relation, buffer, vistest,
190190
limited_xmin, limited_ts,
191-
true, &ignore);
191+
true, &ignore, NULL);
192192
}
193193

194194
/* And release buffer lock */
@@ -213,6 +213,9 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
213213
* send its own new total to pgstats, and we don't want this delta applied
214214
* on top of that.)
215215
*
216+
* off_loc is the offset location required by the caller to use in error
217+
* callback.
218+
*
216219
* Returns the number of tuples deleted from the page and sets
217220
* latestRemovedXid.
218221
*/
@@ -221,7 +224,8 @@ heap_page_prune(Relation relation, Buffer buffer,
221224
GlobalVisState *vistest,
222225
TransactionId old_snap_xmin,
223226
TimestampTz old_snap_ts,
224-
bool report_stats, TransactionId *latestRemovedXid)
227+
bool report_stats, TransactionId *latestRemovedXid,
228+
OffsetNumber *off_loc)
225229
{
226230
int ndeleted = 0;
227231
Page page = BufferGetPage(buffer);
@@ -262,6 +266,13 @@ heap_page_prune(Relation relation, Buffer buffer,
262266
if (prstate.marked[offnum])
263267
continue;
264268

269+
/*
270+
* Set the offset number so that we can display it along with any
271+
* error that occurred while processing this tuple.
272+
*/
273+
if (off_loc)
274+
*off_loc = offnum;
275+
265276
/* Nothing to do if slot is empty or already dead */
266277
itemid = PageGetItemId(page, offnum);
267278
if (!ItemIdIsUsed(itemid) || ItemIdIsDead(itemid))
@@ -271,6 +282,10 @@ heap_page_prune(Relation relation, Buffer buffer,
271282
ndeleted += heap_prune_chain(buffer, offnum, &prstate);
272283
}
273284

285+
/* Clear the offset information once we have processed the given page. */
286+
if (off_loc)
287+
*off_loc = InvalidOffsetNumber;
288+
274289
/* Any error while applying the changes is critical */
275290
START_CRIT_SECTION();
276291

src/backend/access/heap/vacuumlazy.c

+71-20
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,15 @@ typedef struct LVRelStats
316316
/* Used for error callback */
317317
char *indname;
318318
BlockNumber blkno; /* used only for heap operations */
319+
OffsetNumber offnum; /* used only for heap operations */
319320
VacErrPhase phase;
320321
} LVRelStats;
321322

322323
/* Struct for saving and restoring vacuum error information. */
323324
typedef struct LVSavedErrInfo
324325
{
325326
BlockNumber blkno;
327+
OffsetNumber offnum;
326328
VacErrPhase phase;
327329
} LVSavedErrInfo;
328330

@@ -341,7 +343,8 @@ static void lazy_scan_heap(Relation onerel, VacuumParams *params,
341343
LVRelStats *vacrelstats, Relation *Irel, int nindexes,
342344
bool aggressive);
343345
static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
344-
static bool lazy_check_needs_freeze(Buffer buf, bool *hastup);
346+
static bool lazy_check_needs_freeze(Buffer buf, bool *hastup,
347+
LVRelStats *vacrelstats);
345348
static void lazy_vacuum_all_indexes(Relation onerel, Relation *Irel,
346349
IndexBulkDeleteResult **stats,
347350
LVRelStats *vacrelstats, LVParallelState *lps,
@@ -364,6 +367,7 @@ static void lazy_record_dead_tuple(LVDeadTuples *dead_tuples,
364367
static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
365368
static int vac_cmp_itemptr(const void *left, const void *right);
366369
static bool heap_page_is_all_visible(Relation rel, Buffer buf,
370+
LVRelStats *vacrelstats,
367371
TransactionId *visibility_cutoff_xid, bool *all_frozen);
368372
static void lazy_parallel_vacuum_indexes(Relation *Irel, IndexBulkDeleteResult **stats,
369373
LVRelStats *vacrelstats, LVParallelState *lps,
@@ -396,7 +400,8 @@ static LVSharedIndStats *get_indstats(LVShared *lvshared, int n);
396400
static bool skip_parallel_vacuum_index(Relation indrel, LVShared *lvshared);
397401
static void vacuum_error_callback(void *arg);
398402
static void update_vacuum_error_info(LVRelStats *errinfo, LVSavedErrInfo *saved_err_info,
399-
int phase, BlockNumber blkno);
403+
int phase, BlockNumber blkno,
404+
OffsetNumber offnum);
400405
static void restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedErrInfo *saved_err_info);
401406

402407

@@ -547,7 +552,8 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
547552
* revert to the previous phase.
548553
*/
549554
update_vacuum_error_info(vacrelstats, NULL, VACUUM_ERRCB_PHASE_TRUNCATE,
550-
vacrelstats->nonempty_pages);
555+
vacrelstats->nonempty_pages,
556+
InvalidOffsetNumber);
551557
lazy_truncate_heap(onerel, vacrelstats);
552558
}
553559

@@ -960,7 +966,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
960966
pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno);
961967

962968
update_vacuum_error_info(vacrelstats, NULL, VACUUM_ERRCB_PHASE_SCAN_HEAP,
963-
blkno);
969+
blkno, InvalidOffsetNumber);
964970

965971
if (blkno == next_unskippable_block)
966972
{
@@ -1129,7 +1135,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
11291135
* to use lazy_check_needs_freeze() for both situations, though.
11301136
*/
11311137
LockBuffer(buf, BUFFER_LOCK_SHARE);
1132-
if (!lazy_check_needs_freeze(buf, &hastup))
1138+
if (!lazy_check_needs_freeze(buf, &hastup, vacrelstats))
11331139
{
11341140
UnlockReleaseBuffer(buf);
11351141
vacrelstats->scanned_pages++;
@@ -1244,7 +1250,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
12441250
*/
12451251
tups_vacuumed += heap_page_prune(onerel, buf, vistest, false,
12461252
InvalidTransactionId, 0,
1247-
&vacrelstats->latestRemovedXid);
1253+
&vacrelstats->latestRemovedXid,
1254+
&vacrelstats->offnum);
12481255

12491256
/*
12501257
* 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,
12671274
{
12681275
ItemId itemid;
12691276

1277+
/*
1278+
* Set the offset number so that we can display it along with any
1279+
* error that occurred while processing this tuple.
1280+
*/
1281+
vacrelstats->offnum = offnum;
12701282
itemid = PageGetItemId(page, offnum);
12711283

12721284
/* Unused items require no processing, but we count 'em */
@@ -1468,6 +1480,12 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
14681480
}
14691481
} /* scan along page */
14701482

1483+
/*
1484+
* Clear the offset information once we have processed all the tuples
1485+
* on the page.
1486+
*/
1487+
vacrelstats->offnum = InvalidOffsetNumber;
1488+
14711489
/*
14721490
* If we froze any tuples, mark the buffer dirty, and write a WAL
14731491
* record recording the changes. We must log the changes to be
@@ -1845,7 +1863,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
18451863

18461864
/* Update error traceback information */
18471865
update_vacuum_error_info(vacrelstats, &saved_err_info, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
1848-
InvalidBlockNumber);
1866+
InvalidBlockNumber, InvalidOffsetNumber);
18491867

18501868
pg_rusage_init(&ru0);
18511869
npages = 0;
@@ -1927,7 +1945,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
19271945

19281946
/* Update error traceback information */
19291947
update_vacuum_error_info(vacrelstats, &saved_err_info, VACUUM_ERRCB_PHASE_VACUUM_HEAP,
1930-
blkno);
1948+
blkno, InvalidOffsetNumber);
19311949

19321950
START_CRIT_SECTION();
19331951

@@ -1979,7 +1997,8 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
19791997
* dirty, exclusively locked, and, if needed, a full page image has been
19801998
* emitted in the log_heap_clean() above.
19811999
*/
1982-
if (heap_page_is_all_visible(onerel, buffer, &visibility_cutoff_xid,
2000+
if (heap_page_is_all_visible(onerel, buffer, vacrelstats,
2001+
&visibility_cutoff_xid,
19832002
&all_frozen))
19842003
PageSetAllVisible(page);
19852004

@@ -2018,7 +2037,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
20182037
* Also returns a flag indicating whether page contains any tuples at all.
20192038
*/
20202039
static bool
2021-
lazy_check_needs_freeze(Buffer buf, bool *hastup)
2040+
lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats)
20222041
{
20232042
Page page = BufferGetPage(buf);
20242043
OffsetNumber offnum,
@@ -2043,6 +2062,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
20432062
{
20442063
ItemId itemid;
20452064

2065+
/*
2066+
* Set the offset number so that we can display it along with any
2067+
* error that occurred while processing this tuple.
2068+
*/
2069+
vacrelstats->offnum = offnum;
20462070
itemid = PageGetItemId(page, offnum);
20472071

20482072
/* this should match hastup test in count_nondeletable_pages() */
@@ -2057,10 +2081,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
20572081

20582082
if (heap_tuple_needs_freeze(tupleheader, FreezeLimit,
20592083
MultiXactCutoff, buf))
2060-
return true;
2084+
break;
20612085
} /* scan along page */
20622086

2063-
return false;
2087+
/* Clear the offset information once we have processed the given page. */
2088+
vacrelstats->offnum = InvalidOffsetNumber;
2089+
2090+
return (offnum <= maxoff);
20642091
}
20652092

20662093
/*
@@ -2438,7 +2465,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
24382465
vacrelstats->indname = pstrdup(RelationGetRelationName(indrel));
24392466
update_vacuum_error_info(vacrelstats, &saved_err_info,
24402467
VACUUM_ERRCB_PHASE_VACUUM_INDEX,
2441-
InvalidBlockNumber);
2468+
InvalidBlockNumber, InvalidOffsetNumber);
24422469

24432470
/* Do bulk deletion */
24442471
*stats = index_bulk_delete(&ivinfo, *stats,
@@ -2498,7 +2525,7 @@ lazy_cleanup_index(Relation indrel,
24982525
vacrelstats->indname = pstrdup(RelationGetRelationName(indrel));
24992526
update_vacuum_error_info(vacrelstats, &saved_err_info,
25002527
VACUUM_ERRCB_PHASE_INDEX_CLEANUP,
2501-
InvalidBlockNumber);
2528+
InvalidBlockNumber, InvalidOffsetNumber);
25022529

25032530
*stats = index_vacuum_cleanup(&ivinfo, *stats);
25042531

@@ -2522,7 +2549,7 @@ lazy_cleanup_index(Relation indrel,
25222549
pg_rusage_show(&ru0))));
25232550
}
25242551

2525-
/* Revert back to the old phase information for error traceback */
2552+
/* Revert to the previous phase information for error traceback */
25262553
restore_vacuum_error_info(vacrelstats, &saved_err_info);
25272554
pfree(vacrelstats->indname);
25282555
vacrelstats->indname = NULL;
@@ -2964,6 +2991,7 @@ vac_cmp_itemptr(const void *left, const void *right)
29642991
*/
29652992
static bool
29662993
heap_page_is_all_visible(Relation rel, Buffer buf,
2994+
LVRelStats *vacrelstats,
29672995
TransactionId *visibility_cutoff_xid,
29682996
bool *all_frozen)
29692997
{
@@ -2988,6 +3016,11 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
29883016
ItemId itemid;
29893017
HeapTupleData tuple;
29903018

3019+
/*
3020+
* Set the offset number so that we can display it along with any
3021+
* error that occurred while processing this tuple.
3022+
*/
3023+
vacrelstats->offnum = offnum;
29913024
itemid = PageGetItemId(page, offnum);
29923025

29933026
/* Unused or redirect line pointers are of no interest */
@@ -3065,6 +3098,9 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
30653098
}
30663099
} /* scan along page */
30673100

3101+
/* Clear the offset information once we have processed the given page. */
3102+
vacrelstats->offnum = InvalidOffsetNumber;
3103+
30683104
return all_visible;
30693105
}
30703106

@@ -3586,17 +3622,29 @@ vacuum_error_callback(void *arg)
35863622
{
35873623
case VACUUM_ERRCB_PHASE_SCAN_HEAP:
35883624
if (BlockNumberIsValid(errinfo->blkno))
3589-
errcontext("while scanning block %u of relation \"%s.%s\"",
3590-
errinfo->blkno, errinfo->relnamespace, errinfo->relname);
3625+
{
3626+
if (OffsetNumberIsValid(errinfo->offnum))
3627+
errcontext("while scanning block %u and offset %u of relation \"%s.%s\"",
3628+
errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname);
3629+
else
3630+
errcontext("while scanning block %u of relation \"%s.%s\"",
3631+
errinfo->blkno, errinfo->relnamespace, errinfo->relname);
3632+
}
35913633
else
35923634
errcontext("while scanning relation \"%s.%s\"",
35933635
errinfo->relnamespace, errinfo->relname);
35943636
break;
35953637

35963638
case VACUUM_ERRCB_PHASE_VACUUM_HEAP:
35973639
if (BlockNumberIsValid(errinfo->blkno))
3598-
errcontext("while vacuuming block %u of relation \"%s.%s\"",
3599-
errinfo->blkno, errinfo->relnamespace, errinfo->relname);
3640+
{
3641+
if (OffsetNumberIsValid(errinfo->offnum))
3642+
errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"",
3643+
errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname);
3644+
else
3645+
errcontext("while vacuuming block %u of relation \"%s.%s\"",
3646+
errinfo->blkno, errinfo->relnamespace, errinfo->relname);
3647+
}
36003648
else
36013649
errcontext("while vacuuming relation \"%s.%s\"",
36023650
errinfo->relnamespace, errinfo->relname);
@@ -3631,15 +3679,17 @@ vacuum_error_callback(void *arg)
36313679
*/
36323680
static void
36333681
update_vacuum_error_info(LVRelStats *errinfo, LVSavedErrInfo *saved_err_info, int phase,
3634-
BlockNumber blkno)
3682+
BlockNumber blkno, OffsetNumber offnum)
36353683
{
36363684
if (saved_err_info)
36373685
{
3686+
saved_err_info->offnum = errinfo->offnum;
36383687
saved_err_info->blkno = errinfo->blkno;
36393688
saved_err_info->phase = errinfo->phase;
36403689
}
36413690

36423691
errinfo->blkno = blkno;
3692+
errinfo->offnum = offnum;
36433693
errinfo->phase = phase;
36443694
}
36453695

@@ -3650,5 +3700,6 @@ static void
36503700
restore_vacuum_error_info(LVRelStats *errinfo, const LVSavedErrInfo *saved_err_info)
36513701
{
36523702
errinfo->blkno = saved_err_info->blkno;
3703+
errinfo->offnum = saved_err_info->offnum;
36533704
errinfo->phase = saved_err_info->phase;
36543705
}

src/include/access/heapam.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ extern int heap_page_prune(Relation relation, Buffer buffer,
178178
struct GlobalVisState *vistest,
179179
TransactionId limited_oldest_xmin,
180180
TimestampTz limited_oldest_ts,
181-
bool report_stats, TransactionId *latestRemovedXid);
181+
bool report_stats, TransactionId *latestRemovedXid,
182+
OffsetNumber *off_loc);
182183
extern void heap_page_prune_execute(Buffer buffer,
183184
OffsetNumber *redirected, int nredirected,
184185
OffsetNumber *nowdead, int ndead,

0 commit comments

Comments
 (0)