Re: error context for vacuum to include block number
Andres Freund <andres@anarazel.de>
From: Andres Freund <andres@anarazel.de>
To: Justin Pryzby <pryzby@telsasoft.com>
Cc: Michael Paquier <michael@paquier.xyz>, pgsql-hackers@postgresql.org
Date: 2019-12-11T16:54:25Z
Lists: pgsql-hackers
Hi,
Thanks for working on this!
On 2019-12-11 08:36:48 -0600, Justin Pryzby wrote:
> On Wed, Dec 11, 2019 at 09:15:07PM +0900, Michael Paquier wrote:
> > On Fri, Dec 06, 2019 at 10:23:25AM -0600, Justin Pryzby wrote:
> > > Find attached updated patch:
> > > . Use structure to include relation name.
> > > . Split into a separate patch rename of "StringInfoData buf".
> > >
> > > 2019-11-27 20:04:53.640 CST [14244] ERROR: canceling statement due to statement timeout
> > > 2019-11-27 20:04:53.640 CST [14244] CONTEXT: block 2314 of relation t
> > > 2019-11-27 20:04:53.640 CST [14244] STATEMENT: vacuum t;
> > >
> > > I tried to use BufferGetTag() to avoid using a 2ndary structure, but fails if
> > > the buffer is not pinned.
The tag will not add all that informative details, because the
relfilenode isn't easily mappable to the table name or such.
> diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
> index 043ebb4..9376989 100644
> --- a/src/backend/access/heap/vacuumlazy.c
> +++ b/src/backend/access/heap/vacuumlazy.c
> @@ -138,6 +138,12 @@ typedef struct LVRelStats
> bool lock_waiter_detected;
> } LVRelStats;
>
> +typedef struct
> +{
> + char *relname;
> + char *relnamespace;
> + BlockNumber blkno;
> +} vacuum_error_callback_arg;
Hm, wonder if could be worthwhile to not use a separate struct here, but
instead extend one of the existing structs to contain the necessary
information. Or perhaps have one new struct with all the necessary
information. There's already quite a few places that do
get_namespace_name(), for example.
> @@ -524,6 +531,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
> PROGRESS_VACUUM_MAX_DEAD_TUPLES
> };
> int64 initprog_val[3];
> + ErrorContextCallback errcallback;
> + vacuum_error_callback_arg cbarg;
Not a fan of "cbarg", too generic.
> pg_rusage_init(&ru0);
>
> @@ -635,6 +644,15 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
> else
> skipping_blocks = false;
>
> + /* Setup error traceback support for ereport() */
> + errcallback.callback = vacuum_error_callback;
> + cbarg.relname = relname;
> + cbarg.relnamespace = get_namespace_name(RelationGetNamespace(onerel));
> + cbarg.blkno = 0; /* Not known yet */
> + errcallback.arg = (void *) &cbarg;
> + errcallback.previous = error_context_stack;
> + error_context_stack = &errcallback;
> +
> for (blkno = 0; blkno < nblocks; blkno++)
> {
> Buffer buf;
> @@ -658,6 +676,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
>
> pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno);
>
> + cbarg.blkno = blkno;
> +
> if (blkno == next_unskippable_block)
> {
> /* Time to advance next_unskippable_block */
> @@ -817,7 +837,6 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
>
> buf = ReadBufferExtended(onerel, MAIN_FORKNUM, blkno,
> RBM_NORMAL, vac_strategy);
> -
> /* We need buffer cleanup lock so that we can prune HOT chains. */
> if (!ConditionalLockBufferForCleanup(buf))
> {
> @@ -1388,6 +1407,9 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
> RecordPageWithFreeSpace(onerel, blkno, freespace);
> }
>
> + /* Pop the error context stack */
> + error_context_stack = errcallback.previous;
> +
> /* report that everything is scanned and vacuumed */
> pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno);
>
> @@ -2354,3 +2376,15 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
>
> return all_visible;
> }
I think this will misattribute errors that happen when in the:
/*
* If we are close to overrunning the available space for dead-tuple
* TIDs, pause and do a cycle of vacuuming before we tackle this page.
*/
section of lazy_scan_heap(). That will
a) scan the index, during which we presumably don't want the same error
context, as it'd be quite misleading: The block that was just scanned
in the loop isn't actually likely to be the culprit for an index
problem. And we'd not mention the fact that the problem is occurring
in the index.
b) will report the wrong block, when in lazy_vacuum_heap().
Greetings,
Andres Freund
Commits
-
Avoid calls to RelationGetRelationName() and RelationGetNamespace() in
- ef75140fe756 13.0 landed
-
Introduce vacuum errcontext to display additional information.
- b61d161c1463 13.0 landed
-
Fix mesurement of elapsed time during truncating heap in VACUUM.
- 007491979461 13.0 cited
-
Allow vacuum command to process indexes in parallel.
- 40d964ec997f 13.0 cited
-
Refactor code dedicated to index vacuuming in vacuumlazy.c
- 1ab41a3c8edc 13.0 landed
-
Remove duplicated progress reporting during heap scan of VACUUM
- e5a02e0fc68b 13.0 landed