mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Re-think predicate locking on GIN indexes.
The principle behind the locking was not very well thought-out, and not documented. Add a section in the README to explain how it's supposed to work, and change the code so that it actually works that way. This fixes two bugs: 1. If fast update was turned on concurrently, subsequent inserts to the pending list would not conflict with predicate locks that were acquired earlier, on entry pages. The included 'predicate-gin-fastupdate' test demonstrates that. To fix, make all scans acquire a predicate lock on the metapage. That lock represents a scan of the pending list, whether or not there is a pending list at the moment. Forget about the optimization to skip locking/checking for locks, when fastupdate=off. 2. If a scan finds no match, it still needs to lock the entry page. The point of predicate locks is to lock the gabs between values, whether or not there is a match. The included 'predicate-gin-nomatch' test tests that case. In addition to those two bug fixes, this removes some unnecessary locking, following the principle laid out in the README. Because all items in a posting tree have the same key value, a lock on the posting tree root is enough to cover all the items. (With a very large posting tree, it would possibly be better to lock the posting tree leaf pages instead, so that a "skip scan" with a query like "A & B", you could avoid unnecessary conflict if a new tuple is inserted with A but !B. But let's keep this simple.) Also, some spelling fixes. Author: Heikki Linnakangas with some editorization by me Review: Andrey Borodin, Alexander Korotkov Discussion: https://www.postgresql.org/message-id/0b3ad2c2-2692-62a9-3a04-5724f2af9114@iki.fi
This commit is contained in:
@@ -1812,8 +1812,8 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
|
||||
blkno = BufferGetBlockNumber(buffer);
|
||||
|
||||
/*
|
||||
* Copy a predicate lock from entry tree leaf (containing posting list) to
|
||||
* posting tree.
|
||||
* Copy any predicate locks from the entry tree leaf (containing posting
|
||||
* list) to the posting tree.
|
||||
*/
|
||||
PredicateLockPageSplit(index, BufferGetBlockNumber(entrybuffer), blkno);
|
||||
|
||||
@@ -1864,7 +1864,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
|
||||
return blkno;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ginPrepareDataScan(GinBtree btree, Relation index, BlockNumber rootBlkno)
|
||||
{
|
||||
memset(btree, 0, sizeof(GinBtreeData));
|
||||
@@ -1911,7 +1911,6 @@ ginInsertItemPointers(Relation index, BlockNumber rootBlkno,
|
||||
btree.itemptr = insertdata.items[insertdata.curitem];
|
||||
stack = ginFindLeafPage(&btree, false, NULL);
|
||||
|
||||
GinCheckForSerializableConflictIn(btree.index, NULL, stack->buffer);
|
||||
ginInsertValue(&btree, stack, &insertdata, buildStats);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user