v14-0003-Introduce-TAP-test-for-2PC-with-CIC-behavior.patch

application/octet-stream

Filename: v14-0003-Introduce-TAP-test-for-2PC-with-CIC-behavior.patch
Type: application/octet-stream
Part: 2
Message: Re: CREATE INDEX CONCURRENTLY does not index prepared xact's data

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v14-0003
Subject: Introduce TAP test for 2PC with CIC behavior
File+
contrib/amcheck/t/003_cic_2pc.pl 187 0
From 9ad741421cba4c6906078f76cb7d118cdde96eff Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Sun, 8 Aug 2021 14:46:50 +0500
Subject: [PATCH v14 3/6] Introduce TAP test for 2PC with CIC behavior

Currently there are two set of tests:
1. Deterministic reproduction of the bug with 3 psql sessions
   This set also checks that 2PC interacts with CIC correctly
   even after restart.
2. Probablistic reproduction of the bug with 2 pgbench sessions
---
 contrib/amcheck/t/003_cic_2pc.pl | 187 +++++++++++++++++++++++++++++++
 1 file changed, 187 insertions(+)
 create mode 100644 contrib/amcheck/t/003_cic_2pc.pl

diff --git a/contrib/amcheck/t/003_cic_2pc.pl b/contrib/amcheck/t/003_cic_2pc.pl
new file mode 100644
index 0000000000..101a0fea0b
--- /dev/null
+++ b/contrib/amcheck/t/003_cic_2pc.pl
@@ -0,0 +1,187 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test for CREATE INDEX CONCURRENTLY with prepared transactions
+use strict;
+use warnings;
+
+use Config;
+use PostgresNode;
+use TestLib;
+
+use Test::More tests => 6;
+
+my ($node, $result);
+
+#
+# Test set-up
+#
+$node = PostgresNode->new('CIC_2PC_test');
+$node->init;
+$node->append_conf('postgresql.conf', 'max_prepared_transactions = 10');
+$node->append_conf('postgresql.conf', 'lock_timeout = 5000');
+$node->start;
+$node->safe_psql('postgres', q(CREATE EXTENSION amcheck));
+$node->safe_psql('postgres', q(CREATE TABLE tbl(i int)));
+$node->safe_psql('postgres', q(CREATE INDEX idx on tbl(i)));
+
+
+#
+# Test 1. Run 3 overlapping 2PC transactions with concurrent reindex rebuild
+#
+# We have two concurrent background psqls: main_h for transaction and
+# reindex_h for cuncurrent reindex. Also we commit transactions from independent
+# psql's sometimes.
+#
+
+my $main_in  = '';
+my $main_out = '';
+my $main_timer = IPC::Run::timeout(180);
+
+my $main_h = $node->background_psql('postgres', \$main_in, \$main_out, $main_timer,
+	on_error_stop => 1);
+$main_in .= q(
+BEGIN;
+INSERT INTO tbl VALUES(0);
+\echo syncpoint1
+);
+pump $main_h until $main_out =~ /syncpoint1/ || $main_timer->is_expired;
+
+my $reindex_in  = '';
+my $reindex_out = '';
+my $reindex_timer = IPC::Run::timeout(180);
+my $reindex_h = $node->background_psql('postgres', \$reindex_in, \$reindex_out, $reindex_timer,
+	on_error_stop => 1);
+$reindex_in .= q(
+\echo start
+REINDEX TABLE CONCURRENTLY tbl;
+);
+pump $reindex_h until $reindex_out =~ /start/ || $reindex_timer->is_expired;
+
+$main_in .= q(
+PREPARE TRANSACTION 'a';
+);
+
+$main_in .= q(
+BEGIN;
+INSERT INTO tbl VALUES(0);
+\echo syncpoint2
+);
+pump $main_h until $main_out =~ /syncpoint2/ || $main_timer->is_expired;
+
+$node->safe_psql('postgres', q(COMMIT PREPARED 'a';));
+
+$main_in .= q(
+PREPARE TRANSACTION 'b';
+BEGIN;
+INSERT INTO tbl VALUES(0);
+\echo syncpoint3
+);
+pump $main_h until $main_out =~ /syncpoint3/ || $main_timer->is_expired;
+
+$node->safe_psql('postgres', q(COMMIT PREPARED 'b';));
+
+$main_in .= q(
+PREPARE TRANSACTION 'c';
+COMMIT PREPARED 'c';
+);
+$main_h->pump_nb;
+
+$main_h->finish;
+$reindex_h->finish;
+
+$result = $node->psql('postgres', q(SELECT bt_index_check('idx',true)));
+is($result, '0', 'bt_index_check checks index');
+
+
+#
+# Server restart shall not change whether prepared xact blocks CIC
+#
+
+$node->safe_psql('postgres', q(
+BEGIN;
+INSERT INTO tbl VALUES(0);
+PREPARE TRANSACTION 'spans_restart';
+BEGIN;
+CREATE TABLE unused ();
+PREPARE TRANSACTION 'persists_forever';
+));
+$node->restart;
+
+$reindex_in  = '';
+$reindex_out = '';
+$reindex_timer = IPC::Run::timeout(180);
+$reindex_h = $node->background_psql('postgres', \$reindex_in, \$reindex_out, $reindex_timer,
+	on_error_stop => 1);
+$reindex_in .= q(
+\echo start
+REINDEX TABLE CONCURRENTLY tbl;
+);
+pump $reindex_h until $reindex_out =~ /start/ || $reindex_timer->is_expired;
+
+$node->safe_psql('postgres', "COMMIT PREPARED 'spans_restart'");
+$reindex_h->finish;
+$result = $node->psql('postgres', q(SELECT bt_index_check('idx',true)));
+is($result, '0', 'bt_index_check checks index');
+
+
+#
+# Test 2. Stress CIC+2PC with pgbench
+#
+
+# Fix broken index first
+$node->safe_psql('postgres', q(REINDEX TABLE CONCURRENTLY tbl;));
+
+# Run background pgbench with CIC. We cannot mix-in this script into single pgbench:
+# CIC will deadlock with itself occasionally.
+my $pgbench_in  = '';
+my $pgbench_out = '';
+my $pgbench_timer = IPC::Run::timeout(180);
+my $pgbench_h = $node->background_pgbench('postgres', \$pgbench_in, \$pgbench_out, $pgbench_timer,
+	{
+		'002_pgbench_concurrent_cic' =>
+		  q(
+			REINDEX INDEX CONCURRENTLY idx;
+			SELECT bt_index_check('idx',true);
+		   )
+	},
+	'--no-vacuum --client=1 --transactions=100');
+
+# Run pgbench.
+$node->pgbench(
+	'--no-vacuum --client=5 --transactions=100',
+	0,
+	[qr{actually processed}],
+	[qr{^$}],
+	'concurrent CID and 2PC',
+	{
+		'002_pgbench_concurrent_2pc' =>
+		  q(
+			BEGIN;
+			INSERT INTO tbl VALUES(0);
+			PREPARE TRANSACTION 'c:client_id';
+			COMMIT PREPARED 'c:client_id';
+		  ),
+		'002_pgbench_concurrent_2pc_savepoint' =>
+		  q(
+			BEGIN;
+			SAVEPOINT s1;
+			INSERT INTO tbl VALUES(0);
+			PREPARE TRANSACTION 'c:client_id';
+			COMMIT PREPARED 'c:client_id';
+		  )
+	});
+
+$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->safe_psql('postgres', q(DROP TABLE tbl;));
+$node->stop;
+done_testing();
+
+# AUX stuff, taken from 001_pgbench_with_server.pl
\ No newline at end of file
-- 
2.24.3 (Apple Git-128)