agora inbox for pgsql-hackers@postgresql.orghelp / color / mirror / Atom feed
[PATCH 01/11] Don't use EV_CLEAR for kqueue events. 377+ messages / 3 participants [nested] [flat]
* [PATCH 01/11] Don't use EV_CLEAR for kqueue events. @ 2020-02-24 13:53 Thomas Munro <thomas.munro@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Thomas Munro @ 2020-02-24 13:53 UTC (permalink / raw) For the semantics to match the epoll implementation, we need a socket to continue to appear readable/writable if you wait multiple times without doing I/O in between (in Linux terminology, level-triggered rather than edge-triggered). Similar to commit 3b790d256f8 for Windows. Author: Thomas Munro Discussion: https://postgr.es/m/CA%2BhUKGJAC4Oqao%3DqforhNey20J8CiG2R%3DoBPqvfR0vOJrFysGw%40mail.gmail.com --- src/backend/storage/ipc/latch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index 046ca5c6c7..3b6acfb251 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -991,7 +991,7 @@ WaitEventAdjustKqueueAdd(struct kevent *k_ev, int filter, int action, { k_ev->ident = event->fd; k_ev->filter = filter; - k_ev->flags = action | EV_CLEAR; + k_ev->flags = action; k_ev->fflags = 0; k_ev->data = 0; AccessWaitEvent(k_ev) = event; @@ -1003,7 +1003,7 @@ WaitEventAdjustKqueueAddPostmaster(struct kevent *k_ev, WaitEvent *event) /* For now postmaster death can only be added, not removed. */ k_ev->ident = PostmasterPid; k_ev->filter = EVFILT_PROC; - k_ev->flags = EV_ADD | EV_CLEAR; + k_ev->flags = EV_ADD; k_ev->fflags = NOTE_EXIT; k_ev->data = 0; AccessWaitEvent(k_ev) = event; -- 2.18.2 ----Next_Part(Fri_Mar_13_16_21_13_2020_620)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="0002-Use-a-long-lived-WaitEventSet-for-WaitLatch.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH 2/3] one more stress test for repack concurrently @ 2025-12-13 17:46 Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Mikhail Nikalayeu @ 2025-12-13 17:46 UTC (permalink / raw) --- contrib/amcheck/meson.build | 1 + contrib/amcheck/t/008_repack_2.pl | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 contrib/amcheck/t/008_repack_2.pl diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index cb4bc32e98a..6799df214f9 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -51,6 +51,7 @@ tests += { 't/005_pitr.pl', 't/006_verify_gin.pl', 't/007_repack_1.pl', + 't/008_repack_2.pl', ], }, } diff --git a/contrib/amcheck/t/008_repack_2.pl b/contrib/amcheck/t/008_repack_2.pl new file mode 100644 index 00000000000..a287ee2bb71 --- /dev/null +++ b/contrib/amcheck/t/008_repack_2.pl @@ -0,0 +1,111 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +# PG_TEST_EXTRA carries a numerical stress value; 0 disables the test, +# 1 means the test takes about 6 seconds, and the increase should be +# roughly linear. +my $matched = ($ENV{PG_TEST_EXTRA} // '') =~ /\bstress_concurrently(?:=(?<stressval>[0-9]*))?\b/; +my $stressval = $+{stressval} // 1; +if (!$matched or $stressval == 0) +{ + plan skip_all => 'skipping disabled REPACK CONCURRENTLY stress test'; +} + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); + +my $duration = 6 * $stressval; +my $no_hot = int(rand(2)); + +$node->start; +$node->safe_psql('postgres', q(CREATE TABLE tbl(id SERIAL PRIMARY KEY, val int))); +if ($no_hot) +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(val);)); +} +else +{ + $node->safe_psql('postgres', q(CREATE INDEX test_idx ON tbl(id);)); +} + +# Load amcheck +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); + +my $sum = $node->safe_psql('postgres', q( + SELECT SUM(val) AS sum FROM tbl +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE last_j START 1 INCREMENT 1;)); + + +$node->pgbench( +"--no-vacuum --client=30 --jobs=4 --exit-on-abort -T $duration", +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REINDEX/CREATE INDEX CONCURRENTLY', +{ + 'concurrent_ops' => qq( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \\gset + \\if :gotlock + REPACK (CONCURRENTLY) tbl USING INDEX tbl_pkey; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl USING INDEX test_idx; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + REPACK (CONCURRENTLY) tbl; + SELECT bt_index_parent_check('tbl_pkey', heapallindexed => true); + SELECT bt_index_parent_check('test_idx', heapallindexed => true); + \\sleep 10 ms + + SELECT pg_advisory_unlock(42); + \\else + SELECT pg_advisory_lock(43); + BEGIN; + INSERT INTO tbl(val) VALUES (nextval('last_j')) RETURNING val \\gset p_ + COMMIT; + SELECT pg_advisory_unlock(43); + \\sleep 1 ms + + BEGIN + --TRANSACTION ISOLATION LEVEL REPEATABLE READ + ; + SELECT 1; + \\sleep 1 ms + SELECT COUNT(*) AS count FROM tbl WHERE val <= :p_j \\gset p_ + \\if :p_count != :p_j + COMMIT; + SELECT (:p_count) / 0; + \\endif + + COMMIT; + \\endif + ) +}); + +$node->stop; +done_testing(); -- 2.47.3 --tbdehtstrqwksfdh Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0003-Distinguish-properly-when-database-specific-transact.patch" ^ permalink raw reply [nested|flat] 377+ messages in thread
* [PATCH v2] Make propgraph object descriptions translatable @ 2026-06-02 03:07 Kyotaro Horiguchi <horikyota.ntt@gmail.com> 0 siblings, 0 replies; 377+ messages in thread From: Kyotaro Horiguchi @ 2026-06-02 03:07 UTC (permalink / raw) getObjectDescription() currently constructs propgraph-related object descriptions incrementally with appendStringInfo(). This effectively fixes the word order in English, which makes the messages difficult to translate naturally into languages such as Japanese. --- src/backend/catalog/objectaddress.c | 56 +++++++++++++++++++---------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 050b7829eb0..9eb574f5ccc 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -4077,6 +4077,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) { HeapTuple tup; Form_pg_propgraph_element pgeform; + StringInfoData objdesc; + + initStringInfo(&objdesc); tup = SearchSysCache1(PROPGRAPHELOID, ObjectIdGetDatum(object->objectId)); if (!HeapTupleIsValid(tup)) @@ -4089,16 +4092,16 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) pgeform = (Form_pg_propgraph_element) GETSTRUCT(tup); + getRelationDescription(&objdesc, pgeform->pgepgid, false); + if (pgeform->pgekind == PGEKIND_VERTEX) - /* translator: followed by, e.g., "property graph %s" */ - appendStringInfo(&buffer, _("vertex %s of "), NameStr(pgeform->pgealias)); + appendStringInfo(&buffer, _("vertex %s of %s"), NameStr(pgeform->pgealias), objdesc.data); else if (pgeform->pgekind == PGEKIND_EDGE) - /* translator: followed by, e.g., "property graph %s" */ - appendStringInfo(&buffer, _("edge %s of "), NameStr(pgeform->pgealias)); + appendStringInfo(&buffer, _("edge %s of %s"), NameStr(pgeform->pgealias), objdesc.data); else - appendStringInfo(&buffer, "??? element %s of ", NameStr(pgeform->pgealias)); - getRelationDescription(&buffer, pgeform->pgepgid, false); + appendStringInfo(&buffer, "??? element %s of %s", NameStr(pgeform->pgealias), objdesc.data); + pfree(objdesc.data); ReleaseSysCache(tup); break; } @@ -4109,6 +4112,7 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) HeapTuple tuple; Form_pg_propgraph_element_label pgelform; ObjectAddress oa; + char *objdesc; rel = table_open(PropgraphElementLabelRelationId, AccessShareLock); tuple = get_catalog_object_by_oid(rel, @@ -4125,10 +4129,13 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) pgelform = (Form_pg_propgraph_element_label) GETSTRUCT(tuple); - appendStringInfo(&buffer, _("label %s of "), get_propgraph_label_name(pgelform->pgellabelid)); - ObjectAddressSet(oa, PropgraphElementRelationId, pgelform->pgelelid); - appendStringInfoString(&buffer, getObjectDescription(&oa, false)); + ObjectAddressSet(oa, PropgraphElementRelationId, + pgelform->pgelelid); + objdesc = getObjectDescription(&oa, false); + appendStringInfo(&buffer, _("label %s of %s"), get_propgraph_label_name(pgelform->pgellabelid), objdesc); + + pfree(objdesc); table_close(rel, AccessShareLock); break; } @@ -4137,6 +4144,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) { HeapTuple tuple; Form_pg_propgraph_label pglform; + StringInfoData objdesc; + + initStringInfo(&objdesc); tuple = SearchSysCache1(PROPGRAPHLABELOID, ObjectIdGetDatum(object->objectId)); if (!HeapTupleIsValid(tuple)) @@ -4148,9 +4158,11 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) pglform = (Form_pg_propgraph_label) GETSTRUCT(tuple); - /* translator: followed by, e.g., "property graph %s" */ - appendStringInfo(&buffer, _("label %s of "), NameStr(pglform->pgllabel)); - getRelationDescription(&buffer, pglform->pglpgid, false); + getRelationDescription(&objdesc, pglform->pglpgid, false); + + appendStringInfo(&buffer, _("label %s of %s"), NameStr(pglform->pgllabel), objdesc.data); + + pfree(objdesc.data); ReleaseSysCache(tuple); break; } @@ -4161,6 +4173,7 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) HeapTuple tuple; Form_pg_propgraph_label_property plpform; ObjectAddress oa; + char *objdesc; rel = table_open(PropgraphLabelPropertyRelationId, AccessShareLock); tuple = get_catalog_object_by_oid(rel, @@ -4177,10 +4190,13 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) plpform = (Form_pg_propgraph_label_property) GETSTRUCT(tuple); - appendStringInfo(&buffer, _("property %s of "), get_propgraph_property_name(plpform->plppropid)); - ObjectAddressSet(oa, PropgraphElementLabelRelationId, plpform->plpellabelid); - appendStringInfoString(&buffer, getObjectDescription(&oa, false)); + ObjectAddressSet(oa, PropgraphElementLabelRelationId, + plpform->plpellabelid); + objdesc = getObjectDescription(&oa, false); + appendStringInfo(&buffer, _("property %s of %s"), get_propgraph_property_name(plpform->plppropid), objdesc); + + pfree(objdesc); table_close(rel, AccessShareLock); break; } @@ -4189,6 +4205,9 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) { HeapTuple tuple; Form_pg_propgraph_property pgpform; + StringInfoData objdesc; + + initStringInfo(&objdesc); tuple = SearchSysCache1(PROPGRAPHPROPOID, ObjectIdGetDatum(object->objectId)); if (!HeapTupleIsValid(tuple)) @@ -4200,9 +4219,10 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) pgpform = (Form_pg_propgraph_property) GETSTRUCT(tuple); - /* translator: followed by, e.g., "property graph %s" */ - appendStringInfo(&buffer, _("property %s of "), NameStr(pgpform->pgpname)); - getRelationDescription(&buffer, pgpform->pgppgid, false); + getRelationDescription(&objdesc, pgpform->pgppgid, false); + + appendStringInfo(&buffer, _("property %s of %s"), NameStr(pgpform->pgpname), objdesc.data); + pfree(objdesc.data); ReleaseSysCache(tuple); break; } -- 2.52.0 ----Next_Part(Tue_Jun__2_13_43_56_2026_572)---- ^ permalink raw reply [nested|flat] 377+ messages in thread
end of thread, other threads:[~2026-06-02 03:07 UTC | newest] Thread overview: 377+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2020-02-24 13:53 [PATCH 01/11] Don't use EV_CLEAR for kqueue events. Thomas Munro <thomas.munro@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2025-12-13 17:46 [PATCH 2/3] one more stress test for repack concurrently Mikhail Nikalayeu <mihailnikalayeu@gmail.com> 2026-06-02 03:07 [PATCH v2] Make propgraph object descriptions translatable Kyotaro Horiguchi <horikyota.ntt@gmail.com>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox