Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b508a56

Browse files
committed
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
1 parent 971d7dd commit b508a56

File tree

8 files changed

+802
-1
lines changed

8 files changed

+802
-1
lines changed

src/backend/access/hash/hash.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ hashhandler(PG_FUNCTION_ARGS)
6868
amroutine->amsearchnulls = false;
6969
amroutine->amstorage = false;
7070
amroutine->amclusterable = false;
71-
amroutine->ampredlocks = false;
71+
amroutine->ampredlocks = true;
7272
amroutine->amcanparallel = false;
7373
amroutine->amkeytype = INT4OID;
7474

src/backend/access/hash/hashinsert.c

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "utils/rel.h"
2323
#include "storage/lwlock.h"
2424
#include "storage/buf_internals.h"
25+
#include "storage/predicate.h"
2526

2627
static void _hash_vacuum_one_page(Relation rel, Buffer metabuf, Buffer buf,
2728
RelFileNode hnode);
@@ -88,6 +89,8 @@ _hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel)
8889
&usedmetap);
8990
Assert(usedmetap != NULL);
9091

92+
CheckForSerializableConflictIn(rel, NULL, buf);
93+
9194
/* remember the primary bucket buffer to release the pin on it at end. */
9295
bucket_buf = buf;
9396

src/backend/access/hash/hashpage.c

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "miscadmin.h"
3434
#include "storage/lmgr.h"
3535
#include "storage/smgr.h"
36+
#include "storage/predicate.h"
3637

3738

3839
static bool _hash_alloc_buckets(Relation rel, BlockNumber firstblock,
@@ -1107,6 +1108,11 @@ _hash_splitbucket(Relation rel,
11071108
npage = BufferGetPage(nbuf);
11081109
nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
11091110

1111+
/* Copy the predicate locks from old bucket to new bucket. */
1112+
PredicateLockPageSplit(rel,
1113+
BufferGetBlockNumber(bucket_obuf),
1114+
BufferGetBlockNumber(bucket_nbuf));
1115+
11101116
/*
11111117
* Partition the tuples in the old bucket between the old bucket and the
11121118
* new bucket, advancing along the old bucket's overflow bucket chain and

src/backend/access/hash/hashsearch.c

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "miscadmin.h"
2020
#include "pgstat.h"
2121
#include "utils/rel.h"
22+
#include "storage/predicate.h"
2223

2324
static bool _hash_readpage(IndexScanDesc scan, Buffer *bufP,
2425
ScanDirection dir);
@@ -171,6 +172,7 @@ _hash_readnext(IndexScanDesc scan,
171172
Assert(BufferIsValid(*bufp));
172173

173174
LockBuffer(*bufp, BUFFER_LOCK_SHARE);
175+
PredicateLockPage(rel, BufferGetBlockNumber(*bufp), scan->xs_snapshot);
174176

175177
/*
176178
* setting hashso_buc_split to true indicates that we are scanning
@@ -347,6 +349,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
347349
so->hashso_sk_hash = hashkey;
348350

349351
buf = _hash_getbucketbuf_from_hashkey(rel, hashkey, HASH_READ, NULL);
352+
PredicateLockPage(rel, BufferGetBlockNumber(buf), scan->xs_snapshot);
350353
page = BufferGetPage(buf);
351354
TestForOldSnapshot(scan->xs_snapshot, rel, page);
352355
opaque = (HashPageOpaque) PageGetSpecialPointer(page);

src/backend/storage/lmgr/README-SSI

+7
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,13 @@ relation is required. Fast update postpones the insertion of tuples into index
389389
structure by temporarily storing them into pending list. That makes us unable
390390
to detect r-w conflicts using page-level locks.
391391

392+
* Hash index searches acquire predicate locks on the primary
393+
page of a bucket. It acquires a lock on both the old and new buckets
394+
for scans that happen concurrently with page splits. During a bucket
395+
split, a predicate lock is copied from the primary page of an old
396+
bucket to the primary page of a new bucket.
397+
398+
392399
* The effects of page splits, overflows, consolidations, and
393400
removals must be carefully reviewed to ensure that predicate locks
394401
aren't "lost" during those operations, or kept with pages which could

0 commit comments

Comments
 (0)