| From: | Srinath Reddy Sadipiralla <srinath2133(at)gmail(dot)com> |
|---|---|
| To: | Jochen Bandhauer <jb(at)jbitc(dot)de> |
| Cc: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: repack with verbose output: not showing the number of removable row versions when using USING INDEX or CONCURRENTLY option |
| Date: | 2026-08-19 16:16:55 |
| Message-ID: | CAFC+b6rp6CDki8Ea3-wQExS2RMmdPmv9FwrHzCt0FDUWddYLYw@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hi Jochen,
On Wed, Aug 19, 2026 at 4:33 PM Jochen Bandhauer <jb(at)jbitc(dot)de> wrote:
> Hello,
>
> on: PostgreSQL 19beta3 (development build (./configure --enable-debug
> --enable-cassert CFLAGS='-O0 -g3'))
> when using repack with the option CONCURRENTLY or when using USING INDEX
> the verbose output does not show the number of removable row versions.
> When using the command without these options the number of removable
> rows are shown.
>
> Complete Version: PostgreSQL 19beta3 on x86_64-pc-linux-gnu, compiled by
> gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
>
> Test Case:
>
> -- create table and data
> drop table if exists t;
> create table t (id bigint primary key, col1 bigint);
> create index i1 on t (col1);
> insert into t select generate_series(1, 100000);
>
> -- commands
> repack (verbose) t; -- found 0 removable => ok
> update t set col1=1;
> repack (verbose) t; -- found 100000 removable => ok
> update t set col1=1;
> repack (verbose,concurrently) t; -- found 0 removable => is this correct?
> update t set col1=1;
> repack (verbose) t using index i1; -- found 0 removable => is this
> correct?
> update t set col1=1;
> repack (verbose,concurrently) t using index i1; -- found 0 removable =>
> is this correct?
>
> -- output:
> mydb=# repack (verbose) t;
> INFO: repacking "public.t" in physical order
> INFO: "public.t": found 0 removable, 100000 nonremovable row versions
> in 443 pages
> DETAIL: 0 dead row versions cannot be removed yet.
> CPU: user: 0.14 s, system: 0.00 s, elapsed: 0.14 s.
> REPACK
> mydb=# update t set col1=1;
> UPDATE 100000
> mydb=# repack (verbose) t;
> INFO: repacking "public.t" in physical order
> INFO: "public.t": found 100000 removable, 100000 nonremovable row
> versions in 984 pages
> DETAIL: 0 dead row versions cannot be removed yet.
> CPU: user: 0.23 s, system: 0.00 s, elapsed: 0.23 s.
> REPACK
> mydb=# update t set col1=1;
> UPDATE 100000
> mydb=# repack (verbose,concurrently) t;
> INFO: repacking "public.t" in physical order
> INFO: "public.t": found 0 removable, 100000 nonremovable row versions
> in 1082 pages
> DETAIL: 0 dead row versions cannot be removed yet.
> CPU: user: 0.37 s, system: 0.00 s, elapsed: 0.38 s.
> REPACK
> mydb=# update t set col1=1;
> UPDATE 100000
> mydb=# repack (verbose) t using index i1;
> INFO: repacking "public.t" using index scan on "i1"
> INFO: "public.t": found 0 removable, 100000 nonremovable row versions
> in 1082 pages
> DETAIL: 0 dead row versions cannot be removed yet.
> CPU: user: 0.39 s, system: 0.00 s, elapsed: 0.40 s.
> REPACK
> mydb=# update t set col1=1;
> UPDATE 100000
> mydb=# repack (verbose,concurrently) t using index i1;
> INFO: repacking "public.t" using index scan on "i1"
> INFO: "public.t": found 0 removable, 100000 nonremovable row versions
> in 1082 pages
> DETAIL: 0 dead row versions cannot be removed yet.
> CPU: user: 0.56 s, system: 0.01 s, elapsed: 0.59 s.
> REPACK
> mydb=#
>
Thanks for the super-clear reproducer; I can reproduce it on master as well.
The code in copy_table_data(), where VERBOSE bumps the log level to INFO
so the message becomes visible. The counts it prints (removable,
nonremovable,
and "dead row versions cannot be removed yet") are only ever computed in the
non-concurrent path: that path scans the old heap with SnapshotAny and
classifies
every tuple with HeapTupleSatisfiesVacuum(), which is what populates
tups_vacuumed
and tups_recently_dead. The concurrent path instead scans with a regular
MVCC
snapshot, so the scan itself returns only the rows visible to that
snapshot, and those
two counters stay at 0. So for the concurrent case it doesn't make sense to
report
removable/nonremovable counts, since they aren't tracked there. I think
it's more
useful to report the number of tuples copied into the new table. Small
patch below,
thoughts?
diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index edff54e734e..b780dbf2ff9 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -1438,16 +1438,23 @@ copy_table_data(Relation NewHeap, Relation OldHeap,
Relation OldIndex,
num_pages = RelationGetNumberOfBlocks(NewHeap);
/* Log what we did */
- ereport(elevel,
- (errmsg("\"%s.%s\": found %.0f removable, %.0f
nonremovable row versions in %u pages",
- nspname,
- RelationGetRelationName(OldHeap),
- tups_vacuumed, num_tuples,
- RelationGetNumberOfBlocks(OldHeap)),
- errdetail("%.0f dead row versions cannot be
removed yet.\n"
- "%s.",
- tups_recently_dead,
- pg_rusage_show(&ru0))));
+ if (!concurrent)
+ ereport(elevel,
+ (errmsg("\"%s.%s\": found %.0f removable,
%.0f nonremovable row versions in %u pages",
+ nspname,
+
RelationGetRelationName(OldHeap),
+ tups_vacuumed, num_tuples,
+
RelationGetNumberOfBlocks(OldHeap)),
+ errdetail("%.0f dead row versions cannot be
removed yet.\n"
+ "%s.",
+ tups_recently_dead,
+ pg_rusage_show(&ru0))));
+ else
+ ereport(elevel,
+ (errmsg("\"%s.%s\": copied %.0f row
versions in %u pages",
+ nspname,
RelationGetRelationName(OldHeap),
+ num_tuples, num_pages),
+ errdetail("%s.", pg_rusage_show(&ru0))));
/* Update pg_class to reflect the correct values of pages and
tuples. */
relRelation = table_open(RelationRelationId, RowExclusiveLock);
--
Thanks :)
Srinath Reddy Sadipiralla
EDB: https://www.enterprisedb.com/
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Zsolt Parragi | 2026-08-19 17:24:04 | Re: Possible G2-item at SERIALIZABLE |
| Previous Message | Ayush Tiwari | 2026-08-19 16:12:18 | Re: BUG #19629: pg_restore_relation_stats reports XX000 instead of proper SQLSTATE for input validation errors |