Skip to content

Commit f01e3d3

Browse files
committed
Move the PredicateLockRelation() call from nodeSeqscan.c to heapam.c. It's
more consistent that way, since all the other PredicateLock* calls are made in various heapam.c and index AM functions. The call in nodeSeqscan.c was unnecessarily aggressive anyway, there's no need to try to lock the relation every time a tuple is fetched, it's enough to do it once. This has the user-visible effect that if a seq scan is initialized in the executor, but never executed, we now acquire the predicate lock on the heap relation anyway. We could avoid that by taking the lock on the first heap_getnext() call instead, but it doesn't seem worth the trouble given that it feels more natural to do it in heap_beginscan(). Also, remove the retail PredicateLockTuple() calls from heap_getnext(). In a seqscan, started with heap_begin(), we're holding a whole-relation predicate lock on the heap so there's no need to lock the tuples individually. Kevin Grittner and me
1 parent 1aa447a commit f01e3d3

File tree

3 files changed

+14
-14
lines changed

3 files changed

+14
-14
lines changed

src/backend/access/heap/heapam.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,6 @@ heapgettup(HeapScanDesc scan,
479479

480480
if (valid)
481481
{
482-
if (!scan->rs_relpredicatelocked)
483-
PredicateLockTuple(scan->rs_rd, tuple, snapshot);
484482
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
485483
return;
486484
}
@@ -748,16 +746,12 @@ heapgettup_pagemode(HeapScanDesc scan,
748746
nkeys, key, valid);
749747
if (valid)
750748
{
751-
if (!scan->rs_relpredicatelocked)
752-
PredicateLockTuple(scan->rs_rd, tuple, scan->rs_snapshot);
753749
scan->rs_cindex = lineindex;
754750
return;
755751
}
756752
}
757753
else
758754
{
759-
if (!scan->rs_relpredicatelocked)
760-
PredicateLockTuple(scan->rs_rd, tuple, scan->rs_snapshot);
761755
scan->rs_cindex = lineindex;
762756
return;
763757
}
@@ -1224,13 +1218,26 @@ heap_beginscan_internal(Relation relation, Snapshot snapshot,
12241218
scan->rs_strategy = NULL; /* set in initscan */
12251219
scan->rs_allow_strat = allow_strat;
12261220
scan->rs_allow_sync = allow_sync;
1227-
scan->rs_relpredicatelocked = false;
12281221

12291222
/*
12301223
* we can use page-at-a-time mode if it's an MVCC-safe snapshot
12311224
*/
12321225
scan->rs_pageatatime = IsMVCCSnapshot(snapshot);
12331226

1227+
/*
1228+
* For a seqscan in a serializable transaction, acquire a predicate lock
1229+
* on the entire relation. This is required not only to lock all the
1230+
* matching tuples, but also to conflict with new insertions into the
1231+
* table. In an indexscan, we take page locks on the index pages covering
1232+
* the range specified in the scan qual, but in a heap scan there is
1233+
* nothing more fine-grained to lock. A bitmap scan is a different story,
1234+
* there we have already scanned the index and locked the index pages
1235+
* covering the predicate. But in that case we still have to lock any
1236+
* matching heap tuples.
1237+
*/
1238+
if (!is_bitmapscan)
1239+
PredicateLockRelation(relation, snapshot);
1240+
12341241
/* we only need to set this up once */
12351242
scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
12361243

src/backend/executor/nodeSeqscan.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#include "access/relscan.h"
2929
#include "executor/execdebug.h"
3030
#include "executor/nodeSeqscan.h"
31-
#include "storage/predicate.h"
3231

3332
static void InitScanRelation(SeqScanState *node, EState *estate);
3433
static TupleTableSlot *SeqNext(SeqScanState *node);
@@ -106,16 +105,11 @@ SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
106105
* tuple.
107106
* We call the ExecScan() routine and pass it the appropriate
108107
* access method functions.
109-
* For serializable transactions, we first acquire a predicate
110-
* lock on the entire relation.
111108
* ----------------------------------------------------------------
112109
*/
113110
TupleTableSlot *
114111
ExecSeqScan(SeqScanState *node)
115112
{
116-
PredicateLockRelation(node->ss_currentRelation,
117-
node->ss_currentScanDesc->rs_snapshot);
118-
node->ss_currentScanDesc->rs_relpredicatelocked = true;
119113
return ExecScan((ScanState *) node,
120114
(ExecScanAccessMtd) SeqNext,
121115
(ExecScanRecheckMtd) SeqRecheck);

src/include/access/relscan.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ typedef struct HeapScanDescData
3535
BlockNumber rs_startblock; /* block # to start at */
3636
BufferAccessStrategy rs_strategy; /* access strategy for reads */
3737
bool rs_syncscan; /* report location to syncscan logic? */
38-
bool rs_relpredicatelocked; /* predicate lock on relation exists */
3938

4039
/* scan current state */
4140
bool rs_inited; /* false = scan not init'd yet */

0 commit comments

Comments
 (0)