summaryrefslogtreecommitdiff
path: root/src/test/isolation
diff options
context:
space:
mode:
authorMichael Paquier2020-09-08 01:09:22 +0000
committerMichael Paquier2020-09-08 01:09:22 +0000
commita6642b3ae060976b42830b7dc8f29ec190ab05e4 (patch)
tree1a95529f5569ac9d87b4785a4e2b00b0f04f78df /src/test/isolation
parenta547e6867527ca16628a3fb1cf3ef6f785210a31 (diff)
Add support for partitioned tables and indexes in REINDEX
Until now, REINDEX was not able to work with partitioned tables and indexes, forcing users to reindex partitions one by one. This extends REINDEX INDEX and REINDEX TABLE so as they can accept a partitioned index and table in input, respectively, to reindex all the partitions assigned to them with physical storage (foreign tables, partitioned tables and indexes are then discarded). This shares some logic with schema and database REINDEX as each partition gets processed in its own transaction after building a list of relations to work on. This choice has the advantage to minimize the number of invalid indexes to one partition with REINDEX CONCURRENTLY in the event a cancellation or failure in-flight, as the only indexes handled at once in a single REINDEX CONCURRENTLY loop are the ones from the partition being working on. Isolation tests are added to emulate some cases I bumped into while developing this feature, particularly with the concurrent drop of a leaf partition reindexed. However, this is rather limited as LOCK would cause REINDEX to block in the first transaction building the list of partitions. Per its multi-transaction nature, this new flavor cannot run in a transaction block, similarly to REINDEX SCHEMA, SYSTEM and DATABASE. Author: Justin Pryzby, Michael Paquier Reviewed-by: Anastasia Lubennikova Discussion: https://postgr.es/m/db12e897-73ff-467e-94cb-4af03705435f.adger.lj@alibaba-inc.com
Diffstat (limited to 'src/test/isolation')
-rw-r--r--src/test/isolation/expected/reindex-partitions.out107
-rw-r--r--src/test/isolation/isolation_schedule1
-rw-r--r--src/test/isolation/specs/reindex-partitions.spec59
3 files changed, 167 insertions, 0 deletions
diff --git a/src/test/isolation/expected/reindex-partitions.out b/src/test/isolation/expected/reindex-partitions.out
new file mode 100644
index 00000000000..5373abde259
--- /dev/null
+++ b/src/test/isolation/expected/reindex-partitions.out
@@ -0,0 +1,107 @@
+Parsed test spec with 3 sessions
+
+starting permutation: begin1 lockexcl1 reindex2 drop3 end1
+step begin1: BEGIN;
+step lockexcl1: LOCK reind_conc_parent IN ACCESS EXCLUSIVE MODE;
+step reindex2: REINDEX TABLE reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockexcl1 reindex_conc2 drop3 end1
+step begin1: BEGIN;
+step lockexcl1: LOCK reind_conc_parent IN ACCESS EXCLUSIVE MODE;
+step reindex_conc2: REINDEX TABLE CONCURRENTLY reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex_conc2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockshare1 reindex2 drop3 end1
+step begin1: BEGIN;
+step lockshare1: LOCK reind_conc_parent IN SHARE MODE;
+step reindex2: REINDEX TABLE reind_conc_parent;
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step drop3: <... completed>
+
+starting permutation: begin1 lockshare1 reindex_conc2 drop3 end1
+step begin1: BEGIN;
+step lockshare1: LOCK reind_conc_parent IN SHARE MODE;
+step reindex_conc2: REINDEX TABLE CONCURRENTLY reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex_conc2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockupdate1 reindex2 drop3 end1
+step begin1: BEGIN;
+step lockupdate1: LOCK reind_conc_parent IN SHARE UPDATE EXCLUSIVE MODE;
+step reindex2: REINDEX TABLE reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockupdate1 reindex_conc2 drop3 end1
+step begin1: BEGIN;
+step lockupdate1: LOCK reind_conc_parent IN SHARE UPDATE EXCLUSIVE MODE;
+step reindex_conc2: REINDEX TABLE CONCURRENTLY reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex_conc2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockpartexcl1 reindex2 drop3 end1
+step begin1: BEGIN;
+step lockpartexcl1: LOCK reind_conc_10_20 IN ACCESS EXCLUSIVE MODE;
+step reindex2: REINDEX TABLE reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockpartexcl1 reindex_conc2 drop3 end1
+step begin1: BEGIN;
+step lockpartexcl1: LOCK reind_conc_10_20 IN ACCESS EXCLUSIVE MODE;
+step reindex_conc2: REINDEX TABLE CONCURRENTLY reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex_conc2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockpartshare1 reindex2 drop3 end1
+step begin1: BEGIN;
+step lockpartshare1: LOCK reind_conc_10_20 IN SHARE MODE;
+step reindex2: REINDEX TABLE reind_conc_parent;
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step drop3: <... completed>
+
+starting permutation: begin1 lockpartshare1 reindex_conc2 drop3 end1
+step begin1: BEGIN;
+step lockpartshare1: LOCK reind_conc_10_20 IN SHARE MODE;
+step reindex_conc2: REINDEX TABLE CONCURRENTLY reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex_conc2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockpartupdate1 reindex2 drop3 end1
+step begin1: BEGIN;
+step lockpartupdate1: LOCK reind_conc_10_20 IN SHARE UPDATE EXCLUSIVE MODE;
+step reindex2: REINDEX TABLE reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex2: <... completed>
+step drop3: <... completed>
+
+starting permutation: begin1 lockpartupdate1 reindex_conc2 drop3 end1
+step begin1: BEGIN;
+step lockpartupdate1: LOCK reind_conc_10_20 IN SHARE UPDATE EXCLUSIVE MODE;
+step reindex_conc2: REINDEX TABLE CONCURRENTLY reind_conc_parent; <waiting ...>
+step drop3: DROP TABLE reind_conc_10_20; <waiting ...>
+step end1: COMMIT;
+step reindex_conc2: <... completed>
+step drop3: <... completed>
diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule
index 6acbb695ece..65d1443ac68 100644
--- a/src/test/isolation/isolation_schedule
+++ b/src/test/isolation/isolation_schedule
@@ -50,6 +50,7 @@ test: lock-committed-keyupdate
test: update-locked-tuple
test: reindex-concurrently
test: reindex-schema
+test: reindex-partitions
test: propagate-lock-delete
test: tuplelock-conflict
test: tuplelock-update
diff --git a/src/test/isolation/specs/reindex-partitions.spec b/src/test/isolation/specs/reindex-partitions.spec
new file mode 100644
index 00000000000..1a4dd1bf287
--- /dev/null
+++ b/src/test/isolation/specs/reindex-partitions.spec
@@ -0,0 +1,59 @@
+# REINDEX with partitioned tables
+#
+# Ensure that concurrent and non-concurrent operations work correctly when
+# a REINDEX is performed on a partitioned table or index.
+
+# In the cases dealt with here, partition leaves are dropped in parallel of
+# a REINDEX. DROP TABLE gets blocked by the first transaction of REINDEX
+# building the list of partitions, so it will finish executing once REINDEX
+# is done.
+
+setup
+{
+ CREATE TABLE reind_conc_parent (id int) PARTITION BY RANGE (id);
+ CREATE TABLE reind_conc_0_10 PARTITION OF reind_conc_parent
+ FOR VALUES FROM (0) TO (10);
+ CREATE TABLE reind_conc_10_20 PARTITION OF reind_conc_parent
+ FOR VALUES FROM (10) TO (20);
+ INSERT INTO reind_conc_parent VALUES (generate_series(0, 19));
+}
+
+teardown
+{
+ DROP TABLE reind_conc_parent;
+}
+
+session "s1"
+step "begin1" { BEGIN; }
+step "lockexcl1" { LOCK reind_conc_parent IN ACCESS EXCLUSIVE MODE; }
+step "lockshare1" { LOCK reind_conc_parent IN SHARE MODE; }
+step "lockupdate1" { LOCK reind_conc_parent IN SHARE UPDATE EXCLUSIVE MODE; }
+step "lockpartexcl1" { LOCK reind_conc_10_20 IN ACCESS EXCLUSIVE MODE; }
+step "lockpartshare1" { LOCK reind_conc_10_20 IN SHARE MODE; }
+step "lockpartupdate1" { LOCK reind_conc_10_20 IN SHARE UPDATE EXCLUSIVE MODE; }
+step "end1" { COMMIT; }
+
+session "s2"
+step "reindex2" { REINDEX TABLE reind_conc_parent; }
+step "reindex_conc2" { REINDEX TABLE CONCURRENTLY reind_conc_parent; }
+
+session "s3"
+step "drop3" { DROP TABLE reind_conc_10_20; }
+
+# An existing partition leaf is dropped after reindex is done when the
+# parent is locked.
+permutation "begin1" "lockexcl1" "reindex2" "drop3" "end1"
+permutation "begin1" "lockexcl1" "reindex_conc2" "drop3" "end1"
+permutation "begin1" "lockshare1" "reindex2" "drop3" "end1"
+permutation "begin1" "lockshare1" "reindex_conc2" "drop3" "end1"
+permutation "begin1" "lockupdate1" "reindex2" "drop3" "end1"
+permutation "begin1" "lockupdate1" "reindex_conc2" "drop3" "end1"
+
+# An existing partition leaf is dropped after reindex is done when this
+# leaf is locked.
+permutation "begin1" "lockpartexcl1" "reindex2" "drop3" "end1"
+permutation "begin1" "lockpartexcl1" "reindex_conc2" "drop3" "end1"
+permutation "begin1" "lockpartshare1" "reindex2" "drop3" "end1"
+permutation "begin1" "lockpartshare1" "reindex_conc2" "drop3" "end1"
+permutation "begin1" "lockpartupdate1" "reindex2" "drop3" "end1"
+permutation "begin1" "lockpartupdate1" "reindex_conc2" "drop3" "end1"