From 3b8acd46982bc2ca212dda2acb89c3e0a55d875b Mon Sep 17 00:00:00 2001 From: shubhambaraiss Date: Sun, 1 Oct 2017 23:42:41 +0530 Subject: [PATCH] Predicate locking in gist index --- src/backend/access/gist/gist.c | 12 +- src/backend/access/gist/gistget.c | 3 + src/backend/storage/lmgr/README-SSI | 5 +- src/test/isolation/expected/predicate-gist-2.out | 321 +++++++++++++++++++++ src/test/isolation/expected/predicate-gist.out | 339 +++++++++++++++++++++++ src/test/isolation/isolation_schedule | 2 + src/test/isolation/specs/predicate-gist-2.spec | 44 +++ src/test/isolation/specs/predicate-gist.spec | 44 +++ 8 files changed, 767 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/backend/access/gist/gist.c mode change 100644 => 100755 src/backend/access/gist/gistget.c mode change 100644 => 100755 src/backend/storage/lmgr/README-SSI create mode 100644 src/test/isolation/expected/predicate-gist-2.out create mode 100644 src/test/isolation/expected/predicate-gist.out create mode 100644 src/test/isolation/specs/predicate-gist-2.spec create mode 100644 src/test/isolation/specs/predicate-gist.spec diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c old mode 100644 new mode 100755 index 565525b..a64b833 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -18,6 +18,8 @@ #include "access/gistscan.h" #include "catalog/pg_collation.h" #include "miscadmin.h" +#include "storage/lmgr.h" +#include "storage/predicate.h" #include "nodes/execnodes.h" #include "utils/builtins.h" #include "utils/index_selfuncs.h" @@ -70,7 +72,7 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amsearchnulls = true; amroutine->amstorage = true; amroutine->amclusterable = true; - amroutine->ampredlocks = false; + amroutine->ampredlocks = true; amroutine->amcanparallel = false; amroutine->amkeytype = InvalidOid; @@ -446,6 +448,11 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate, GistPageSetNSN(ptr->page, oldnsn); } + for (ptr = dist; ptr; ptr = ptr->next) + PredicateLockPageSplit(rel, + BufferGetBlockNumber(buffer), + BufferGetBlockNumber(ptr->buffer)); + /* * gistXLogSplit() needs to WAL log a lot of pages, prepare WAL * insertion for that. NB: The number of pages and data segments @@ -733,6 +740,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate) } } + CheckForSerializableConflictIn(r, NULL, stack->buffer); /* * Update the tuple. * @@ -827,6 +835,8 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate) } } + CheckForSerializableConflictIn(r, NULL, stack->buffer); + /* now state.stack->(page, buffer and blkno) points to leaf page */ gistinserttuple(&state, stack, giststate, itup, diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c old mode 100644 new mode 100755 index 760ea0c..4fe5be2 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -18,6 +18,8 @@ #include "access/relscan.h" #include "catalog/pg_type.h" #include "miscadmin.h" +#include "storage/lmgr.h" +#include "storage/predicate.h" #include "pgstat.h" #include "lib/pairingheap.h" #include "utils/builtins.h" @@ -336,6 +338,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances, buffer = ReadBuffer(scan->indexRelation, pageItem->blkno); LockBuffer(buffer, GIST_SHARE); + PredicateLockPage(r, BufferGetBlockNumber(buffer), scan->xs_snapshot); gistcheckpage(scan->indexRelation, buffer); page = BufferGetPage(buffer); TestForOldSnapshot(scan->xs_snapshot, r, page); diff --git a/src/backend/storage/lmgr/README-SSI b/src/backend/storage/lmgr/README-SSI old mode 100644 new mode 100755 index a9dc01f..e221241 --- a/src/backend/storage/lmgr/README-SSI +++ b/src/backend/storage/lmgr/README-SSI @@ -374,10 +374,11 @@ however, a search discovers that no root page has yet been created, a predicate lock on the index relation is required. * GiST searches can determine that there are no matches at any -level of the index, so there must be a predicate lock at each index +level of the index, so we acquire predicate lock at each index level during a GiST search. An index insert at the leaf level can then be trusted to ripple up to all levels and locations where -conflicting predicate locks may exist. +conflicting predicate locks may exist. In case there is a page split, +we need to copy predicate lock from an original page to all new pages. * The effects of page splits, overflows, consolidations, and removals must be carefully reviewed to ensure that predicate locks diff --git a/src/test/isolation/expected/predicate-gist-2.out b/src/test/isolation/expected/predicate-gist-2.out new file mode 100644 index 0000000..8f54137 --- /dev/null +++ b/src/test/isolation/expected/predicate-gist-2.out @@ -0,0 +1,321 @@ +Parsed test spec with 2 sessions + +starting permutation: rxy1 wx1 c1 rxy2 wy2 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 c1 wy2 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step c1: COMMIT; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 wy2 c1 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 wy2 c2 c1 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy1 rxy2 wx1 c1 wy2 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; + +starting permutation: rxy1 rxy2 wx1 wy2 c1 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy1 rxy2 wx1 wy2 c2 c1 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy1 rxy2 wy2 wx1 c1 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy1 rxy2 wy2 wx1 c2 c1 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy1 rxy2 wy2 c2 wx1 c1 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; + +starting permutation: rxy2 rxy1 wx1 c1 wy2 c2 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; + +starting permutation: rxy2 rxy1 wx1 wy2 c1 c2 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy2 rxy1 wx1 wy2 c2 c1 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy2 rxy1 wy2 wx1 c1 c2 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy2 rxy1 wy2 wx1 c2 c1 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy2 rxy1 wy2 c2 wx1 c1 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; + +starting permutation: rxy2 wy2 rxy1 wx1 c1 c2 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy2 wy2 rxy1 wx1 c2 c1 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy2 wy2 rxy1 c2 wx1 c1 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step c2: COMMIT; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; + +starting permutation: rxy2 wy2 c2 rxy1 wx1 c1 +step rxy2: select sum(p[0]) from gist_point_tbl where p << point(1000,1000); +sum + +49500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; +step c2: COMMIT; +step rxy1: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); +sum + +3202000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; +step c1: COMMIT; diff --git a/src/test/isolation/expected/predicate-gist.out b/src/test/isolation/expected/predicate-gist.out new file mode 100644 index 0000000..56bdf3b --- /dev/null +++ b/src/test/isolation/expected/predicate-gist.out @@ -0,0 +1,339 @@ +Parsed test spec with 2 sessions + +starting permutation: rxy1 wx1 c1 rxy2 wy2 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step c1: COMMIT; +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +26500 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 c1 wy2 c2 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step c1: COMMIT; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step c1: COMMIT; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step c2: COMMIT; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step c1: COMMIT; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step c2: COMMIT; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) 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 sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3000 +step c2: COMMIT; +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +ERROR: could not serialize access due to read/write dependencies among transactions +step c1: COMMIT; + +starting permutation: rxy2 wy2 c2 rxy1 wx1 c1 +step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(750,750); +sum + +22000 +step wy2: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; +step c2: COMMIT; +step rxy1: select sum(p[0]) from gist_point_tbl where p << point(250, 250); +sum + +3500 +step wx1: insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; +step c1: COMMIT; diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 32c965b..e95036c 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -62,3 +62,5 @@ test: sequence-ddl test: async-notify test: vacuum-reltuples test: timeouts +test: predicate-gist +test: predicate-gist-2 diff --git a/src/test/isolation/specs/predicate-gist-2.spec b/src/test/isolation/specs/predicate-gist-2.spec new file mode 100644 index 0000000..1d67203 --- /dev/null +++ b/src/test/isolation/specs/predicate-gist-2.spec @@ -0,0 +1,44 @@ +# Test for page level predicate locking in gist +# +# Test to check false positives. +# +# Queries 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 different part(sub-tree) of the index. + + +setup +{ + create table gist_point_tbl(id int4, p point); + create index gist_pointidx on gist_point_tbl using gist(p); + insert into gist_point_tbl (id, p) + select g, point(g*10, g*10) from generate_series(1, 1000) g; +} + +teardown +{ + DROP TABLE gist_point_tbl; +} + +session "s1" +setup { + BEGIN ISOLATION LEVEL SERIALIZABLE; + set enable_seqscan=off; + set enable_bitmapscan=off; + set enable_indexonlyscan=on; + } +step "rxy1" { select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); } +step "wx1" { insert into gist_point_tbl (id, p) + select g, point(g*500, g*500) from generate_series(12, 18) g; } +step "c1" { COMMIT; } + +session "s2" +setup { + BEGIN ISOLATION LEVEL SERIALIZABLE; + set enable_seqscan=off; + set enable_bitmapscan=off; + set enable_indexonlyscan=on; + } + +step "rxy2" { select sum(p[0]) from gist_point_tbl where p << point(1000,1000); } +step "wy2" { insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 20) g; } +step "c2" { COMMIT; } diff --git a/src/test/isolation/specs/predicate-gist.spec b/src/test/isolation/specs/predicate-gist.spec new file mode 100644 index 0000000..400a1cf --- /dev/null +++ b/src/test/isolation/specs/predicate-gist.spec @@ -0,0 +1,44 @@ +# Test for page level predicate locking in gist +# +# Test to verify serialization failures. +# +# Queries 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. + +setup +{ + create table gist_point_tbl(id int4, p point); + create index gist_pointidx on gist_point_tbl using gist(p); + insert into gist_point_tbl (id, p) + select g, point(g*10, g*10) from generate_series(1, 100) g; +} + +teardown +{ + DROP TABLE gist_point_tbl; +} + +session "s1" +setup { + BEGIN ISOLATION LEVEL SERIALIZABLE; + set enable_seqscan=off; + set enable_bitmapscan=off; + set enable_indexonlyscan=on; + } +step "rxy1" { select sum(p[0]) from gist_point_tbl where p << point(250, 250); } +step "wx1" { insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(15, 20) g; } +step "c1" { COMMIT; } + + +session "s2" +setup { + BEGIN ISOLATION LEVEL SERIALIZABLE; + set enable_seqscan=off; + set enable_bitmapscan=off; + set enable_indexonlyscan=on; + } + +step "rxy2" { select sum(p[0]) from gist_point_tbl where p >> point(750,750); } +step "wy2" { insert into gist_point_tbl (id, p) + select g, point(g*50, g*50) from generate_series(1, 5) g; } +step "c2" { COMMIT; } -- 1.9.1