Hi Antonin,

Thanks for your update.

I think v04 fixes the finalize_block_range() problem.

The compute_new_xmax_infomask() Assert is easy to hit. The
AccessExclusiveLock in rebuild_relation_finish_concurrent() assigns an
XID, so any UPDATE or DELETE committed while REPACK waits for it fails
on replay. The attached spec does it every time.


If you give the new counter a slot that index builds don't write,
like 13, 0008 does not have to depend on 6958.

Thanks,
Shihao
# v04-0008: an UPDATE that commits while REPACK (CONCURRENTLY) waits for
# AccessExclusiveLock on the table is replayed after the lock is granted.
# LockAcquireExtended() assigned REPACK an XID for the standby lock record
# (wal_level >= replica), so the replayed heap_update() runs with a valid
# top XID and add_to_xmax of the original transaction.
setup
{
        CREATE EXTENSION injection_points;
        CREATE TABLE t(i int PRIMARY KEY, j int);
        INSERT INTO t SELECT x, 0 FROM generate_series(1, 100) x;
}

teardown
{
        DROP TABLE t;
        DROP EXTENSION injection_points;
}

session s1
setup
{
        SELECT injection_points_set_local();
        SELECT injection_points_attach('repack-concurrently-before-lock', 
'wait');
}
step repack { REPACK (CONCURRENTLY) t; }
step check { SELECT count(*), sum(j) FROM t; }

session s2
step begin { BEGIN; }
step upd { UPDATE t SET j = j + 1 WHERE i = 10; }
step del { DELETE FROM t WHERE i = 20; }
step commit { COMMIT; }

session s3
step wakeup
{
        SELECT injection_points_detach('repack-concurrently-before-lock');
        SELECT injection_points_wakeup('repack-concurrently-before-lock');
}
# Make sure REPACK is queued for AccessExclusiveLock before s2 commits.
step waitlock
{
        DO $$
        BEGIN
                WHILE NOT EXISTS (SELECT 1 FROM pg_locks
                                                  WHERE relation = 
't'::regclass AND NOT granted
                                                        AND mode = 
'AccessExclusiveLock')
                LOOP
                        PERFORM pg_sleep(0.01);
                END LOOP;
        END
        $$;
}

permutation repack begin upd wakeup waitlock commit check
permutation repack begin del wakeup waitlock commit check
# Controls: the change commits before REPACK leaves the injection point,
# so it is replayed before the lock is requested.
permutation repack begin upd commit wakeup check
permutation repack begin del commit wakeup check

Reply via email to