summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorTeodor Sigaev2018-03-30 11:23:17 +0000
committerTeodor Sigaev2018-03-30 11:23:17 +0000
commit43d1ed60fdd96027f044e152176c0d45cd6bf443 (patch)
treeb5efc150a6cfa4d5edbc5ecbc828850097d0201f /src/test
parent019fa576ca8298ecb7b8ded6e0c857840b57a4ae (diff)
Predicate locking in GIN index
Predicate locks are used on per page basis only if fastupdate = off, in opposite case predicate lock on pending list will effectively lock whole index, to reduce locking overhead, just lock a relation. Entry and posting trees are essentially B-tree, so locks are acquired on leaf pages only. Author: Shubham Barai with some editorization by me and Dmitry Ivanov Review by: Alexander Korotkov, Dmitry Ivanov, Fedor Sigaev Discussion: https://www.postgresql.org/message-id/flat/CALxAEPt5sWW+EwTaKUGFL5_XFcZ0MuGBcyJ70oqbWqr42YKR8Q@mail.gmail.com
Diffstat (limited to 'src/test')
-rw-r--r--src/test/isolation/expected/predicate-gin.out756
-rw-r--r--src/test/isolation/isolation_schedule1
-rw-r--r--src/test/isolation/specs/predicate-gin.spec134
3 files changed, 891 insertions, 0 deletions
diff --git a/src/test/isolation/expected/predicate-gin.out b/src/test/isolation/expected/predicate-gin.out
new file mode 100644
index 00000000000..4f5501f6f01
--- /dev/null
+++ b/src/test/isolation/expected/predicate-gin.out
@@ -0,0 +1,756 @@
+Parsed test spec with 2 sessions
+
+starting permutation: rxy1 wx1 c1 rxy2 wy2 c2
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10050
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+
+starting permutation: rxy2 wy2 c2 rxy1 wx1 c1
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10050
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+
+starting permutation: rxy3 wx3 c1 rxy4 wy4 c2
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+
+starting permutation: rxy4 wy4 c2 rxy3 wx3 c1
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+
+starting permutation: rxy1 wx1 rxy2 c1 wy2 c2
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step c1: commit;
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+ERROR: could not serialize access due to read/write dependencies among transactions
+step c2: commit;
+
+starting permutation: rxy1 wx1 rxy2 wy2 c1 c2
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c1: commit;
+step c2: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 wx1 rxy2 wy2 c2 c1
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+step c1: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wx1 c1 wy2 c2
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+ERROR: could not serialize access due to read/write dependencies among transactions
+step c2: commit;
+
+starting permutation: rxy1 rxy2 wx1 wy2 c1 c2
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c1: commit;
+step c2: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wx1 wy2 c2 c1
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+step c1: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wy2 wx1 c1 c2
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step c2: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wy2 wx1 c2 c1
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c2: commit;
+step c1: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wy2 c2 wx1 c1
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+ERROR: could not serialize access due to read/write dependencies among transactions
+step c1: commit;
+
+starting permutation: rxy2 rxy1 wx1 c1 wy2 c2
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+ERROR: could not serialize access due to read/write dependencies among transactions
+step c2: commit;
+
+starting permutation: rxy2 rxy1 wx1 wy2 c1 c2
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c1: commit;
+step c2: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wx1 wy2 c2 c1
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+step c1: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wy2 wx1 c1 c2
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step c2: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wy2 wx1 c2 c1
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c2: commit;
+step c1: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wy2 c2 wx1 c1
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+ERROR: could not serialize access due to read/write dependencies among transactions
+step c1: commit;
+
+starting permutation: rxy2 wy2 rxy1 wx1 c1 c2
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step c2: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 wy2 rxy1 wx1 c2 c1
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c2: commit;
+step c1: commit;
+ERROR: could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 wy2 rxy1 c2 wx1 c1
+step rxy2: select count(*) from gin_tbl where p @> array[5,6];
+count
+
+10000
+step wy2: insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g;
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step c2: commit;
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+ERROR: could not serialize access due to read/write dependencies among transactions
+step c1: commit;
+
+starting permutation: rxy3 wx3 rxy4 c1 wy4 c2
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step c1: commit;
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+
+starting permutation: rxy3 wx3 rxy4 wy4 c1 c2
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy3 wx3 rxy4 wy4 c2 c1
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy3 rxy4 wx3 c1 wy4 c2
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+
+starting permutation: rxy3 rxy4 wx3 wy4 c1 c2
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy3 rxy4 wx3 wy4 c2 c1
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy3 rxy4 wy4 wx3 c1 c2
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy3 rxy4 wy4 wx3 c2 c1
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy3 rxy4 wy4 c2 wx3 c1
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+
+starting permutation: rxy4 rxy3 wx3 c1 wy4 c2
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+
+starting permutation: rxy4 rxy3 wx3 wy4 c1 c2
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy4 rxy3 wx3 wy4 c2 c1
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy4 rxy3 wy4 wx3 c1 c2
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy4 rxy3 wy4 wx3 c2 c1
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy4 rxy3 wy4 c2 wx3 c1
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step c2: commit;
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+
+starting permutation: rxy4 wy4 rxy3 wx3 c1 c2
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy4 wy4 rxy3 wx3 c2 c1
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy4 wy4 rxy3 c2 wx3 c1
+step rxy4: select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000];
+count
+
+4
+step wy4: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g;
+step rxy3: select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000];
+count
+
+4
+step c2: commit;
+step wx3: insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g;
+step c1: commit;
+
+starting permutation: rxy1 rxy2fu wx1 c1 wy2fu c2
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2fu: select count(*) from gin_tbl where p @> array[10000,10005];
+count
+
+0
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step wy2fu: insert into gin_tbl select g, array[10000,10005] from
+ generate_series(20051, 20100) g;
+step c2: commit;
+
+starting permutation: fu1 rxy1 rxy2fu wx1 c1 wy2fu c2
+step fu1: alter index ginidx set (fastupdate = on);
+ commit;
+ begin isolation level serializable;
+ set enable_seqscan=off;
+step rxy1: select count(*) from gin_tbl where p @> array[4,5];
+count
+
+10000
+step rxy2fu: select count(*) from gin_tbl where p @> array[10000,10005];
+count
+
+0
+step wx1: insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g;
+step c1: commit;
+step wy2fu: insert into gin_tbl select g, array[10000,10005] from
+ generate_series(20051, 20100) g;
+ERROR: could not serialize access due to read/write dependencies among transactions
+step c2: commit;
diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule
index 53e1f192b0b..d3965fe73f7 100644
--- a/src/test/isolation/isolation_schedule
+++ b/src/test/isolation/isolation_schedule
@@ -67,3 +67,4 @@ test: vacuum-reltuples
test: timeouts
test: vacuum-concurrent-drop
test: predicate-gist
+test: predicate-gin
diff --git a/src/test/isolation/specs/predicate-gin.spec b/src/test/isolation/specs/predicate-gin.spec
new file mode 100644
index 00000000000..9f0cda80573
--- /dev/null
+++ b/src/test/isolation/specs/predicate-gin.spec
@@ -0,0 +1,134 @@
+# Test for page level predicate locking in gin index
+#
+# Test to verify serialization failures and to check reduced false positives
+#
+# To verify serialization failures, queries and permutations are written in such
+# a way that an index scan (from one transaction) and an index insert (from
+# another transaction) will try to access the same part (sub-tree) of the index
+# whereas to check reduced false positives, they will try to access different
+# parts (sub-tree) of the index.
+
+
+setup
+{
+ create table gin_tbl(id int4, p int4[]);
+ insert into gin_tbl select g, array[g, g*2,g*3] from generate_series(1, 10000) g;
+ insert into gin_tbl select g, array[4,5,6] from generate_series(10001, 20000) g;
+ create index ginidx on gin_tbl using gin(p) with (fastupdate = off);
+}
+
+teardown
+{
+ drop table gin_tbl;
+}
+
+session "s1"
+setup
+{
+ begin isolation level serializable;
+ set enable_seqscan=off;
+}
+
+# enable pending list for a small subset of tests
+step "fu1" { alter index ginidx set (fastupdate = on);
+ commit;
+ begin isolation level serializable;
+ set enable_seqscan=off; }
+
+step "rxy1" { select count(*) from gin_tbl where p @> array[4,5]; }
+step "wx1" { insert into gin_tbl select g, array[5,6] from generate_series
+ (20001, 20050) g; }
+step "rxy3" { select count(*) from gin_tbl where p @> array[1,2] or
+ p @> array[100,200] or p @> array[500,1000] or p @> array[1000,2000]; }
+step "wx3" { insert into gin_tbl select g, array[g,g*2] from generate_series
+ (1, 50) g; }
+step "c1" { commit; }
+
+session "s2"
+setup
+{
+ begin isolation level serializable;
+ set enable_seqscan=off;
+}
+
+step "rxy2" { select count(*) from gin_tbl where p @> array[5,6]; }
+step "rxy2fu" { select count(*) from gin_tbl where p @> array[10000,10005]; }
+step "wy2" { insert into gin_tbl select g, array[4,5] from
+ generate_series(20051, 20100) g; }
+step "wy2fu" { insert into gin_tbl select g, array[10000,10005] from
+ generate_series(20051, 20100) g; }
+step "rxy4" { select count(*) from gin_tbl where p @> array[4000,8000] or
+ p @> array[5000,10000] or p @> array[6000,12000] or
+ p @> array[8000,16000]; }
+step "wy4" { insert into gin_tbl select g, array[g,g*2] from generate_series
+ (10000, 10050) g; }
+step "c2" { commit; }
+
+
+# An index scan (from one transaction) and an index insert (from another transaction)
+# try to access the same part of the index but one transaction commits before other
+# transaction begins so no r-w conflict.
+
+permutation "rxy1" "wx1" "c1" "rxy2" "wy2" "c2"
+permutation "rxy2" "wy2" "c2" "rxy1" "wx1" "c1"
+
+# An index scan (from one transaction) and an index insert (from another transaction)
+# try to access different parts of the index and also one transaction commits before
+# other transaction begins, so no r-w conflict.
+
+permutation "rxy3" "wx3" "c1" "rxy4" "wy4" "c2"
+permutation "rxy4" "wy4" "c2" "rxy3" "wx3" "c1"
+
+
+# An index scan (from one transaction) and an index insert (from another transaction)
+# try to access the same part of the index and one transaction begins before other
+# transaction commits so there is a r-w conflict.
+
+permutation "rxy1" "wx1" "rxy2" "c1" "wy2" "c2"
+permutation "rxy1" "wx1" "rxy2" "wy2" "c1" "c2"
+permutation "rxy1" "wx1" "rxy2" "wy2" "c2" "c1"
+permutation "rxy1" "rxy2" "wx1" "c1" "wy2" "c2"
+permutation "rxy1" "rxy2" "wx1" "wy2" "c1" "c2"
+permutation "rxy1" "rxy2" "wx1" "wy2" "c2" "c1"
+permutation "rxy1" "rxy2" "wy2" "wx1" "c1" "c2"
+permutation "rxy1" "rxy2" "wy2" "wx1" "c2" "c1"
+permutation "rxy1" "rxy2" "wy2" "c2" "wx1" "c1"
+permutation "rxy2" "rxy1" "wx1" "c1" "wy2" "c2"
+permutation "rxy2" "rxy1" "wx1" "wy2" "c1" "c2"
+permutation "rxy2" "rxy1" "wx1" "wy2" "c2" "c1"
+permutation "rxy2" "rxy1" "wy2" "wx1" "c1" "c2"
+permutation "rxy2" "rxy1" "wy2" "wx1" "c2" "c1"
+permutation "rxy2" "rxy1" "wy2" "c2" "wx1" "c1"
+permutation "rxy2" "wy2" "rxy1" "wx1" "c1" "c2"
+permutation "rxy2" "wy2" "rxy1" "wx1" "c2" "c1"
+permutation "rxy2" "wy2" "rxy1" "c2" "wx1" "c1"
+
+# An index scan (from one transaction) and an index insert (from another transaction)
+# try to access different parts of the index so no r-w conflict.
+
+permutation "rxy3" "wx3" "rxy4" "c1" "wy4" "c2"
+permutation "rxy3" "wx3" "rxy4" "wy4" "c1" "c2"
+permutation "rxy3" "wx3" "rxy4" "wy4" "c2" "c1"
+permutation "rxy3" "rxy4" "wx3" "c1" "wy4" "c2"
+permutation "rxy3" "rxy4" "wx3" "wy4" "c1" "c2"
+permutation "rxy3" "rxy4" "wx3" "wy4" "c2" "c1"
+permutation "rxy3" "rxy4" "wy4" "wx3" "c1" "c2"
+permutation "rxy3" "rxy4" "wy4" "wx3" "c2" "c1"
+permutation "rxy3" "rxy4" "wy4" "c2" "wx3" "c1"
+permutation "rxy4" "rxy3" "wx3" "c1" "wy4" "c2"
+permutation "rxy4" "rxy3" "wx3" "wy4" "c1" "c2"
+permutation "rxy4" "rxy3" "wx3" "wy4" "c2" "c1"
+permutation "rxy4" "rxy3" "wy4" "wx3" "c1" "c2"
+permutation "rxy4" "rxy3" "wy4" "wx3" "c2" "c1"
+permutation "rxy4" "rxy3" "wy4" "c2" "wx3" "c1"
+permutation "rxy4" "wy4" "rxy3" "wx3" "c1" "c2"
+permutation "rxy4" "wy4" "rxy3" "wx3" "c2" "c1"
+permutation "rxy4" "wy4" "rxy3" "c2" "wx3" "c1"
+
+# Test fastupdate = on. First test should pass because fastupdate is off and
+# sessions touches different parts of index, second should fail because
+# with fastupdate on, then whole index should be under predicate lock.
+
+permutation "rxy1" "rxy2fu" "wx1" "c1" "wy2fu" "c2"
+permutation "fu1" "rxy1" "rxy2fu" "wx1" "c1" "wy2fu" "c2"
+