Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pJd8R-0003CS-Jg for pgsql-hackers@arkaria.postgresql.org; Sun, 22 Jan 2023 16:23:59 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pJd8O-0005gg-R8 for pgsql-hackers@arkaria.postgresql.org; Sun, 22 Jan 2023 16:23:56 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pJd8O-0005gX-Cj for pgsql-hackers@lists.postgresql.org; Sun, 22 Jan 2023 16:23:56 +0000 Received: from mail-il1-x12c.google.com ([2607:f8b0:4864:20::12c]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pJd8H-0006gi-Ti for pgsql-hackers@lists.postgresql.org; Sun, 22 Jan 2023 16:23:55 +0000 Received: by mail-il1-x12c.google.com with SMTP id m15so5055722ilq.2 for ; Sun, 22 Jan 2023 08:23:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20210112.gappssmtp.com; s=20210112; h=user-agent:content-disposition:mime-version:message-id:subject:cc :to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=R8ncKgepTZkhljalnUceDShFLf87SZUWWhgVgkICXro=; b=XPaltM3vKFYc8TTRoCTfKEnYalE84xeXP3BteCX63Jp4EqkDVOJ59EgGcJTdXClj1I ayVg42qBdoq9Xd4dy8nU8LUhyo12Y5zhbzIDBRgqnSsAEwpEMW7TKvKvKkV9yl8hucij iy+CiDnsovMilqYw6g6SVPa+YTrv8nuZV4Hqc1Bzq1hMxXu89EFF8ZTxgjflpJ14/kmU wdqFGzFJXthKex7bqtvC+EOSbqV+HgmKA2mNQCAcrbw4ucZIDawL00layR/eJQ+Z7tji pWkHB/CtjtLifsypXUtVb9jXon7ffux/sdTG6Y/DtjW42oj4jhMmmZ4eNS12SUEEa1za endw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=user-agent:content-disposition:mime-version:message-id:subject:cc :to:from:date:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=R8ncKgepTZkhljalnUceDShFLf87SZUWWhgVgkICXro=; b=hkX+H+lCPz8lG2eBFU+LOr25kwVV7MYebz+CSJ05V9TvKTYSTt7Ss/CANJHbGWbp7x 6WSIAJ3pmBINT2MsRlK9G4qjrqM62UjJ7Hwz7NhoiBt2G/ca2mrtDehWNy+CIJ097EPZ 7alw6gDEMbF+yl7sUAVPKsK69Kmr6s6dF3fRjY57bLzoKXrwvEA8eTYWUWZlxcXJDuUX ayQPq8K4YNU6tC2SmOyJupxVxyjnP5VOXLsZ3OLZ9K9VLxLX5psSZTSlNsL54l+Vwqa8 S4ZtWxPydgkBLQTRlMJQIY0QObkI8yLMxBk1OxSvp8oXBBvxWZEwJu1b3yNuGgOQtG0u rzag== X-Gm-Message-State: AFqh2kqCmhxONYBmy5AAlJtXBth7ZDQhZiTEXcV3NX3nXqbgArmEQ9gm 3k0RWIh3LTBDKrkJVgSIRPuMvQ== X-Google-Smtp-Source: AMrXdXv1eE0fW2H93EOXzilvz1uXJ32wSz0PBoTWgYLKZRU7JjgicE12dUUygni1joMDYcglldDM/w== X-Received: by 2002:a92:ce0d:0:b0:30e:e4cf:3fa7 with SMTP id b13-20020a92ce0d000000b0030ee4cf3fa7mr16229472ilo.4.1674404628065; Sun, 22 Jan 2023 08:23:48 -0800 (PST) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id c14-20020a92d3ce000000b0030dbef81995sm9784975ilh.57.2023.01.22.08.23.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 22 Jan 2023 08:23:47 -0800 (PST) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id BB91D80146E; Sun, 22 Jan 2023 10:23:45 -0600 (CST) Date: Sun, 22 Jan 2023 10:23:45 -0600 From: Justin Pryzby To: Alvaro Herrera Cc: pgsql-hackers@lists.postgresql.org, Ilya Gladyshev , Matthias van de Meent , Robert Haas Subject: bug: ANALYZE progress report with inheritance tables Message-ID: <20230122162345.GP13860@telsasoft.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk pg_stat_progress_analyze was added in v13 (a166d408e). For tables with inheritance children, do_analyze_rel() and acquire_sample_rows() are called twice. The first time through, pgstat_progress_start_command() has memset() the progress array to zero. But the 2nd time, ANALYZE_BLOCKS_DONE is already set from the previous call, and BLOCKS_TOTAL can be set to some lower value (and in any case a value unrelated to the pre-existing value of BLOCKS_DONE). So the progress report briefly shows a bogus combination of values and, with these assertions, fails regression tests in master and v13, unless BLOCKS_DONE is first zeroed. | Core was generated by `postgres: pryzbyj regression [local] VACUUM '. | ... | #5 0x0000559a1c9fbbcc in ExceptionalCondition (conditionName=conditionName@entry=0x559a1cb68068 "a[PROGRESS_ANALYZE_BLOCKS_DONE] <= a[PROGRESS_ANALYZE_BLOCKS_TOTAL]", | ... | #16 0x0000563165cc7cfe in exec_simple_query (query_string=query_string@entry=0x563167cad0c8 "VACUUM ANALYZE stxdinh, stxdinh1, stxdinh2;") at ../src/backend/tcop/postgres.c:1237 | ... | (gdb) p MyBEEntry->st_progress_param[1] | $1 = 5 | (gdb) p MyBEEntry->st_progress_param[2] | $2 = 9 BTW, I found this bug as well as the COPY progress bug I reported [0] while testing the CREATE INDEX progress bug reported by Ilya. It seems like the progress infrastructure should have some checks added. [0] https://www.postgresql.org/message-id/flat/20230119054703.GB13860@telsasoft.com diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index c86e690980e..96710b84558 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -1145,6 +1145,12 @@ acquire_sample_rows(Relation onerel, int elevel, TableScanDesc scan; BlockNumber nblocks; BlockNumber blksdone = 0; + int64 progress_vals[2] = {0}; + int const progress_inds[2] = { + PROGRESS_ANALYZE_BLOCKS_DONE, + PROGRESS_ANALYZE_BLOCKS_TOTAL + }; + #ifdef USE_PREFETCH int prefetch_maximum = 0; /* blocks to prefetch if enabled */ BlockSamplerData prefetch_bs; @@ -1169,8 +1175,8 @@ acquire_sample_rows(Relation onerel, int elevel, #endif /* Report sampling block numbers */ - pgstat_progress_update_param(PROGRESS_ANALYZE_BLOCKS_TOTAL, - nblocks); + progress_vals[1] = nblocks; + pgstat_progress_update_multi_param(2, progress_inds, progress_vals); /* Prepare for sampling rows */ reservoir_init_selection_state(&rstate, targrows); diff --git a/src/backend/utils/activity/backend_progress.c b/src/backend/utils/activity/backend_progress.c index d96af812b19..05593fb13cb 100644 --- a/src/backend/utils/activity/backend_progress.c +++ b/src/backend/utils/activity/backend_progress.c @@ -10,6 +10,7 @@ */ #include "postgres.h" +#include "commands/progress.h" #include "port/atomics.h" /* for memory barriers */ #include "utils/backend_progress.h" #include "utils/backend_status.h" @@ -37,6 +38,83 @@ pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid) PGSTAT_END_WRITE_ACTIVITY(beentry); } +/* + * Check for consistency of progress data (current < total). + * + * Check during pgstat_progress_updates_*() rather than only from + * pgstat_progress_end_command() to catch issues with uninitialized/stale data + * from previous progress commands. + * + * If a command fails due to interrupt or error, the values may be less than + * the expected final value. + */ +static void +pgstat_progress_asserts(void) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + volatile int64 *a = beentry->st_progress_param; + + switch (beentry->st_progress_command) + { + case PROGRESS_COMMAND_VACUUM: + Assert(a[PROGRESS_VACUUM_HEAP_BLKS_SCANNED] <= + a[PROGRESS_VACUUM_TOTAL_HEAP_BLKS]); + Assert(a[PROGRESS_VACUUM_HEAP_BLKS_VACUUMED] <= + a[PROGRESS_VACUUM_TOTAL_HEAP_BLKS]); + Assert(a[PROGRESS_VACUUM_NUM_DEAD_TUPLES] <= + a[PROGRESS_VACUUM_MAX_DEAD_TUPLES]); + break; + + case PROGRESS_COMMAND_ANALYZE: + Assert(a[PROGRESS_ANALYZE_BLOCKS_DONE] <= + a[PROGRESS_ANALYZE_BLOCKS_TOTAL]); + Assert(a[PROGRESS_ANALYZE_EXT_STATS_COMPUTED] <= + a[PROGRESS_ANALYZE_EXT_STATS_TOTAL]); + Assert(a[PROGRESS_ANALYZE_CHILD_TABLES_DONE] <= + a[PROGRESS_ANALYZE_CHILD_TABLES_TOTAL]); + break; + + case PROGRESS_COMMAND_CLUSTER: + Assert(a[PROGRESS_CLUSTER_HEAP_BLKS_SCANNED] <= + a[PROGRESS_CLUSTER_TOTAL_HEAP_BLKS]); + /* fall through because CLUSTER rebuilds indexes */ + case PROGRESS_COMMAND_CREATE_INDEX: + Assert(a[PROGRESS_CREATEIDX_TUPLES_DONE] <= + a[PROGRESS_CREATEIDX_TUPLES_TOTAL]); + Assert(a[PROGRESS_CREATEIDX_PARTITIONS_DONE] <= + a[PROGRESS_CREATEIDX_PARTITIONS_TOTAL]); + break; + + case PROGRESS_COMMAND_BASEBACKUP: + /* progress reporting is optional for these */ + if (a[PROGRESS_BASEBACKUP_BACKUP_TOTAL] >= 0) + { + Assert(a[PROGRESS_BASEBACKUP_BACKUP_STREAMED] <= + a[PROGRESS_BASEBACKUP_BACKUP_TOTAL]); + Assert(a[PROGRESS_BASEBACKUP_TBLSPC_STREAMED] <= + a[PROGRESS_BASEBACKUP_TBLSPC_TOTAL]); + } + break; + +#if 0 + case PROGRESS_COMMAND_COPY: +// This currently fails file_fdw tests, since pgstat_prorgress evidently fails +// to support simultaneous copy commands, as happens during JOIN. + /* bytes progress is not available in all cases */ + if (a[PROGRESS_COPY_BYTES_TOTAL] > 0) + // Assert(a[PROGRESS_COPY_BYTES_PROCESSED] <= a[PROGRESS_COPY_BYTES_TOTAL]); + if (a[PROGRESS_COPY_BYTES_PROCESSED] > a[PROGRESS_COPY_BYTES_TOTAL]) + elog(WARNING, "PROGRESS_COPY_BYTES_PROCESSED %ld %ld", + a[PROGRESS_COPY_BYTES_PROCESSED], + a[PROGRESS_COPY_BYTES_TOTAL]); +#endif + break; + + case PROGRESS_COMMAND_INVALID: + break; /* Do nothing */ + } +} + /*----------- * pgstat_progress_update_param() - * @@ -56,6 +134,8 @@ pgstat_progress_update_param(int index, int64 val) PGSTAT_BEGIN_WRITE_ACTIVITY(beentry); beentry->st_progress_param[index] = val; PGSTAT_END_WRITE_ACTIVITY(beentry); + + pgstat_progress_asserts(); } /*----------- @@ -85,6 +165,8 @@ pgstat_progress_update_multi_param(int nparam, const int *index, } PGSTAT_END_WRITE_ACTIVITY(beentry); + + pgstat_progress_asserts(); } /*-----------