]> granicus.if.org Git - postgresql/commitdiff
Remove entry tree root conflict checking from GIN predicate locking
authorAlexander Korotkov <akorotkov@postgresql.org>
Thu, 27 Dec 2018 01:10:51 +0000 (04:10 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Thu, 27 Dec 2018 01:24:20 +0000 (04:24 +0300)
According to README we acquire predicate locks on entry tree leafs and posting
tree roots.  However, when ginFindLeafPage() is going to lock leaf in exclusive
mode, then it checks root for conflicts regardless whether it's a entry or
posting tree.  Assuming that we never place predicate lock on entry tree root
(excluding corner case when root is leaf), this check is redundant.  This
commit removes this check.  Now, root conflict checking is controlled by
separate argument of ginFindLeafPage().

Discussion: https://postgr.es/m/CAPpHfdv7rrDyy%3DMgsaK-L9kk0AH7az0B-mdC3w3p0FSb9uoyEg%40mail.gmail.com
Author: Alexander Korotkov
Backpatch-through: 11

src/backend/access/gin/ginbtree.c
src/backend/access/gin/gindatapage.c
src/backend/access/gin/ginget.c
src/backend/access/gin/gininsert.c
src/include/access/gin_private.h

index d5a568106c580da7e9eeb87a1936ffa8cad7fca2..01a1b0c2d2fbc429383ffcf90a7df57df116ccb7 100644 (file)
@@ -72,9 +72,13 @@ ginTraverseLock(Buffer buffer, bool searchMode)
  * If 'searchmode' is false, on return stack->buffer is exclusively locked,
  * and the stack represents the full path to the root. Otherwise stack->buffer
  * is share-locked, and stack->parent is NULL.
+ *
+ * If 'rootConflictCheck' is true, tree root is checked for serialization
+ * conflict.
  */
 GinBtreeStack *
-ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot)
+ginFindLeafPage(GinBtree btree, bool searchMode,
+                               bool rootConflictCheck, Snapshot snapshot)
 {
        GinBtreeStack *stack;
 
@@ -84,7 +88,7 @@ ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot)
        stack->parent = NULL;
        stack->predictNumber = 1;
 
-       if (!searchMode)
+       if (rootConflictCheck)
                CheckForSerializableConflictIn(btree->index, NULL, stack->buffer);
 
        for (;;)
index 9f20513811e6ac47d15d87c35f25a5d7ccc84ba1..54d6890912566131f21af883aad06459a82d3e8a 100644 (file)
@@ -1913,7 +1913,7 @@ ginInsertItemPointers(Relation index, BlockNumber rootBlkno,
        {
                /* search for the leaf page where the first item should go to */
                btree.itemptr = insertdata.items[insertdata.curitem];
-               stack = ginFindLeafPage(&btree, false, NULL);
+               stack = ginFindLeafPage(&btree, false, true, NULL);
 
                ginInsertValue(&btree, stack, &insertdata, buildStats);
        }
@@ -1932,7 +1932,7 @@ ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno,
 
        btree->fullScan = true;
 
-       stack = ginFindLeafPage(btree, true, snapshot);
+       stack = ginFindLeafPage(btree, true, false, snapshot);
 
        return stack;
 }
index 8466d947eaba5a7d18e5664628e12bc30a8b0908..6bfe18c359fe92b6ebcd244c7ccd52586306cd22 100644 (file)
@@ -338,7 +338,7 @@ restartScanEntry:
        ginPrepareEntryScan(&btreeEntry, entry->attnum,
                                                entry->queryKey, entry->queryCategory,
                                                ginstate);
-       stackEntry = ginFindLeafPage(&btreeEntry, true, snapshot);
+       stackEntry = ginFindLeafPage(&btreeEntry, true, false, snapshot);
        page = BufferGetPage(stackEntry->buffer);
 
        /* ginFindLeafPage() will have already checked snapshot age. */
@@ -679,7 +679,7 @@ entryLoadMoreItems(GinState *ginstate, GinScanEntry entry,
                                                   OffsetNumberNext(GinItemPointerGetOffsetNumber(&advancePast)));
                }
                entry->btree.fullScan = false;
-               stack = ginFindLeafPage(&entry->btree, true, snapshot);
+               stack = ginFindLeafPage(&entry->btree, true, false, snapshot);
 
                /* we don't need the stack, just the buffer. */
                entry->buffer = stack->buffer;
index 5281eb682382ff170fadb0f91abde8a5842974b4..2781d3fdd83ee744fca01fe286f45eadfc10be4e 100644 (file)
@@ -195,7 +195,7 @@ ginEntryInsert(GinState *ginstate,
 
        ginPrepareEntryScan(&btree, attnum, key, category, ginstate);
 
-       stack = ginFindLeafPage(&btree, false, NULL);
+       stack = ginFindLeafPage(&btree, false, false, NULL);
        page = BufferGetPage(stack->buffer);
 
        if (btree.findItem(&btree, stack))
index 81bf8734ce31a5fbbd5e6831d1bcd66c49fb0ea3..bca82463199015777a13fb99934909aad67c22ec 100644 (file)
@@ -195,7 +195,8 @@ typedef struct
  * PostingItem
  */
 
-extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot);
+extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode,
+                               bool rootConflictCheck, Snapshot snapshot);
 extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode);
 extern void freeGinBtreeStack(GinBtreeStack *stack);
 extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack,