mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Predicate locking in hash indexes.
Hash index searches acquire predicate locks on the primary page of a bucket. It acquires a lock on both the old and new buckets for scans that happen concurrently with page splits. During a bucket split, a predicate lock is copied from the primary page of an old bucket to the primary page of a new bucket. Author: Shubham Barai, Amit Kapila Reviewed by: Amit Kapila, Alexander Korotkov, Thomas Munro Discussion: https://www.postgresql.org/message-id/flat/CALxAEPvNsM2GTiXdRgaaZ1Pjd1bs+sxfFsf7Ytr+iq+5JJoYXA@mail.gmail.com
This commit is contained in:
@ -68,7 +68,7 @@ hashhandler(PG_FUNCTION_ARGS)
|
||||
amroutine->amsearchnulls = false;
|
||||
amroutine->amstorage = false;
|
||||
amroutine->amclusterable = false;
|
||||
amroutine->ampredlocks = false;
|
||||
amroutine->ampredlocks = true;
|
||||
amroutine->amcanparallel = false;
|
||||
amroutine->amkeytype = INT4OID;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "utils/rel.h"
|
||||
#include "storage/lwlock.h"
|
||||
#include "storage/buf_internals.h"
|
||||
#include "storage/predicate.h"
|
||||
|
||||
static void _hash_vacuum_one_page(Relation rel, Buffer metabuf, Buffer buf,
|
||||
RelFileNode hnode);
|
||||
@ -88,6 +89,8 @@ restart_insert:
|
||||
&usedmetap);
|
||||
Assert(usedmetap != NULL);
|
||||
|
||||
CheckForSerializableConflictIn(rel, NULL, buf);
|
||||
|
||||
/* remember the primary bucket buffer to release the pin on it at end. */
|
||||
bucket_buf = buf;
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "storage/predicate.h"
|
||||
|
||||
|
||||
static bool _hash_alloc_buckets(Relation rel, BlockNumber firstblock,
|
||||
@ -1107,6 +1108,11 @@ _hash_splitbucket(Relation rel,
|
||||
npage = BufferGetPage(nbuf);
|
||||
nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
|
||||
|
||||
/* Copy the predicate locks from old bucket to new bucket. */
|
||||
PredicateLockPageSplit(rel,
|
||||
BufferGetBlockNumber(bucket_obuf),
|
||||
BufferGetBlockNumber(bucket_nbuf));
|
||||
|
||||
/*
|
||||
* Partition the tuples in the old bucket between the old bucket and the
|
||||
* new bucket, advancing along the old bucket's overflow bucket chain and
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "utils/rel.h"
|
||||
#include "storage/predicate.h"
|
||||
|
||||
static bool _hash_readpage(IndexScanDesc scan, Buffer *bufP,
|
||||
ScanDirection dir);
|
||||
@ -171,6 +172,7 @@ _hash_readnext(IndexScanDesc scan,
|
||||
Assert(BufferIsValid(*bufp));
|
||||
|
||||
LockBuffer(*bufp, BUFFER_LOCK_SHARE);
|
||||
PredicateLockPage(rel, BufferGetBlockNumber(*bufp), scan->xs_snapshot);
|
||||
|
||||
/*
|
||||
* setting hashso_buc_split to true indicates that we are scanning
|
||||
@ -347,6 +349,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
|
||||
so->hashso_sk_hash = hashkey;
|
||||
|
||||
buf = _hash_getbucketbuf_from_hashkey(rel, hashkey, HASH_READ, NULL);
|
||||
PredicateLockPage(rel, BufferGetBlockNumber(buf), scan->xs_snapshot);
|
||||
page = BufferGetPage(buf);
|
||||
TestForOldSnapshot(scan->xs_snapshot, rel, page);
|
||||
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||
|
Reference in New Issue
Block a user