aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2021-01-30 00:00:27 -0800
committerNoah Misch <noah@leadboat.com>2021-01-30 00:00:27 -0800
commit8a54e12a38d1545d249f1402f66c8cde2837d97c (patch)
treed6b155a68f9e3dc21f1061106320c620eeaeb6ed /src/test
parentf77717b2985aa529a185e6988de26b885ca10ddb (diff)
downloadpostgresql-8a54e12a38d1545d249f1402f66c8cde2837d97c.tar.gz
postgresql-8a54e12a38d1545d249f1402f66c8cde2837d97c.zip
Fix CREATE INDEX CONCURRENTLY for simultaneous prepared transactions.
In a cluster having used CREATE INDEX CONCURRENTLY while having enabled prepared transactions, queries that use the resulting index can silently fail to find rows. Fix this for future CREATE INDEX CONCURRENTLY by making it wait for prepared transactions like it waits for ordinary transactions. This expands the VirtualTransactionId structure domain to admit prepared transactions. It may be necessary to reindex to recover from past occurrences. Back-patch to 9.5 (all supported versions). Andrey Borodin, reviewed (in earlier versions) by Tom Lane and Michael Paquier. Discussion: https://postgr.es/m/2E712143-97F7-4890-B470-4A35142ABC82@yandex-team.ru
Diffstat (limited to 'src/test')
-rw-r--r--src/test/isolation/Makefile11
-rw-r--r--src/test/isolation/README6
-rw-r--r--src/test/isolation/expected/prepared-transactions-cic.out18
-rw-r--r--src/test/isolation/specs/prepared-transactions-cic.spec37
4 files changed, 63 insertions, 9 deletions
diff --git a/src/test/isolation/Makefile b/src/test/isolation/Makefile
index d23e2cec640..edff04f041c 100644
--- a/src/test/isolation/Makefile
+++ b/src/test/isolation/Makefile
@@ -62,12 +62,11 @@ installcheck: all
check: all
$(pg_isolation_regress_check) --schedule=$(srcdir)/isolation_schedule
-# Versions of the check tests that include the prepared-transactions test
-# It only makes sense to run these if set up to use prepared transactions,
-# via TEMP_CONFIG for the check case, or via the postgresql.conf for the
-# installcheck case.
+# Non-default tests. It only makes sense to run these if set up to use
+# prepared transactions, via TEMP_CONFIG for the check case, or via the
+# postgresql.conf for the installcheck case.
installcheck-prepared-txns: all temp-install
- $(pg_isolation_regress_installcheck) --schedule=$(srcdir)/isolation_schedule prepared-transactions
+ $(pg_isolation_regress_installcheck) --schedule=$(srcdir)/isolation_schedule prepared-transactions prepared-transactions-cic
check-prepared-txns: all temp-install
- $(pg_isolation_regress_check) --schedule=$(srcdir)/isolation_schedule prepared-transactions
+ $(pg_isolation_regress_check) --schedule=$(srcdir)/isolation_schedule prepared-transactions prepared-transactions-cic
diff --git a/src/test/isolation/README b/src/test/isolation/README
index 217953d1834..6ae71523258 100644
--- a/src/test/isolation/README
+++ b/src/test/isolation/README
@@ -23,9 +23,9 @@ you can do something like
./pg_isolation_regress fk-contention fk-deadlock
(look into the specs/ subdirectory to see the available tests).
-The prepared-transactions test requires the server's
-max_prepared_transactions parameter to be set to at least 3; therefore it
-is not run by default. To include it in the test run, use
+Certain tests require the server's max_prepared_transactions parameter to be
+set to at least 3; therefore they are not run by default. To include them in
+the test run, use
make check-prepared-txns
or
make installcheck-prepared-txns
diff --git a/src/test/isolation/expected/prepared-transactions-cic.out b/src/test/isolation/expected/prepared-transactions-cic.out
new file mode 100644
index 00000000000..043ec3c3636
--- /dev/null
+++ b/src/test/isolation/expected/prepared-transactions-cic.out
@@ -0,0 +1,18 @@
+Parsed test spec with 2 sessions
+
+starting permutation: w1 p1 cic2 c1 r2
+step w1: BEGIN; INSERT INTO cic_test VALUES (1);
+step p1: PREPARE TRANSACTION 's1';
+step cic2:
+ CREATE INDEX CONCURRENTLY on cic_test(a);
+
+ERROR: canceling statement due to lock timeout
+step c1: COMMIT PREPARED 's1';
+step r2:
+ SET enable_seqscan to off;
+ SET enable_bitmapscan to off;
+ SELECT * FROM cic_test WHERE a = 1;
+
+a
+
+1
diff --git a/src/test/isolation/specs/prepared-transactions-cic.spec b/src/test/isolation/specs/prepared-transactions-cic.spec
new file mode 100644
index 00000000000..c39eaf5ad0c
--- /dev/null
+++ b/src/test/isolation/specs/prepared-transactions-cic.spec
@@ -0,0 +1,37 @@
+# This test verifies that CREATE INDEX CONCURRENTLY interacts with prepared
+# transactions correctly.
+setup
+{
+ CREATE TABLE cic_test (a int);
+}
+
+teardown
+{
+ DROP TABLE cic_test;
+}
+
+
+# Sessions for CREATE INDEX CONCURRENTLY test
+session "s1"
+step "w1" { BEGIN; INSERT INTO cic_test VALUES (1); }
+step "p1" { PREPARE TRANSACTION 's1'; }
+step "c1" { COMMIT PREPARED 's1'; }
+
+session "s2"
+# The isolation tester never recognizes that a lock of s1 blocks s2, because a
+# prepared transaction's locks have no pid associated. While there's a slight
+# chance of timeout while waiting for an autovacuum-held lock, that wouldn't
+# change the output. Hence, no timeout is too short.
+setup { SET lock_timeout = 10; }
+step "cic2"
+{
+ CREATE INDEX CONCURRENTLY on cic_test(a);
+}
+step "r2"
+{
+ SET enable_seqscan to off;
+ SET enable_bitmapscan to off;
+ SELECT * FROM cic_test WHERE a = 1;
+}
+
+permutation "w1" "p1" "cic2" "c1" "r2"