Commit 29ef2b31 authored by Tom Lane's avatar Tom Lane

Restore sane locking behavior during parallel query.

Commit 9a3cebea changed things so that parallel workers didn't obtain
any lock of their own on tables they access.  That was clearly a bad
idea, but I'd mistakenly supposed that it was the intended end result
of the series of patches for simplifying the executor's lock management.
Undo that change in relation_open(), and adjust ExecOpenScanRelation()
so that it gets the correct lock if inside a parallel worker.

In passing, clean up some more obsolete comments about when locks
are acquired.

Discussion: https://postgr.es/m/468c85d9-540e-66a2-1dde-fec2b741e688@lab.ntt.co.jp
parent f2343653
...@@ -1140,13 +1140,9 @@ relation_open(Oid relationId, LOCKMODE lockmode) ...@@ -1140,13 +1140,9 @@ relation_open(Oid relationId, LOCKMODE lockmode)
/* /*
* If we didn't get the lock ourselves, assert that caller holds one, * If we didn't get the lock ourselves, assert that caller holds one,
* except in bootstrap mode where no locks are used. * except in bootstrap mode where no locks are used.
*
* Also, parallel workers currently assume that their parent holds locks
* for tables used in the parallel query (a mighty shaky assumption).
*/ */
Assert(lockmode != NoLock || Assert(lockmode != NoLock ||
IsBootstrapProcessingMode() || IsBootstrapProcessingMode() ||
IsParallelWorker() ||
CheckRelationLockedByMe(r, AccessShareLock, true)); CheckRelationLockedByMe(r, AccessShareLock, true));
/* Make note that we've accessed a temporary relation */ /* Make note that we've accessed a temporary relation */
......
...@@ -1622,8 +1622,8 @@ ExecEndPlan(PlanState *planstate, EState *estate) ...@@ -1622,8 +1622,8 @@ ExecEndPlan(PlanState *planstate, EState *estate)
} }
/* /*
* close whatever rangetable Relations have been opened. We did not * close whatever rangetable Relations have been opened. We do not
* acquire locks in ExecGetRangeTableRelation, so don't release 'em here. * release any locks we might hold on those rels.
*/ */
num_relations = estate->es_range_table_size; num_relations = estate->es_range_table_size;
for (i = 0; i < num_relations; i++) for (i = 0; i < num_relations; i++)
......
...@@ -732,16 +732,30 @@ ExecGetRangeTableRelation(EState *estate, Index rti) ...@@ -732,16 +732,30 @@ ExecGetRangeTableRelation(EState *estate, Index rti)
Assert(rte->rtekind == RTE_RELATION); Assert(rte->rtekind == RTE_RELATION);
rel = estate->es_relations[rti - 1] = heap_open(rte->relid, NoLock); if (!IsParallelWorker())
{
/*
* In a normal query, we should already have the appropriate lock,
* but verify that through an Assert. Since there's already an
* Assert inside heap_open that insists on holding some lock, it
* seems sufficient to check this only when rellockmode is higher
* than the minimum.
*/
rel = heap_open(rte->relid, NoLock);
Assert(rte->rellockmode == AccessShareLock ||
CheckRelationLockedByMe(rel, rte->rellockmode, false));
}
else
{
/*
* If we are a parallel worker, we need to obtain our own local
* lock on the relation. This ensures sane behavior in case the
* parent process exits before we do.
*/
rel = heap_open(rte->relid, rte->rellockmode);
}
/* estate->es_relations[rti - 1] = rel;
* Verify that appropriate lock was obtained before execution.
*
* In the case of parallel query, only the leader would've obtained
* the lock (that needs to be fixed, though).
*/
Assert(IsParallelWorker() ||
CheckRelationLockedByMe(rel, rte->rellockmode, false));
} }
return rel; return rel;
......
...@@ -899,16 +899,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) ...@@ -899,16 +899,12 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); ExecAssignExprContext(estate, &scanstate->ss.ps);
/* /*
* open the base relation and acquire appropriate lock on it. * open the scan relation
*/ */
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags); currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
/* /*
* initialize child nodes * initialize child nodes
*
* We do this after ExecOpenScanRelation because the child nodes will open
* indexscans on our relation's indexes, and we want to be sure we have
* acquired a lock on the relation first.
*/ */
outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags); outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
......
...@@ -55,7 +55,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) ...@@ -55,7 +55,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
ExecAssignExprContext(estate, &css->ss.ps); ExecAssignExprContext(estate, &css->ss.ps);
/* /*
* open the base relation, if any, and acquire an appropriate lock on it * open the scan relation, if any
*/ */
if (scanrelid > 0) if (scanrelid > 0)
{ {
......
...@@ -156,8 +156,8 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) ...@@ -156,8 +156,8 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); ExecAssignExprContext(estate, &scanstate->ss.ps);
/* /*
* open the base relation, if any, and acquire an appropriate lock on it; * open the scan relation, if any; also acquire function pointers from the
* also acquire function pointers from the FDW's handler * FDW's handler
*/ */
if (scanrelid > 0) if (scanrelid > 0)
{ {
......
...@@ -511,7 +511,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) ...@@ -511,7 +511,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &indexstate->ss.ps); ExecAssignExprContext(estate, &indexstate->ss.ps);
/* /*
* open the base relation and acquire appropriate lock on it. * open the scan relation
*/ */
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags); currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
......
...@@ -933,7 +933,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) ...@@ -933,7 +933,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &indexstate->ss.ps); ExecAssignExprContext(estate, &indexstate->ss.ps);
/* /*
* open the base relation and acquire appropriate lock on it. * open the scan relation
*/ */
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags); currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
......
...@@ -134,10 +134,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags) ...@@ -134,10 +134,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); ExecAssignExprContext(estate, &scanstate->ss.ps);
/* /*
* Initialize scan relation. * open the scan relation
*
* Get the relation object id from the relid'th entry in the range table,
* open that relation and acquire appropriate lock on it.
*/ */
scanstate->ss.ss_currentRelation = scanstate->ss.ss_currentRelation =
ExecOpenScanRelation(estate, ExecOpenScanRelation(estate,
......
...@@ -163,10 +163,7 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) ...@@ -163,10 +163,7 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); ExecAssignExprContext(estate, &scanstate->ss.ps);
/* /*
* Initialize scan relation. * open the scan relation
*
* Get the relation object id from the relid'th entry in the range table,
* open that relation and acquire appropriate lock on it.
*/ */
scanstate->ss.ss_currentRelation = scanstate->ss.ss_currentRelation =
ExecOpenScanRelation(estate, ExecOpenScanRelation(estate,
......
...@@ -531,7 +531,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags) ...@@ -531,7 +531,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
tidstate->tss_TidPtr = -1; tidstate->tss_TidPtr = -1;
/* /*
* open the base relation and acquire appropriate lock on it. * open the scan relation
*/ */
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags); currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment