Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1j2cyz-0002ur-5p for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Feb 2020 15:34:21 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1j2cyx-0002SU-W9 for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Feb 2020 15:34:19 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1j2cyx-0002SL-Ix for pgsql-hackers@lists.postgresql.org; Fri, 14 Feb 2020 15:34:19 +0000 Received: from mail-yb1-xb41.google.com ([2607:f8b0:4864:20::b41]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1j2cyv-0001jK-Cv for pgsql-hackers@postgresql.org; Fri, 14 Feb 2020 15:34:19 +0000 Received: by mail-yb1-xb41.google.com with SMTP id f21so4922739ybg.11 for ; Fri, 14 Feb 2020 07:34:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=7zN23i5ZBo64+r8mfr2j2JejFnjXr+jGpUN78TVDWPs=; b=hAEM0NTrgRyamtuBOJjjq6TbHN9LmEnhCcIentCPHVzKTVMQCrU8pSbA7UI9l9+fFo J0smP4/G4KZ4RgG2CZ8ywiukIlElNwSSipxKIo/gmXzZdauugFTx3wdOG+qGl9HKLKbi JqX5BLREylwS+w0vLfyzMJnlrOhJcPWilbMKOoWw3FM2McwQOfifV54DgTlgdDn7bJ9b 0KqFFczztoQoiytAkACVx6+2ZTEd1Qex5R0yZ8pCE7KXO7BRMdeQbEo8k7rLmrsWi6EK amDGMpu5Ibw0XqlHM+B0cZs9twVS+yb17o9+oKHU8CejvUAdttv2GdW95J0LI82skUm5 cfAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=7zN23i5ZBo64+r8mfr2j2JejFnjXr+jGpUN78TVDWPs=; b=CaD2IoePXi8PhpO3I/QNfsrZF6uY6LdkZrshm7jnxYc1OyQuOP/b9joNHxeO9/QM5H dDp9F4R6woRy2gcBceYibxqf7hJ0tpshc5bcqGwmVhNBoc1Ec10wL3YuzrbsoHYkHlea O7RbF9AgDLFtNomYi3Fp4pO6tBkQV1gDXgQKKXb1Q44W8QCUilpGzuvhhSA3QoVAiZN+ V4I/ZWcmDrswEOrP6PXxZXhqesHUeXRvPuANBz9OhFngMTlVD2X09ORizl555NSc/RGS D3awXkSiR0z4WTcD2kOkmceqC3LODq7I6z5oryE6Aj1nZjF91e1euwDfRhPLIJCA52ZC 6xtQ== X-Gm-Message-State: APjAAAXtgs7PyJgtDeZuOfgfpURqOZTOiGJLq4Ylh/nVMAbweKAxRWXg 3aTXMjqwiPQky0G+J2OuOw24YA== X-Google-Smtp-Source: APXvYqxTsa+6tnoIImKMtVWGueef3ibO6wbp+lz7DDnAay8nbNTBN+DiexOIom9Lq+CTLBOoFHD75A== X-Received: by 2002:a25:d912:: with SMTP id q18mr3276735ybg.370.1581694455902; Fri, 14 Feb 2020 07:34:15 -0800 (PST) Received: from pryzbyj (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id q185sm2786533ywh.61.2020.02.14.07.34.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Feb 2020 07:34:14 -0800 (PST) Received: by pryzbyj (Postfix, from userid 1000) id B6716800897; Fri, 14 Feb 2020 09:34:12 -0600 (CST) Date: Fri, 14 Feb 2020 09:34:12 -0600 From: Justin Pryzby To: Masahiko Sawada Cc: Andres Freund , Michael Paquier , Alvaro Herrera , pgsql-hackers@postgresql.org Subject: Re: error context for vacuum to include block number Message-ID: <20200214153412.GD31889@telsasoft.com> References: <20200127053813.GS13621@telsasoft.com> <20200127225018.GY13621@telsasoft.com> <20200202060259.GG13621@telsasoft.com> <20200208010107.GT403@telsasoft.com> <20200213235254.GC31889@telsasoft.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="E/DnYTRukya0zdZ1" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --E/DnYTRukya0zdZ1 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Feb 14, 2020 at 12:30:25PM +0900, Masahiko Sawada wrote: > * I think the function name is too generic. init_vacuum_error_callback > or init_vacuum_errcallback is better. > * The comment of this function is not accurate since this function is > not only for heap vacuum but also index vacuum. How about just > "Initialize vacuum error callback"? > * I think it's easier to read the code if we set the relname and > indname in the same order. > * The comment I wrote in the previous mail seems better, because in > this function the reader might get confused that 'rel' is a relation > or an index depending on the phase but that comment helps it. Fixed these > * rel->rd_index->indexrelid should be rel->rd_index->indrelid. Ack. I think that's been wrong since I first wrote it two weeks ago :( The error is probably more obvious due to the switch statement you proposed. Thanks for continued reviews. -- Justin --E/DnYTRukya0zdZ1 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v19-0001-vacuum-errcontext-to-show-block-being-processed.patch" From 94768a134118d30853b75a96b90166363f0fef5b Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Thu, 12 Dec 2019 20:54:37 -0600 Subject: [PATCH v19] vacuum errcontext to show block being processed Discussion: https://www.postgresql.org/message-id/20191120210600.GC30362@telsasoft.com --- src/backend/access/heap/vacuumlazy.c | 120 +++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index a23cdef..ebfb2e7 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -292,6 +292,14 @@ typedef struct LVRelStats bool lock_waiter_detected; } LVRelStats; +typedef struct +{ + char *relnamespace; + char *relname; + char *indname; + BlockNumber blkno; /* used only for heap operations */ + int phase; /* Reusing same enums as for progress reporting */ +} vacuum_error_callback_arg; /* A few variables that don't seem worth passing around as parameters */ static int elevel = -1; @@ -361,6 +369,9 @@ static void end_parallel_vacuum(Relation *Irel, IndexBulkDeleteResult **stats, LVParallelState *lps, int nindexes); static LVSharedIndStats *get_indstats(LVShared *lvshared, int n); static bool skip_parallel_vacuum_index(Relation indrel, LVShared *lvshared); +static void vacuum_error_callback(void *arg); +static void init_vacuum_error_callback(ErrorContextCallback *errcallback, + vacuum_error_callback_arg *errcbarg, Relation onerel, int phase); /* @@ -724,6 +735,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 errcbarg; pg_rusage_init(&ru0); @@ -870,6 +883,10 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, else skipping_blocks = false; + /* Setup error traceback support for ereport() */ + init_vacuum_error_callback(&errcallback, &errcbarg, onerel, PROGRESS_VACUUM_PHASE_SCAN_HEAP); + error_context_stack = &errcallback; + for (blkno = 0; blkno < nblocks; blkno++) { Buffer buf; @@ -891,6 +908,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, #define FORCE_CHECK_PAGE() \ (blkno == nblocks - 1 && should_attempt_truncation(params, vacrelstats)) + errcbarg.blkno = blkno; + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); if (blkno == next_unskippable_block) @@ -987,6 +1006,9 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, vmbuffer = InvalidBuffer; } + /* Pop the error context stack while calling vacuum */ + error_context_stack = errcallback.previous; + /* Work on all the indexes, then the heap */ lazy_vacuum_all_indexes(onerel, Irel, indstats, vacrelstats, lps, nindexes); @@ -1011,6 +1033,9 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats, /* Report that we are once again scanning the heap */ pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_SCAN_HEAP); + + /* Set the error context while continuing heap scan */ + error_context_stack = &errcallback; } /* @@ -1597,6 +1622,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); @@ -1772,11 +1800,19 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) int npages; PGRUsage ru0; Buffer vmbuffer = InvalidBuffer; + ErrorContextCallback errcallback; + vacuum_error_callback_arg errcbarg; /* Report that we are now vacuuming the heap */ pgstat_progress_update_param(PROGRESS_VACUUM_PHASE, PROGRESS_VACUUM_PHASE_VACUUM_HEAP); + /* + * Setup error traceback support for ereport() + */ + init_vacuum_error_callback(&errcallback, &errcbarg, onerel, PROGRESS_VACUUM_PHASE_VACUUM_HEAP); + error_context_stack = &errcallback; + pg_rusage_init(&ru0); npages = 0; @@ -1791,6 +1827,7 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) vacuum_delay_point(); tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); + errcbarg.blkno = tblk; buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1811,6 +1848,9 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) npages++; } + /* Pop the error context stack */ + error_context_stack = errcallback.previous; + if (BufferIsValid(vmbuffer)) { ReleaseBuffer(vmbuffer); @@ -2318,6 +2358,8 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats, IndexVacuumInfo ivinfo; const char *msg; PGRUsage ru0; + ErrorContextCallback errcallback; + vacuum_error_callback_arg errcbarg; pg_rusage_init(&ru0); @@ -2329,10 +2371,17 @@ lazy_vacuum_index(Relation indrel, IndexBulkDeleteResult **stats, ivinfo.num_heap_tuples = reltuples; ivinfo.strategy = vac_strategy; + /* Setup error traceback support for ereport() */ + init_vacuum_error_callback(&errcallback, &errcbarg, indrel, PROGRESS_VACUUM_PHASE_VACUUM_INDEX); + error_context_stack = &errcallback; + /* Do bulk deletion */ *stats = index_bulk_delete(&ivinfo, *stats, lazy_tid_reaped, (void *) dead_tuples); + /* Pop the error context stack */ + error_context_stack = errcallback.previous; + if (IsParallelWorker()) msg = gettext_noop("scanned index \"%s\" to remove %d row versions by parallel vacuum worker"); else @@ -2359,6 +2408,8 @@ lazy_cleanup_index(Relation indrel, IndexVacuumInfo ivinfo; const char *msg; PGRUsage ru0; + vacuum_error_callback_arg errcbarg; + ErrorContextCallback errcallback; pg_rusage_init(&ru0); @@ -2371,8 +2422,15 @@ lazy_cleanup_index(Relation indrel, ivinfo.num_heap_tuples = reltuples; ivinfo.strategy = vac_strategy; + /* Setup error traceback support for ereport() */ + init_vacuum_error_callback(&errcallback, &errcbarg, indrel, PROGRESS_VACUUM_PHASE_INDEX_CLEANUP); + error_context_stack = &errcallback; + *stats = index_vacuum_cleanup(&ivinfo, *stats); + /* Pop the error context stack */ + error_context_stack = errcallback.previous; + if (!(*stats)) return; @@ -3375,3 +3433,65 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) table_close(onerel, ShareUpdateExclusiveLock); pfree(stats); } + +/* + * Error context callback for errors occurring during vacuum. + */ +static void +vacuum_error_callback(void *arg) +{ + vacuum_error_callback_arg *cbarg = arg; + + switch (cbarg->phase) { + case PROGRESS_VACUUM_PHASE_SCAN_HEAP: + if (BlockNumberIsValid(cbarg->blkno)) + errcontext(_("while scanning block %u of relation \"%s.%s\""), + cbarg->blkno, cbarg->relnamespace, cbarg->relname); + break; + + case PROGRESS_VACUUM_PHASE_VACUUM_HEAP: + if (BlockNumberIsValid(cbarg->blkno)) + errcontext(_("while vacuuming block %u of relation \"%s.%s\""), + cbarg->blkno, cbarg->relnamespace, cbarg->relname); + break; + + case PROGRESS_VACUUM_PHASE_VACUUM_INDEX: + errcontext(_("while vacuuming index \"%s.%s\" of relation \"%s\""), + cbarg->relnamespace, cbarg->indname, cbarg->relname); + break; + + case PROGRESS_VACUUM_PHASE_INDEX_CLEANUP: + errcontext(_("while cleaning up index \"%s.%s\" of relation \"%s\""), + cbarg->relnamespace, cbarg->indname, cbarg->relname); + break; + } +} + +/* Initialize vacuum error callback */ +static void +init_vacuum_error_callback(ErrorContextCallback *errcallback, vacuum_error_callback_arg *errcbarg, Relation rel, int phase) +{ + switch (phase) + { + case PROGRESS_VACUUM_PHASE_SCAN_HEAP: + case PROGRESS_VACUUM_PHASE_VACUUM_HEAP: + errcbarg->relname = RelationGetRelationName(rel); + errcbarg->indname = NULL; /* Not used for heap */ + break; + + case PROGRESS_VACUUM_PHASE_VACUUM_INDEX: + case PROGRESS_VACUUM_PHASE_INDEX_CLEANUP: + /* rel is an index relation in index vacuum case */ + errcbarg->relname = get_rel_name(rel->rd_index->indrelid); + errcbarg->indname = RelationGetRelationName(rel); + break; + } + + errcbarg->relnamespace = get_namespace_name(RelationGetNamespace(rel)); + errcbarg->blkno = InvalidBlockNumber; /* Not known yet */ + errcbarg->phase = phase; + + errcallback->callback = vacuum_error_callback; + errcallback->arg = errcbarg; + errcallback->previous = error_context_stack; +} -- 2.7.4 --E/DnYTRukya0zdZ1--