Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6e35939

Browse files
committed
Change rewriter/planner/executor/plancache to depend on RTE rellockmode.
Instead of recomputing the required lock levels in all these places,just use what commitfdba460 made the parser store in the RTE fields.This already simplifies the code measurably in these places, andfollow-on changes will remove a bunch of no-longer-needed infrastructure.In a few cases, this change causes us to acquire a higher lock levelthan we did before. This is OK primarily because said higher lock levelshould've been acquired already at query parse time; thus, we're savinga useless extra trip through the shared lock manager to acquire a lesserlock alongside the original lock. The only known exception to this isthat re-execution of a previously planned SELECT FOR UPDATE/SHARE query,for a table that uses ROW_MARK_REFERENCE or ROW_MARK_COPY methods, mighthave gotten only AccessShareLock before. Now it will get RowShareLocklike the first execution did, which seems fine.While there's more to do, push it in this state anyway, to let thebuildfarm help verify that nothing bad happened.Amit Langote, reviewed by David Rowley and Jesper Pedersen,and whacked around a bit more by meDiscussion:https://postgr.es/m/468c85d9-540e-66a2-1dde-fec2b741e688@lab.ntt.co.jp
1 parentcc2905e commit6e35939

File tree

5 files changed

+27
-115
lines changed

5 files changed

+27
-115
lines changed

‎src/backend/executor/execMain.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -970,26 +970,16 @@ InitPlan(QueryDesc *queryDesc, int eflags)
970970

971971
/* get relation's OID (will produce InvalidOid if subquery) */
972972
relid=getrelid(rc->rti,rangeTable);
973-
rellockmode=rt_fetch(rc->rti,rangeTable)->rellockmode;
974973

