Alexander Lakhin <[email protected]> wrote: > Could you please look at an assertion failure produced by the following > script, starting from 0d3dba38c:? > createdb db1 > createdb db2 > > echo " > CREATE TABLE t0 (a text); > BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; > INSERT INTO t0 VALUES ('a'); > SELECT pg_sleep(1); > " | psql db1 & > > echo " > CREATE TABLE t1 (id int PRIMARY KEY); > CREATE TABLE t2 (id int PRIMARY KEY, a TEXT, FOREIGN KEY (id) REFERENCES t1); > SET min_parallel_table_scan_size = 1; > REPACK (CONCURRENTLY) t2; > " | psql db2 > wait > > It triggers for me: > TRAP: failed Assert("TransactionIdPrecedesOrEquals(TransactionXmin, > RecentXmin)"), File: "procarray.c", Line: 2071, PID: 3529520
Attached is a fix that works for me. Nevertheless, REPACK (CONCURRENTLY) in your test goes ahead only due to commit 0d3dba38c7, which will probably be reverted [1]. Then REPACK will wait for the transaction in the other database (db1) to complete before it can actually start. Thanks for the report! [1] https://www.postgresql.org/message-id/cdgw4sbbfcgk6du3iv54r2dgiy4tfywoklbotlmj4irxavdcr3@glxfw5jj277q -- Antonin Houska Web: https://www.cybertec-postgresql.com
>From 3fd0a70566f42d695b92c1cb2d26d3dbd5918a58 Mon Sep 17 00:00:00 2001 From: Antonin Houska <[email protected]> Date: Fri, 10 Apr 2026 12:17:36 +0200 Subject: [PATCH] Do not push the active snapshot for copy_table_data before it's needed. make_new_heap() can launch parallel workers when building index on TOAST relation. If the snapshot for copy_table_data() is already the active snapshot, the workers can incorrectly consider it their transaction snapshot. --- src/backend/commands/repack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 58e3867246f..08fd132a4e3 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -1013,8 +1013,6 @@ rebuild_relation(Relation OldHeap, Relation index, bool verbose, * Wait until the worker has the initial snapshot and retrieve it. */ snapshot = get_initial_snapshot(decoding_worker); - - PushActiveSnapshot(snapshot); } /* for CLUSTER or REPACK USING INDEX, mark the index as the one to use */ @@ -1038,6 +1036,8 @@ rebuild_relation(Relation OldHeap, Relation index, bool verbose, NewHeap = table_open(OIDNewHeap, NoLock); /* Copy the heap data into the new table in the desired order */ + if (snapshot) + PushActiveSnapshot(snapshot); copy_table_data(NewHeap, OldHeap, index, snapshot, verbose, &swap_toast_by_content, &frozenXid, &cutoffMulti); -- 2.47.3
