From ef3d301697afabc3ad121dccbbcaba0149d1df25 Mon Sep 17 00:00:00 2001 From: "Andrey M. Borodin" Date: Thu, 10 Feb 2022 21:47:44 +0500 Subject: [PATCH] Try to check indexes on standby --- contrib/amcheck/t/002_cic.pl | 48 +++++++++++++-------- contrib/amcheck/t/003_cic_2pc.pl | 53 +++++++++++++----------- src/test/perl/PostgreSQL/Test/Cluster.pm | 48 +++++++++++++++++++++ 3 files changed, 108 insertions(+), 41 deletions(-) diff --git a/contrib/amcheck/t/002_cic.pl b/contrib/amcheck/t/002_cic.pl index f6b91e89ad..58689423c9 100644 --- a/contrib/amcheck/t/002_cic.pl +++ b/contrib/amcheck/t/002_cic.pl @@ -9,7 +9,7 @@ use Config; use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; -use Test::More tests => 3; +use Test::More tests => 4; my ($node, $result); @@ -25,18 +25,32 @@ $node->safe_psql('postgres', q(CREATE TABLE tbl(i int))); $node->safe_psql('postgres', q(CREATE INDEX idx ON tbl(i))); # -# Stress CIC with pgbench. -# -# pgbench might try to launch more than one instance of the CIC -# transaction concurrently. That would deadlock, so use an advisory -# lock to ensure only one CIC runs at a time. +# Stress CIC with pgbench # + +# Run background pgbench with CIC. We cannot mix-in this script into single +# pgbench: CIC will deadlock with itself occasionally. +my $pgbench_out = ''; +my $pgbench_timer = IPC::Run::timeout(180); +my $pgbench_h = $node->background_pgbench( + '--no-vacuum --client=1 --transactions=200', + { + '002_pgbench_concurrent_cic' => q( + DROP INDEX CONCURRENTLY idx; + CREATE INDEX CONCURRENTLY idx ON tbl(i); + SELECT bt_index_check('idx',true); + ) + }, + \$pgbench_out, + $pgbench_timer); + +# Run pgbench. $node->pgbench( - '--no-vacuum --client=5 --transactions=100', + '--no-vacuum --client=5 --transactions=200', 0, [qr{actually processed}], [qr{^$}], - 'concurrent INSERTs and CIC', + 'concurrent INSERTs', { '002_pgbench_concurrent_transaction' => q( BEGIN; @@ -48,17 +62,17 @@ $node->pgbench( SAVEPOINT s1; INSERT INTO tbl VALUES(0); COMMIT; - ), - '002_pgbench_concurrent_cic' => q( - SELECT pg_try_advisory_lock(42)::integer AS gotlock \gset - \if :gotlock - DROP INDEX CONCURRENTLY idx; - CREATE INDEX CONCURRENTLY idx ON tbl(i); - SELECT bt_index_check('idx',true); - SELECT pg_advisory_unlock(42); - \endif ) }); +$pgbench_h->pump_nb; +$pgbench_h->finish(); +$result = + ($Config{osname} eq "MSWin32") + ? ($pgbench_h->full_results)[0] + : $pgbench_h->result(0); +is($result, 0, "pgbench with CIC works"); + +# done $node->stop; done_testing(); diff --git a/contrib/amcheck/t/003_cic_2pc.pl b/contrib/amcheck/t/003_cic_2pc.pl index 2f804efb84..e78de60e64 100644 --- a/contrib/amcheck/t/003_cic_2pc.pl +++ b/contrib/amcheck/t/003_cic_2pc.pl @@ -9,7 +9,7 @@ use Config; use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; -use Test::More tests => 5; +use Test::More tests => 6; local $TODO = 'filesystem bug' if PostgreSQL::Test::Utils::has_wal_read_bug; @@ -134,52 +134,57 @@ is($result, '0', 'bt_index_check after 2PC and restart'); # # Stress CIC+2PC with pgbench # -# pgbench might try to launch more than one instance of the CIC -# transaction concurrently. That would deadlock, so use an advisory -# lock to ensure only one CIC runs at a time. # Fix broken index first $node->safe_psql('postgres', q(REINDEX TABLE tbl;)); +# Run background pgbench with CIC. We cannot mix-in this script into single +# pgbench: CIC will deadlock with itself occasionally. +my $pgbench_out = ''; +my $pgbench_timer = IPC::Run::timeout(180); +my $pgbench_h = $node->background_pgbench( + '--no-vacuum --client=1 --transactions=100', + { + '002_pgbench_concurrent_cic' => q( + DROP INDEX CONCURRENTLY idx; + CREATE INDEX CONCURRENTLY idx ON tbl(i); + SELECT bt_index_check('idx',true); + ) + }, + \$pgbench_out, + $pgbench_timer); + # Run pgbench. $node->pgbench( '--no-vacuum --client=5 --transactions=100', 0, [qr{actually processed}], [qr{^$}], - 'concurrent INSERTs w/ 2PC and CIC', + 'concurrent INSERTs w/ 2PC', { - '003_pgbench_concurrent_2pc' => q( + '002_pgbench_concurrent_2pc' => q( BEGIN; INSERT INTO tbl VALUES(0); PREPARE TRANSACTION 'c:client_id'; COMMIT PREPARED 'c:client_id'; ), - '003_pgbench_concurrent_2pc_savepoint' => q( + '002_pgbench_concurrent_2pc_savepoint' => q( BEGIN; SAVEPOINT s1; INSERT INTO tbl VALUES(0); PREPARE TRANSACTION 'c:client_id'; COMMIT PREPARED 'c:client_id'; - ), - '003_pgbench_concurrent_cic' => q( - SELECT pg_try_advisory_lock(42)::integer AS gotlock \gset - \if :gotlock - DROP INDEX CONCURRENTLY idx; - CREATE INDEX CONCURRENTLY idx ON tbl(i); - SELECT bt_index_check('idx',true); - SELECT pg_advisory_unlock(42); - \endif - ), - '004_pgbench_concurrent_ric' => q( - SELECT pg_try_advisory_lock(42)::integer AS gotlock \gset - \if :gotlock - REINDEX INDEX CONCURRENTLY idx; - SELECT bt_index_check('idx',true); - SELECT pg_advisory_unlock(42); - \endif ) }); +$pgbench_h->pump_nb; +$pgbench_h->finish(); +$result = + ($Config{osname} eq "MSWin32") + ? ($pgbench_h->full_results)[0] + : $pgbench_h->result(0); +is($result, 0, "pgbench with CIC works"); + +# done $node->stop; done_testing(); diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm index 41beadff9d..8041092edb 100644 --- a/src/test/perl/PostgreSQL/Test/Cluster.pm +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm @@ -2142,6 +2142,54 @@ sub pgbench =pod +=item $node->background_pgbench($opts, $files, \$stdout, $timer) => harness + +Invoke B and return an IPC::Run harness object. The process's stdin +is empty, and its stdout and stderr go to the $stdout scalar reference. This +allows the caller to act on other parts of the system while B is +running. Errors from B are the caller's problem. + +The specified timer object is attached to the harness, as well. It's caller's +responsibility to select the timeout length, and to restart the timer after +each command if the timeout is per-command. + +Be sure to "finish" the harness when done with it. + +=over + +=item $opts + +Options as a string to be split on spaces. + +=item $files + +Reference to filename/contents dictionary. + +=back + +=cut + +sub background_pgbench +{ + my ($self, $opts, $files, $stdout, $timer) = @_; + + my @cmd = + ('pgbench', split(/\s+/, $opts), $self->_pgbench_make_files($files)); + + local %ENV = $self->_get_env(); + + my $stdin = ""; + # IPC::Run would otherwise append to existing contents: + $$stdout = "" if ref($stdout); + + my $harness = IPC::Run::start \@cmd, '<', \$stdin, '>', $stdout, '2>&1', + $timer; + + return $harness; +} + +=pod + =item $node->connect_ok($connstr, $test_name, %params) Attempt a connection with a custom connection string. This is expected -- 2.32.0 (Apple Git-132)