Re: Adding REPACK [concurrently]

Mihail Nikalayeu <mihailnikalayeu@gmail.com>

From: Mihail Nikalayeu <mihailnikalayeu@gmail.com>
To: Antonin Houska <ah@cybertec.at>
Cc: Alvaro Herrera <alvherre@alvh.no-ip.org>, Pg Hackers <pgsql-hackers@lists.postgresql.org>, Robert Treat <rob@xzilla.net>
Date: 2026-01-10T17:37:06Z
Lists: pgsql-hackers
Hello, Antonin!

On Thu, Jan 8, 2026 at 7:59 PM Antonin Houska <ah@cybertec.at> wrote:
> v29 tries to fix the problem.

Some comments for 0001-0004.

------ 0001 -----

> src/bin/scripts/t/103_repackdb.pl:1:
>  # Copyright (c) 2021-2025

Update year for 2026.

> * FIXME: this is missing a way to specify the index to use to repack one
> * table, or whether to pass a WITH INDEX clause when multiple tables are
> * used.  Something like --index[=indexname].  Adding that bleeds into
> * vacuuming.c as well.

Comments look stale.

> return "???";
I think it is better to add Assert(false); before (done that way in a
few places).

> command <link linkend="sql-repack"><command>REPACK</command></link> There
need .

> “An utility”
Should be “A utility”

> else if (pg_strcasecmp(cmd, "CLUSTER") == 0)
>    cmdtype = PROGRESS_COMMAND_CLUSTER;

Should we set PROGRESS_COMMAND_REPACK here? Because cluster is not
used anywhere. Probably we may even delete PROGRESS_COMMAND_CLUSTER.

> CLUOPT_RECHECK_ISCLUSTERED
It is not set anymore... Probably something is wrong here or we need
to just remove that constant and check for it.

------ 0002 -----

> rebuild_relation(Relation OldHeap, Relation index, bool verbose)
It removes unused cmd parameter, but I think it is better to not add
it in the previous commit.

------ 0003 -----

> int       newxcnt = 0;

I think it is better to use uint32 for consistency here.

Also, I think it is worth adding Assert(snapshot->snapshot_type ==
SNAPSHOT_HISTORIC_MVCC)

------ 0004 -----

> /* Is REPACK (CONCURRENTLY) being run by this backend? */
> if (am_decoding_for_repack())

We should check change_useless_for_repack here - to avoid looking and
TRUNCATE of unrelated tables.

> /* For the same reason, unlock TOAST relation. */
> if (OldHeap->rd_rel->reltoastrelid)
>    LockRelationOid(OldHeap->rd_rel->reltoastrelid, AccessExclusiveLock);

Hm, we are locking here instead of unlocking ;)

> (errhint("Relation \"%s\" has no identity index.",
>       RelationGetRelationName(rel)))));

One level of braces may be removed.

> * to decode on behalf of REPACK (CONCURRENT)?

CONCURRENTLY

> * If recheck is required, it must have been preformed on the source

"performed"

> * On exit,'*scan_p' contains the scan descriptor used. The caller must close
> * it when he no longer needs the tuple returned.

There is no scan_p argument here.

> * Copyright (c) 2012-2025, PostgreSQL Global Development Group

2026

> newtuple = change->data.tp.newtuple != NULL ?
>   change->data.tp.newtuple : NULL;

> oldtuple = change->data.tp.oldtuple != NULL ?
>    change->data.tp.oldtuple : NULL;
> newtuple = change->data.tp.newtuple != NULL ?
>    change->data.tp.newtuple : NULL;

Hm, should it be just x = y ?

> apply_concurrent_insert

Double newline at function start.

> heap2_decode

Should we check for change_useless_for_repack here also? (for multi
insert, for example).

Best regards,
Mikhail.



Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Allow old WAL recycling during REPACK CONCURRENTLY

  2. Advance restart_lsn more eagerly in LogicalConfirmReceivedLocation

  3. Remove unnecessary signal handler change

  4. Improve REPACK (CONCURRENTLY) error messages some more

  5. Revert "Allow logical replication snapshots to be database-specific"

  6. Move REPACK (CONCURRENTLY) test out of stock regression tests

  7. REPACK: do not require REPLICATION or LOGIN

  8. Add missing initialization

  9. Simplify declaration of memcpy target

  10. Reserve replication slots specifically for REPACK

  11. doc: Add an example of REPACK (CONCURRENTLY)

  12. Allow logical replication snapshots to be database-specific

  13. Avoid different-size pointer-to-integer cast

  14. Fix valgrind failure

  15. Add CONCURRENTLY option to REPACK

  16. Rename cluster.c to repack.c (and corresponding .h)

  17. Allow index_create to suppress index_build progress reporting

  18. Make index_concurrently_create_copy more general

  19. Document the 'command' column of pg_stat_progress_repack

  20. Introduce the REPACK command

  21. Toggle logical decoding dynamically based on logical slot presence.

  22. Split vacuumdb to create vacuuming.c/h

  23. Remove ReorderBufferTupleBuf structure.

  24. Revert changes to CONCURRENTLY that "sped up" Xmin advance

  25. VACUUM: ignore indexing operations with CONCURRENTLY