@@ -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. */
323324typedef 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 );
343345static 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 );
345348static 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,
364367static bool lazy_tid_reaped (ItemPointer itemptr , void * state );
365368static int vac_cmp_itemptr (const void * left , const void * right );
366369static bool heap_page_is_all_visible (Relation rel , Buffer buf ,
370+ LVRelStats * vacrelstats ,
367371 TransactionId * visibility_cutoff_xid , bool * all_frozen );
368372static 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);
396400static bool skip_parallel_vacuum_index (Relation indrel , LVShared * lvshared );
397401static void vacuum_error_callback (void * arg );
398402static void update_vacuum_error_info (LVRelStats * errinfo , LVSavedErrInfo * saved_err_info ,
399- int phase , BlockNumber blkno );
403+ int phase , BlockNumber blkno ,
404+ OffsetNumber offnum );
400405static 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 */
20202039static 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 */
29652992static bool
29662993heap_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 */
36323680static void
36333681update_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
36503700restore_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}
0 commit comments