975-
/*
976-
* If you change the conditions under which rel locks are acquired
977-
* here, be sure to adjust ExecOpenScanRelation to match.
978-
*/
979974
switch (rc->markType)
980975
{
981976
caseROW_MARK_EXCLUSIVE:
982977
caseROW_MARK_NOKEYEXCLUSIVE:
983978
caseROW_MARK_SHARE:
984979
caseROW_MARK_KEYSHARE:
985-
Assert(rellockmode==RowShareLock);
986-
relation=heap_open(relid,RowShareLock);
987-
break;
988980
caseROW_MARK_REFERENCE:
989-
/* RTE might be a query target table */
990-
Assert(rellockmode==AccessShareLock||
991-
rellockmode==RowExclusiveLock);
992-
relation=heap_open(relid,AccessShareLock);
981+
rellockmode=rt_fetch(rc->rti,rangeTable)->rellockmode;
982+
relation=heap_open(relid,rellockmode);
993983
break;
994984
caseROW_MARK_COPY:
995985
/* no physical table access is required */

‎src/backend/executor/execUtils.c

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -641,10 +641,6 @@ ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
641641
*
642642
*Open the heap relation to be scanned by a base-level scan plan node.
643643
*This should be called during the node's ExecInit routine.
644-
*
645-
* By default, this acquires AccessShareLock on the relation. However,
646-
* if the relation was already locked by InitPlan, we don't need to acquire
647-
* any additional lock. This saves trips to the shared lock manager.
648644
* ----------------------------------------------------------------
649645
*/
650646
Relation
@@ -654,37 +650,9 @@ ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
654650
Oidreloid;
655651
LOCKMODElockmode;
656652

657-
/*
658-
* Determine the lock type we need. First, scan to see if target relation
659-
* is a result relation. If not, check if it's a FOR UPDATE/FOR SHARE
660-
* relation.
661-
*
662-
* Note: we may have already gotten the desired lock type, but for now
663-
* don't try to optimize; this logic is going away soon anyhow.
664-
*/
665-
lockmode=AccessShareLock;
666-
if (ExecRelationIsTargetRelation(estate,scanrelid))
667-
lockmode=RowExclusiveLock;
668-
else
669-
{
670-
/* Keep this check in sync with InitPlan! */
671-
ExecRowMark*erm=ExecFindRowMark(estate,scanrelid, true);
672-
673-
if (erm!=NULL)
674-
{
675-
if (erm->markType==ROW_MARK_REFERENCE||
676-
erm->markType==ROW_MARK_COPY)
677-
lockmode=AccessShareLock;
678-
else
679-
lockmode=RowShareLock;
680-
}
681-
}
682-
683-
/* lockmode per above logic must not be more than we previously acquired */
684-
Assert(lockmode <=rt_fetch(scanrelid,estate->es_range_table)->rellockmode);
685-
686653
/* Open the relation and acquire lock as needed */
687654
reloid=getrelid(scanrelid,estate->es_range_table);
655+
lockmode=rt_fetch(scanrelid,estate->es_range_table)->rellockmode;
688656
rel=heap_open(reloid,lockmode);
689657

690658
/*
@@ -912,6 +880,7 @@ ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
912880
if (!is_result_rel)
913881
{
914882
PlanRowMark*rc=NULL;
883+
LOCKMODElockmode;
915884

916885
foreach(l,stmt->rowMarks)
917886
{
@@ -923,9 +892,13 @@ ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
923892
}
924893

925894
if (rc&&RowMarkRequiresRowShareLock(rc->markType))
926-
LockRelationOid(relid,RowShareLock);
895+
lockmode=RowShareLock;
927896
else
928-
LockRelationOid(relid,AccessShareLock);
897+
lockmode=AccessShareLock;
898+
899+
Assert(lockmode==rt_fetch(rti,estate->es_range_table)->rellockmode);
900+
901+
LockRelationOid(relid,lockmode);
929902
}
930903
}
931904
}

‎src/backend/optimizer/prep/prepunion.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,6 @@ expand_inherited_tables(PlannerInfo *root)
15151515
staticvoid
15161516
expand_inherited_rtentry(PlannerInfo*root,RangeTblEntry*rte,Indexrti)
15171517
{
1518-
Query*parse=root->parse;
15191518
OidparentOID;
15201519
PlanRowMark*oldrc;
15211520
Relationoldrelation;
@@ -1546,21 +1545,9 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
15461545
* relation named in the query. However, for each child relation we add
15471546
* to the query, we must obtain an appropriate lock, because this will be
15481547
* the first use of those relations in the parse/rewrite/plan pipeline.
1549-
*
1550-
* If the parent relation is the query's result relation, then we need
1551-
* RowExclusiveLock. Otherwise, if it's accessed FOR UPDATE/SHARE, we
1552-
* need RowShareLock; otherwise AccessShareLock. We can't just grab
1553-
* AccessShareLock because then the executor would be trying to upgrade
1554-
* the lock, leading to possible deadlocks. (This code should match the
1555-
* parser and rewriter.)
1548+
* Child rels should use the same lockmode as their parent.
15561549
*/
1557-
oldrc=get_plan_rowmark(root->rowMarks,rti);
1558-
if (rti==parse->resultRelation)
1559-
lockmode=RowExclusiveLock;
1560-
elseif (oldrc&&RowMarkRequiresRowShareLock(oldrc->markType))
1561-
lockmode=RowShareLock;
1562-
else
1563-
lockmode=AccessShareLock;
1550+
lockmode=rte->rellockmode;
15641551

15651552
/* Scan for all members of inheritance set, acquire needed locks */
15661553
inhOIDs=find_all_inheritors(parentOID,lockmode,NULL);
@@ -1582,6 +1569,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
15821569
* PlanRowMark as isParent = true, and generate a new PlanRowMark for each
15831570
* child.
15841571
*/
1572+
oldrc=get_plan_rowmark(root->rowMarks,rti);
15851573
if (oldrc)
15861574
oldrc->isParent= true;
15871575

‎src/backend/rewrite/rewriteHandler.c

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,14 @@ static Bitmapset *adjust_view_column_set(Bitmapset *cols, List *targetlist);
8787
* AcquireRewriteLocks -
8888
* Acquire suitable locks on all the relations mentioned in the Query.
8989
* These locks will ensure that the relation schemas don't change under us
90-
* while we are rewritingandplanning the query.
90+
* while we are rewriting, planning,andexecuting the query.
9191
*
9292
* Caution: this may modify the querytree, therefore caller should usually
9393
* have done a copyObject() to make a writable copy of the querytree in the
9494
* current memory context.
9595
*
96-
* forExecute indicates that the query is about to be executed.
97-
* If so, we'll acquire RowExclusiveLock on the query's resultRelation,
98-
* RowShareLock on any relation accessed FOR [KEY] UPDATE/SHARE, and
99-
* AccessShareLock on all other relations mentioned.
100-
*
96+
* forExecute indicates that the query is about to be executed. If so,
97+
* we'll acquire the lock modes specified in the RTE rellockmode fields.
10198
* If forExecute is false, AccessShareLock is acquired on all relations.
10299
* This case is suitable for ruleutils.c, for example, where we only need
103100
* schema stability and we don't intend to actually modify any relations.
@@ -162,31 +159,24 @@ AcquireRewriteLocks(Query *parsetree,
162159

163160
/*
164161
* Grab the appropriate lock type for the relation, and do not
165-
* release it until end of transaction. This protects the
166-
* rewriter and planner against schema changes mid-query.
162+
* release it until end of transaction. This protects the
163+
* rewriter, planner, and executor against schema changes
164+
* mid-query.
167165
*
168-
*Assuming forExecute istrue, this logic must match what the
169-
*executor will do, else we risk lock-upgrade deadlocks.
166+
*If forExecute isfalse, ignore rellockmode and just use
167+
*AccessShareLock.
170168
*/
171169
if (!forExecute)
172170
lockmode=AccessShareLock;
173-
elseif (rt_index==parsetree->resultRelation)
174-
lockmode=RowExclusiveLock;
175171
elseif (forUpdatePushedDown)
176172
{
177-
lockmode=RowShareLock;
178173
/* Upgrade RTE's lock mode to reflect pushed-down lock */
179174
if (rte->rellockmode==AccessShareLock)
180175
rte->rellockmode=RowShareLock;
176+
lockmode=rte->rellockmode;
181177
}
182-
elseif (get_parse_rowmark(parsetree,rt_index)!=NULL)
183-
lockmode=RowShareLock;
184178
else
185-
lockmode=AccessShareLock;
186-
187-
Assert(!forExecute||lockmode==rte->rellockmode||
188-
(lockmode==AccessShareLock&&
189-
rte->rellockmode==RowExclusiveLock));
179+
lockmode=rte->rellockmode;
190180

191181
rel=heap_open(rte->relid,lockmode);
192182

‎src/backend/utils/cache/plancache.c

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,7 +1493,6 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
14931493
foreach(lc1,stmt_list)
14941494
{
14951495
PlannedStmt*plannedstmt=lfirst_node(PlannedStmt,lc1);
1496-
intrt_index;
14971496
ListCell*lc2;
14981497

14991498
if (plannedstmt->commandType==CMD_UTILITY)
@@ -1512,14 +1511,9 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
15121511
continue;
15131512
}
15141513

1515-
rt_index=0;
15161514
foreach(lc2,plannedstmt->rtable)
15171515
{
15181516
RangeTblEntry*rte= (RangeTblEntry*)lfirst(lc2);
1519-
LOCKMODElockmode;
1520-
PlanRowMark*rc;
1521-
1522-
rt_index++;
15231517

15241518
if (rte->rtekind!=RTE_RELATION)
15251519
continue;
@@ -1530,21 +1524,10 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
15301524
* fail if it's been dropped entirely --- we'll just transiently
15311525
* acquire a non-conflicting lock.
15321526
*/
1533-
if (list_member_int(plannedstmt->resultRelations,rt_index)||
1534-
list_member_int(plannedstmt->nonleafResultRelations,rt_index))
1535-
lockmode=RowExclusiveLock;
1536-
elseif ((rc=get_plan_rowmark(plannedstmt->rowMarks,rt_index))!=NULL&&
1537-
RowMarkRequiresRowShareLock(rc->markType))
1538-
lockmode=RowShareLock;
1539-
else
1540-
lockmode=AccessShareLock;
1541-
1542-
Assert(lockmode==rte->rellockmode);
1543-
15441527
if (acquire)
1545-
LockRelationOid(rte->relid,lockmode);
1528+
LockRelationOid(rte->relid,rte->rellockmode);
15461529
else
1547-
UnlockRelationOid(rte->relid,lockmode);
1530+
UnlockRelationOid(rte->relid,rte->rellockmode);
15481531
}
15491532
}
15501533
}
@@ -1586,37 +1569,25 @@ static void
15861569
ScanQueryForLocks(Query*parsetree,boolacquire)
15871570
{
15881571
ListCell*lc;
1589-
intrt_index;
15901572

15911573
/* Shouldn't get called on utility commands */
15921574
Assert(parsetree->commandType!=CMD_UTILITY);
15931575

15941576
/*
15951577
* First, process RTEs of the current query level.
15961578
*/
1597-
rt_index=0;
15981579
foreach(lc,parsetree->rtable)
15991580
{
16001581
RangeTblEntry*rte= (RangeTblEntry*)lfirst(lc);
1601-
LOCKMODElockmode;
16021582

1603-
rt_index++;
16041583
switch (rte->rtekind)
16051584
{
16061585
caseRTE_RELATION:
16071586
/* Acquire or release the appropriate type of lock */
1608-
if (rt_index==parsetree->resultRelation)
1609-
lockmode=RowExclusiveLock;
1610-
elseif (get_parse_rowmark(parsetree,rt_index)!=NULL)
1611-
lockmode=RowShareLock;
1612-
else
1613-
lockmode=AccessShareLock;
1614-
Assert(lockmode==rte->rellockmode||
1615-
(lockmode==AccessShareLock&&rte->rellockmode==RowExclusiveLock));
16161587
if (acquire)
1617-
LockRelationOid(rte->relid,lockmode);
1588+
LockRelationOid(rte->relid,rte->rellockmode);
16181589
else
1619-
UnlockRelationOid(rte->relid,lockmode);
1590+
UnlockRelationOid(rte->relid,rte->rellockmode);
16201591
break;
16211592

16221593
caseRTE_SUBQUERY:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp