aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/lmgr/predicate.c5
-rw-r--r--src/test/isolation/expected/matview-write-skew.out121
-rw-r--r--src/test/isolation/isolation_schedule1
-rw-r--r--src/test/isolation/specs/matview-write-skew.spec51
4 files changed, 175 insertions, 3 deletions
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index e8120174d61..df1c0d72e97 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -490,14 +490,13 @@ static void ReleasePredicateLocksLocal(void);
/*
* Does this relation participate in predicate locking? Temporary and system
- * relations are exempt, as are materialized views.
+ * relations are exempt.
*/
static inline bool
PredicateLockingNeededForRelation(Relation relation)
{
return !(relation->rd_id < FirstUnpinnedObjectId ||
- RelationUsesLocalBuffers(relation) ||
- relation->rd_rel->relkind == RELKIND_MATVIEW);
+ RelationUsesLocalBuffers(relation));
}
/*
diff --git a/src/test/isolation/expected/matview-write-skew.out b/src/test/isolation/expected/matview-write-skew.out
new file mode 100644
index 00000000000..4c8eaf5ae89
--- /dev/null
+++ b/src/test/isolation/expected/matview-write-skew.out
@@ -0,0 +1,121 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1_begin s2_begin s1_refresh s2_read s2_insert s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s2_insert: INSERT INTO orders VALUES ('2022-04-02', 'orange', 15);
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: s1_begin s2_begin s1_refresh s2_read s2_update s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s2_update: UPDATE orders SET num = num + 1;
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: s1_begin s2_begin s2_read s1_refresh s2_insert s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s2_insert: INSERT INTO orders VALUES ('2022-04-02', 'orange', 15);
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: s1_begin s2_begin s2_read s1_refresh s2_update s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s2_update: UPDATE orders SET num = num + 1;
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: s1_begin s2_begin s2_read s2_insert s1_refresh s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s2_insert: INSERT INTO orders VALUES ('2022-04-02', 'orange', 15);
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: s1_begin s2_begin s2_read s2_update s1_refresh s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s2_update: UPDATE orders SET num = num + 1;
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: s1_begin s2_begin s1_refresh s2_insert s2_read s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s2_insert: INSERT INTO orders VALUES ('2022-04-02', 'orange', 15);
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: s1_begin s2_begin s1_refresh s2_update s2_read s1_commit s2_commit
+step s1_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2_begin: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s1_refresh: REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
+step s2_update: UPDATE orders SET num = num + 1;
+step s2_read: SELECT max(date) FROM order_summary;
+ max
+----------
+04-01-2022
+(1 row)
+
+step s1_commit: COMMIT;
+step s2_commit: COMMIT;
+ERROR: could not serialize access due to read/write dependencies among transactions
diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule
index 5413a59a807..c11dc9a4202 100644
--- a/src/test/isolation/isolation_schedule
+++ b/src/test/isolation/isolation_schedule
@@ -108,3 +108,4 @@ test: cluster-conflict-partition
test: truncate-conflict
test: serializable-parallel
test: serializable-parallel-2
+test: matview-write-skew
diff --git a/src/test/isolation/specs/matview-write-skew.spec b/src/test/isolation/specs/matview-write-skew.spec
new file mode 100644
index 00000000000..5fe21f1fb5a
--- /dev/null
+++ b/src/test/isolation/specs/matview-write-skew.spec
@@ -0,0 +1,51 @@
+# Test write skew with a materialized view.
+#
+# This test uses two serializable transactions: one that refreshes a
+# materialized view containing a summary of some order information, and
+# one that looks at the materialized view while doing writes on its
+# parent relation.
+#
+# Any overlap between the transactions should cause a serialization failure.
+
+setup
+{
+ CREATE TABLE orders (date date, item text, num int);
+ INSERT INTO orders VALUES ('2022-04-01', 'apple', 10), ('2022-04-01', 'banana', 20);
+
+ CREATE MATERIALIZED VIEW order_summary AS
+ SELECT date, item, sum(num) FROM orders GROUP BY date, item;
+ CREATE UNIQUE INDEX ON order_summary(date, item);
+ -- Create a diff between the summary table and the parent orders.
+ INSERT INTO orders VALUES ('2022-04-02', 'apple', 20);
+}
+
+teardown
+{
+ DROP MATERIALIZED VIEW order_summary;
+ DROP TABLE orders;
+}
+
+session s1
+step s1_begin { BEGIN ISOLATION LEVEL SERIALIZABLE; }
+step s1_refresh { REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary; }
+step s1_commit { COMMIT; }
+
+session s2
+step s2_begin { BEGIN ISOLATION LEVEL SERIALIZABLE; }
+step s2_read { SELECT max(date) FROM order_summary; }
+step s2_insert { INSERT INTO orders VALUES ('2022-04-02', 'orange', 15); }
+step s2_update { UPDATE orders SET num = num + 1; }
+step s2_commit { COMMIT; }
+
+# refresh -> read -> write
+permutation "s1_begin" "s2_begin" "s1_refresh" "s2_read" "s2_insert" "s1_commit" "s2_commit"
+permutation "s1_begin" "s2_begin" "s1_refresh" "s2_read" "s2_update" "s1_commit" "s2_commit"
+# read -> refresh -> write
+permutation "s1_begin" "s2_begin" "s2_read" "s1_refresh" "s2_insert" "s1_commit" "s2_commit"
+permutation "s1_begin" "s2_begin" "s2_read" "s1_refresh" "s2_update" "s1_commit" "s2_commit"
+# read -> write -> refresh
+permutation "s1_begin" "s2_begin" "s2_read" "s2_insert" "s1_refresh" "s1_commit" "s2_commit"
+permutation "s1_begin" "s2_begin" "s2_read" "s2_update" "s1_refresh" "s1_commit" "s2_commit"
+# refresh -> write -> read
+permutation "s1_begin" "s2_begin" "s1_refresh" "s2_insert" "s2_read" "s1_commit" "s2_commit"
+permutation "s1_begin" "s2_begin" "s1_refresh" "s2_update" "s2_read" "s1_commit" "s2_commit"