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-25T16:31:00Z
Lists: pgsql-hackers

Attachments

Hello, Antonin!

PART 1:

I started rebasing the MVCC-safe version on top of the multi-snapshot
version and realized it becomes complex.
But, what's really bad about MVCC-unsafety is the ability to access
*incorrect* data and break some logic (or even constraints).

If we may *prevent* such data access with some kind of error (which is
going to be very infrequent) - I don't see any sense to achieve true
MVCC-safety.

I remembered a way it works with indcheckxmin for indexes. And made
something similar for pg_class: it records the rewriting transaction XID
and causes the executor to raise an error if a transaction with an older
snapshot attempts to access the rewritten relation.

For the normal case - check is never executed, no performance regression
here. Also, the flag is automatically cleared by VACUUM once the
transaction ID is frozen.

It also "fixes" ALTER TABLE, not only REPACK concurrently.

Attached patch contains more details (some in the commit message).

PART 2:

I have continued working with stress tests. This time I added your WIP
patch to fix the LR\CLOG race.

I made the following configs:
1) just REPACK CONCURRENTLY - ok
2) + relcheckxmin (see PART1) - ok
3) + worker - ok
4) + multiple snapshots - broken in multiple ways.

You may see example of run here -
https://cirrus-ci.com/build/6359048020295680

Some examples:

1)  'pgbench: error: client 11 script 0 aborted in command 20 query 0:
ERROR:  could not read blocks 0..0 in file "base/5/16414": read only 0 of
8192 bytes
2) at /home/postgres/postgres/contrib/amcheck/t/008_repack_concurrently.pl
line 51.
[15:36:37.204] #                   'pgbench: error: client 5 script 0
aborted in command 28 query 0: ERROR:  division by zero
3)    'pgbench: error: client 12 script 0 aborted in command 6 query 0:
ERROR:  cache lookup failed for relation 17400

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