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

Commit258cef1

Browse files
committed
Fix possibile deadlock when dropping partitions.
heap_drop_with_catalog and RangeVarCallbackForDropRelation shouldlock the parent before locking the target relation.Amit LangoteDiscussion:http://postgr.es/m/29588799-a8ce-b0a2-3dae-f39ff6d35922@lab.ntt.co.jp
1 parentfeffa0e commit258cef1

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

‎src/backend/catalog/heap.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,29 +1759,33 @@ void
17591759
heap_drop_with_catalog(Oidrelid)
17601760
{
17611761
Relationrel;
1762+
HeapTupletuple;
17621763
OidparentOid;
17631764
Relationparent=NULL;
17641765

17651766
/*
1766-
* Open and lock the relation.
1767+
* To drop a partition safely, we must grab exclusive lock on its parent,
1768+
* because another backend might be about to execute a query on the parent
1769+
* table. If it relies on previously cached partition descriptor, then
1770+
* it could attempt to access the just-dropped relation as its partition.
1771+
* We must therefore take a table lock strong enough to prevent all
1772+
* queries on the table from proceeding until we commit and send out a
1773+
* shared-cache-inval notice that will make them update their index lists.
17671774
*/
1768-
rel=relation_open(relid,AccessExclusiveLock);
1769-
1770-
/*
1771-
* If the relation is a partition, we must grab exclusive lock on its
1772-
* parent because we need to update its partition descriptor. We must take
1773-
* a table lock strong enough to prevent all queries on the parent from
1774-
* proceeding until we commit and send out a shared-cache-inval notice
1775-
* that will make them update their partition descriptor. Sometimes, doing
1776-
* this is cycles spent uselessly, especially if the parent will be
1777-
* dropped as part of the same command anyway.
1778-
*/
1779-
if (rel->rd_rel->relispartition)
1775+
tuple=SearchSysCache1(RELOID,ObjectIdGetDatum(relid));
1776+
if (((Form_pg_class)GETSTRUCT(tuple))->relispartition)
17801777
{
17811778
parentOid=get_partition_parent(relid);
17821779
parent=heap_open(parentOid,AccessExclusiveLock);
17831780
}
17841781

1782+
ReleaseSysCache(tuple);
1783+
1784+
/*
1785+
* Open and lock the relation.
1786+
*/
1787+
rel=relation_open(relid,AccessExclusiveLock);
1788+
17851789
/*
17861790
* There can no longer be anyone *else* touching the relation, but we
17871791
* might still have open queries or cursors, or pending trigger events, in

‎src/backend/commands/tablecmds.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ struct DropRelationCallbackState
271271
{
272272
charrelkind;
273273
OidheapOid;
274+
OidpartParentOid;
274275
boolconcurrent;
275276
};
276277

@@ -1049,6 +1050,7 @@ RemoveRelations(DropStmt *drop)
10491050
/* Look up the appropriate relation using namespace search. */
10501051
state.relkind=relkind;
10511052
state.heapOid=InvalidOid;
1053+
state.partParentOid=InvalidOid;
10521054
state.concurrent=drop->concurrent;
10531055
relOid=RangeVarGetRelidExtended(rel,lockmode, true,
10541056
false,
@@ -1078,6 +1080,8 @@ RemoveRelations(DropStmt *drop)
10781080
/*
10791081
* Before acquiring a table lock, check whether we have sufficient rights.
10801082
* In the case of DROP INDEX, also try to lock the table before the index.
1083+
* Also, if the table to be dropped is a partition, we try to lock the parent
1084+
* first.
10811085
*/
10821086
staticvoid
10831087
RangeVarCallbackForDropRelation(constRangeVar*rel,OidrelOid,OidoldRelOid,
@@ -1087,6 +1091,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
10871091
structDropRelationCallbackState*state;
10881092
charrelkind;
10891093
charexpected_relkind;
1094+
boolis_partition;
10901095
Form_pg_classclassform;
10911096
LOCKMODEheap_lockmode;
10921097

@@ -1106,6 +1111,17 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
11061111
state->heapOid=InvalidOid;
11071112
}
11081113

1114+
/*
1115+
* Similarly, if we previously locked some other partition's heap, and
1116+
* the name we're looking up no longer refers to that relation, release
1117+
* the now-useless lock.
1118+
*/
1119+
if (relOid!=oldRelOid&&OidIsValid(state->partParentOid))
1120+
{
1121+
UnlockRelationOid(state->partParentOid,AccessExclusiveLock);
1122+
state->partParentOid=InvalidOid;
1123+
}
1124+
11091125
/* Didn't find a relation, so no need for locking or permission checks. */
11101126
if (!OidIsValid(relOid))
11111127
return;
@@ -1114,6 +1130,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
11141130
if (!HeapTupleIsValid(tuple))
11151131
return;/* concurrently dropped, so nothing to do */
11161132
classform= (Form_pg_class)GETSTRUCT(tuple);
1133+
is_partition=classform->relispartition;
11171134

11181135
/*
11191136
* Both RELKIND_RELATION and RELKIND_PARTITIONED_TABLE are OBJECT_TABLE,
@@ -1157,6 +1174,19 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
11571174
if (OidIsValid(state->heapOid))
11581175
LockRelationOid(state->heapOid,heap_lockmode);
11591176
}
1177+
1178+
/*
1179+
* Similarly, if the relation is a partition, we must acquire lock on its
1180+
* parent before locking the partition. That's because queries lock the
1181+
* parent before its partitions, so we risk deadlock it we do it the other
1182+
* way around.
1183+
*/
1184+
if (is_partition&&relOid!=oldRelOid)
1185+
{
1186+
state->partParentOid=get_partition_parent(relOid);
1187+
if (OidIsValid(state->partParentOid))
1188+
LockRelationOid(state->partParentOid,AccessExclusiveLock);
1189+
}
11601190
}
11611191

11621192
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp