@@ -316,13 +316,15 @@ typedef struct LVRelStats
316
316
/* Used for error callback */
317
317
char * indname ;
318
318
BlockNumber blkno ; /* used only for heap operations */
319
+ OffsetNumber offnum ; /* used only for heap operations */
319
320
VacErrPhase phase ;
320
321
} LVRelStats ;
321
322
322
323
/* Struct for saving and restoring vacuum error information. */
323
324
typedef struct LVSavedErrInfo
324
325
{
325
326
BlockNumber blkno ;
327
+ OffsetNumber offnum ;
326
328
VacErrPhase phase ;
327
329
} LVSavedErrInfo ;
328
330
@@ -341,7 +343,8 @@ static void lazy_scan_heap(Relation onerel, VacuumParams *params,
341
343
LVRelStats * vacrelstats , Relation * Irel , int nindexes ,
342
344
bool aggressive );
343
345
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 );
345
348
static void lazy_vacuum_all_indexes (Relation onerel , Relation * Irel ,
346
349
IndexBulkDeleteResult * * stats ,
347
350
LVRelStats * vacrelstats , LVParallelState * lps ,
@@ -364,6 +367,7 @@ static void lazy_record_dead_tuple(LVDeadTuples *dead_tuples,
364
367
static bool lazy_tid_reaped (ItemPointer itemptr , void * state );
365
368
static int vac_cmp_itemptr (const void * left , const void * right );
366
369
static bool heap_page_is_all_visible (Relation rel , Buffer buf ,
370
+ LVRelStats * vacrelstats ,
367
371
TransactionId * visibility_cutoff_xid , bool * all_frozen );
368
372
static void lazy_parallel_vacuum_indexes (Relation * Irel , IndexBulkDeleteResult * * stats ,
369
373
LVRelStats * vacrelstats , LVParallelState * lps ,
@@ -396,7 +400,8 @@ static LVSharedIndStats *get_indstats(LVShared *lvshared, int n);
396
400
static bool skip_parallel_vacuum_index (Relation indrel , LVShared * lvshared );
397
401
static void vacuum_error_callback (void * arg );
398
402
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 );
400
405
static void restore_vacuum_error_info (LVRelStats * errinfo , const LVSavedErrInfo * saved_err_info );
401
406
402
407
@@ -547,7 +552,8 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
547
552
* revert to the previous phase.
548
553
*/
549
554
update_vacuum_error_info (vacrelstats , NULL , VACUUM_ERRCB_PHASE_TRUNCATE ,
550
- vacrelstats -> nonempty_pages );
555
+ vacrelstats -> nonempty_pages ,
556
+ InvalidOffsetNumber );
551
557
lazy_truncate_heap (onerel , vacrelstats );
552
558
}
553
559
@@ -960,7 +966,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
960
966
pgstat_progress_update_param (PROGRESS_VACUUM_HEAP_BLKS_SCANNED , blkno );
961
967
962
968
update_vacuum_error_info (vacrelstats , NULL , VACUUM_ERRCB_PHASE_SCAN_HEAP ,
963
- blkno );
969
+ blkno , InvalidOffsetNumber );
964
970
965
971
if (blkno == next_unskippable_block )
966
972
{
@@ -1129,7 +1135,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
1129
1135
* to use lazy_check_needs_freeze() for both situations, though.
1130
1136
*/
1131
1137
LockBuffer (buf , BUFFER_LOCK_SHARE );
1132
- if (!lazy_check_needs_freeze (buf , & hastup ))
1138
+ if (!lazy_check_needs_freeze (buf , & hastup , vacrelstats ))
1133
1139
{
1134
1140
UnlockReleaseBuffer (buf );
1135
1141
vacrelstats -> scanned_pages ++ ;
@@ -1244,7 +1250,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
1244
1250
*/
1245
1251
tups_vacuumed += heap_page_prune (onerel , buf , vistest , false,
1246
1252
InvalidTransactionId , 0 ,
1247
- & vacrelstats -> latestRemovedXid );
1253
+ & vacrelstats -> latestRemovedXid ,
1254
+ & vacrelstats -> offnum );
1248
1255
1249
1256
/*
1250
1257
* 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
1274
{
1268
1275
ItemId itemid ;
1269
1276
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 ;
1270
1282
itemid = PageGetItemId (page , offnum );
1271
1283
1272
1284
/* Unused items require no processing, but we count 'em */
@@ -1468,6 +1480,12 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
1468
1480
}
1469
1481
} /* scan along page */
1470
1482
1483
+ /*
1484
+ * Clear the offset information once we have processed all the tuples
1485
+ * on the page.
1486
+ */
1487
+ vacrelstats -> offnum = InvalidOffsetNumber ;
1488
+
1471
1489
/*
1472
1490
* If we froze any tuples, mark the buffer dirty, and write a WAL
1473
1491
* record recording the changes. We must log the changes to be
@@ -1845,7 +1863,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats)
1845
1863
1846
1864
/* Update error traceback information */
1847
1865
update_vacuum_error_info (vacrelstats , & saved_err_info , VACUUM_ERRCB_PHASE_VACUUM_HEAP ,
1848
- InvalidBlockNumber );
1866
+ InvalidBlockNumber , InvalidOffsetNumber );
1849
1867
1850
1868
pg_rusage_init (& ru0 );
1851
1869
npages = 0 ;
@@ -1927,7 +1945,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
1927
1945
1928
1946
/* Update error traceback information */
1929
1947
update_vacuum_error_info (vacrelstats , & saved_err_info , VACUUM_ERRCB_PHASE_VACUUM_HEAP ,
1930
- blkno );
1948
+ blkno , InvalidOffsetNumber );
1931
1949
1932
1950
START_CRIT_SECTION ();
1933
1951
@@ -1979,7 +1997,8 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
1979
1997
* dirty, exclusively locked, and, if needed, a full page image has been
1980
1998
* emitted in the log_heap_clean() above.
1981
1999
*/
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 ,
1983
2002
& all_frozen ))
1984
2003
PageSetAllVisible (page );
1985
2004
@@ -2018,7 +2037,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
2018
2037
* Also returns a flag indicating whether page contains any tuples at all.
2019
2038
*/
2020
2039
static bool
2021
- lazy_check_needs_freeze (Buffer buf , bool * hastup )
2040
+ lazy_check_needs_freeze (Buffer buf , bool * hastup , LVRelStats * vacrelstats )
2022
2041
{
2023
2042
Page page = BufferGetPage (buf );
2024
2043
OffsetNumber offnum ,
@@ -2043,6 +2062,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
2043
2062
{
2044
2063
ItemId itemid ;
2045
2064
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 ;
2046
2070
itemid = PageGetItemId (page , offnum );
2047
2071
2048
2072
/* this should match hastup test in count_nondeletable_pages() */
@@ -2057,10 +2081,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
2057
2081
2058
2082
if (heap_tuple_needs_freeze (tupleheader , FreezeLimit ,
2059
2083
MultiXactCutoff , buf ))
2060
- return true ;
2084
+ break ;
2061
2085
} /* scan along page */
2062
2086
2063
- return false;
2087
+ /* Clear the offset information once we have processed the given page. */
2088
+ vacrelstats -> offnum = InvalidOffsetNumber ;
2089
+
2090
+ return (offnum <= maxoff );
2064
2091
}
2065
2092
2066
2093
/*
@@ -2438,7 +2465,7 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats,
2438
2465
vacrelstats -> indname = pstrdup (RelationGetRelationName (indrel ));
2439
2466
update_vacuum_error_info (vacrelstats , & saved_err_info ,
2440
2467
VACUUM_ERRCB_PHASE_VACUUM_INDEX ,
2441
- InvalidBlockNumber );
2468
+ InvalidBlockNumber , InvalidOffsetNumber );
2442
2469
2443
2470
/* Do bulk deletion */
2444
2471
* stats = index_bulk_delete (& ivinfo , * stats ,
@@ -2498,7 +2525,7 @@ lazy_cleanup_index(Relation indrel,
2498
2525
vacrelstats -> indname = pstrdup (RelationGetRelationName (indrel ));
2499
2526
update_vacuum_error_info (vacrelstats , & saved_err_info ,
2500
2527
VACUUM_ERRCB_PHASE_INDEX_CLEANUP ,
2501
- InvalidBlockNumber );
2528
+ InvalidBlockNumber , InvalidOffsetNumber );
2502
2529
2503
2530
* stats = index_vacuum_cleanup (& ivinfo , * stats );
2504
2531
@@ -2522,7 +2549,7 @@ lazy_cleanup_index(Relation indrel,
2522
2549
pg_rusage_show (& ru0 ))));
2523
2550
}
2524
2551
2525
- /* Revert back to the old phase information for error traceback */
2552
+ /* Revert to the previous phase information for error traceback */
2526
2553
restore_vacuum_error_info (vacrelstats , & saved_err_info );
2527
2554
pfree (vacrelstats -> indname );
2528
2555
vacrelstats -> indname = NULL ;
@@ -2964,6 +2991,7 @@ vac_cmp_itemptr(const void *left, const void *right)
2964
2991
*/
2965
2992
static bool
2966
2993
heap_page_is_all_visible (Relation rel , Buffer buf ,
2994
+ LVRelStats * vacrelstats ,
2967
2995
TransactionId * visibility_cutoff_xid ,
2968
2996
bool * all_frozen )
2969
2997
{
@@ -2988,6 +3016,11 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
2988
3016
ItemId itemid ;
2989
3017
HeapTupleData tuple ;
2990
3018
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 ;
2991
3024
itemid = PageGetItemId (page , offnum );
2992
3025
2993
3026
/* Unused or redirect line pointers are of no interest */
@@ -3065,6 +3098,9 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
3065
3098
}
3066
3099
} /* scan along page */
3067
3100
3101
+ /* Clear the offset information once we have processed the given page. */
3102
+ vacrelstats -> offnum = InvalidOffsetNumber ;
3103
+
3068
3104
return all_visible ;
3069
3105
}
3070
3106
@@ -3586,17 +3622,29 @@ vacuum_error_callback(void *arg)
3586
3622
{
3587
3623
case VACUUM_ERRCB_PHASE_SCAN_HEAP :
3588
3624
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
+ }
3591
3633
else
3592
3634
errcontext ("while scanning relation \"%s.%s\"" ,
3593
3635
errinfo -> relnamespace , errinfo -> relname );
3594
3636
break ;
3595
3637
3596
3638
case VACUUM_ERRCB_PHASE_VACUUM_HEAP :
3597
3639
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
+ }
3600
3648
else
3601
3649
errcontext ("while vacuuming relation \"%s.%s\"" ,
3602
3650
errinfo -> relnamespace , errinfo -> relname );
@@ -3631,15 +3679,17 @@ vacuum_error_callback(void *arg)
3631
3679
*/
3632
3680
static void
3633
3681
update_vacuum_error_info (LVRelStats * errinfo , LVSavedErrInfo * saved_err_info , int phase ,
3634
- BlockNumber blkno )
3682
+ BlockNumber blkno , OffsetNumber offnum )
3635
3683
{
3636
3684
if (saved_err_info )
3637
3685
{
3686
+ saved_err_info -> offnum = errinfo -> offnum ;
3638
3687
saved_err_info -> blkno = errinfo -> blkno ;
3639
3688
saved_err_info -> phase = errinfo -> phase ;
3640
3689
}
3641
3690
3642
3691
errinfo -> blkno = blkno ;
3692
+ errinfo -> offnum = offnum ;
3643
3693
errinfo -> phase = phase ;
3644
3694
}
3645
3695
@@ -3650,5 +3700,6 @@ static void
3650
3700
restore_vacuum_error_info (LVRelStats * errinfo , const LVSavedErrInfo * saved_err_info )
3651
3701
{
3652
3702
errinfo -> blkno = saved_err_info -> blkno ;
3703
+ errinfo -> offnum = saved_err_info -> offnum ;
3653
3704
errinfo -> phase = saved_err_info -> phase ;
3654
3705
}
0 commit comments