mirror of
https://github.com/postgres/postgres.git
synced 2025-05-02 11:44:50 +03:00
Avoid redundant relation lock grabs during planning, and make sure
that we acquire a lock on relations added to the query due to inheritance. Formerly, no such lock was held throughout planning, which meant that a schema change could occur to invalidate the plan before it's even been completed.
This commit is contained in:
parent
353f111f98
commit
c1393173aa
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.75 2005/04/28 21:47:14 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.76 2005/05/23 03:01:13 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -189,9 +189,11 @@ expand_targetlist(List *tlist, int command_type,
|
|||||||
* attributes.
|
* attributes.
|
||||||
*
|
*
|
||||||
* Scan the tuple description in the relation's relcache entry to make
|
* Scan the tuple description in the relation's relcache entry to make
|
||||||
* sure we have all the user attributes in the right order.
|
* sure we have all the user attributes in the right order. We assume
|
||||||
|
* that the rewriter already acquired at least AccessShareLock on the
|
||||||
|
* relation, so we need no lock here.
|
||||||
*/
|
*/
|
||||||
rel = heap_open(getrelid(result_relation, range_table), AccessShareLock);
|
rel = heap_open(getrelid(result_relation, range_table), NoLock);
|
||||||
|
|
||||||
numattrs = RelationGetNumberOfAttributes(rel);
|
numattrs = RelationGetNumberOfAttributes(rel);
|
||||||
|
|
||||||
@ -326,7 +328,7 @@ expand_targetlist(List *tlist, int command_type,
|
|||||||
tlist_item = lnext(tlist_item);
|
tlist_item = lnext(tlist_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_close(rel, AccessShareLock);
|
heap_close(rel, NoLock);
|
||||||
|
|
||||||
return new_tlist;
|
return new_tlist;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.107 2005/05/22 22:30:20 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.108 2005/05/23 03:01:14 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -67,7 +67,25 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
|
|||||||
bool hasindex;
|
bool hasindex;
|
||||||
List *indexinfos = NIL;
|
List *indexinfos = NIL;
|
||||||
|
|
||||||
relation = heap_open(relationObjectId, AccessShareLock);
|
/*
|
||||||
|
* Normally, we can assume the rewriter already acquired at least
|
||||||
|
* AccessShareLock on each relation used in the query. However this
|
||||||
|
* will not be the case for relations added to the query because they
|
||||||
|
* are inheritance children of some relation mentioned explicitly.
|
||||||
|
* For them, this is the first access during the parse/rewrite/plan
|
||||||
|
* pipeline, and so we need to obtain and keep a suitable lock.
|
||||||
|
*
|
||||||
|
* XXX really, a suitable lock is RowShareLock if the relation is
|
||||||
|
* an UPDATE/DELETE target, and AccessShareLock otherwise. However
|
||||||
|
* we cannot easily tell here which to get, so for the moment just
|
||||||
|
* get AccessShareLock always. The executor will get the right lock
|
||||||
|
* when it runs, which means there is a very small chance of deadlock
|
||||||
|
* trying to upgrade our lock.
|
||||||
|
*/
|
||||||
|
if (rel->reloptkind == RELOPT_BASEREL)
|
||||||
|
relation = heap_open(relationObjectId, NoLock);
|
||||||
|
else
|
||||||
|
relation = heap_open(relationObjectId, AccessShareLock);
|
||||||
|
|
||||||
rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1;
|
rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1;
|
||||||
rel->max_attr = RelationGetNumberOfAttributes(relation);
|
rel->max_attr = RelationGetNumberOfAttributes(relation);
|
||||||
@ -205,8 +223,8 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
|
|||||||
|
|
||||||
rel->indexlist = indexinfos;
|
rel->indexlist = indexinfos;
|
||||||
|
|
||||||
/* XXX keep the lock here? */
|
/* close rel, but keep lock if any */
|
||||||
heap_close(relation, AccessShareLock);
|
heap_close(relation, NoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -374,7 +392,8 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
|
|||||||
switch (rte->rtekind)
|
switch (rte->rtekind)
|
||||||
{
|
{
|
||||||
case RTE_RELATION:
|
case RTE_RELATION:
|
||||||
relation = heap_open(rte->relid, AccessShareLock);
|
/* Assume we already have adequate lock */
|
||||||
|
relation = heap_open(rte->relid, NoLock);
|
||||||
|
|
||||||
numattrs = RelationGetNumberOfAttributes(relation);
|
numattrs = RelationGetNumberOfAttributes(relation);
|
||||||
for (attrno = 1; attrno <= numattrs; attrno++)
|
for (attrno = 1; attrno <= numattrs; attrno++)
|
||||||
@ -401,7 +420,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
|
|||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_close(relation, AccessShareLock);
|
heap_close(relation, NoLock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTE_SUBQUERY:
|
case RTE_SUBQUERY:
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.65 2005/04/22 21:58:31 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.66 2005/05/23 03:01:14 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -23,7 +23,8 @@
|
|||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
|
|
||||||
|
|
||||||
static RelOptInfo *make_base_rel(Query *root, int relid);
|
static RelOptInfo *make_reloptinfo(Query *root, int relid,
|
||||||
|
RelOptKind reloptkind);
|
||||||
static void build_joinrel_tlist(Query *root, RelOptInfo *joinrel);
|
static void build_joinrel_tlist(Query *root, RelOptInfo *joinrel);
|
||||||
static List *build_joinrel_restrictlist(Query *root,
|
static List *build_joinrel_restrictlist(Query *root,
|
||||||
RelOptInfo *joinrel,
|
RelOptInfo *joinrel,
|
||||||
@ -67,7 +68,7 @@ build_base_rel(Query *root, int relid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* No existing RelOptInfo for this base rel, so make a new one */
|
/* No existing RelOptInfo for this base rel, so make a new one */
|
||||||
rel = make_base_rel(root, relid);
|
rel = make_reloptinfo(root, relid, RELOPT_BASEREL);
|
||||||
|
|
||||||
/* and add it to the list */
|
/* and add it to the list */
|
||||||
root->base_rel_list = lcons(rel, root->base_rel_list);
|
root->base_rel_list = lcons(rel, root->base_rel_list);
|
||||||
@ -102,11 +103,8 @@ build_other_rel(Query *root, int relid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* No existing RelOptInfo for this other rel, so make a new one */
|
/* No existing RelOptInfo for this other rel, so make a new one */
|
||||||
rel = make_base_rel(root, relid);
|
|
||||||
|
|
||||||
/* presently, must be an inheritance child rel */
|
/* presently, must be an inheritance child rel */
|
||||||
Assert(rel->reloptkind == RELOPT_BASEREL);
|
rel = make_reloptinfo(root, relid, RELOPT_OTHER_CHILD_REL);
|
||||||
rel->reloptkind = RELOPT_OTHER_CHILD_REL;
|
|
||||||
|
|
||||||
/* and add it to the list */
|
/* and add it to the list */
|
||||||
root->other_rel_list = lcons(rel, root->other_rel_list);
|
root->other_rel_list = lcons(rel, root->other_rel_list);
|
||||||
@ -115,18 +113,18 @@ build_other_rel(Query *root, int relid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make_base_rel
|
* make_reloptinfo
|
||||||
* Construct a base-relation RelOptInfo for the specified rangetable index.
|
* Construct a RelOptInfo for the specified rangetable index.
|
||||||
*
|
*
|
||||||
* Common code for build_base_rel and build_other_rel.
|
* Common code for build_base_rel and build_other_rel.
|
||||||
*/
|
*/
|
||||||
static RelOptInfo *
|
static RelOptInfo *
|
||||||
make_base_rel(Query *root, int relid)
|
make_reloptinfo(Query *root, int relid, RelOptKind reloptkind)
|
||||||
{
|
{
|
||||||
RelOptInfo *rel = makeNode(RelOptInfo);
|
RelOptInfo *rel = makeNode(RelOptInfo);
|
||||||
RangeTblEntry *rte = rt_fetch(relid, root->rtable);
|
RangeTblEntry *rte = rt_fetch(relid, root->rtable);
|
||||||
|
|
||||||
rel->reloptkind = RELOPT_BASEREL;
|
rel->reloptkind = reloptkind;
|
||||||
rel->relids = bms_make_singleton(relid);
|
rel->relids = bms_make_singleton(relid);
|
||||||
rel->rows = 0;
|
rel->rows = 0;
|
||||||
rel->width = 0;
|
rel->width = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user