Skip to content

Commit 7c0ca29

Browse files
committed
Don't lock tables in RelationGetPartitionDispatchInfo.
Instead, lock them in the caller using find_all_inheritors so that they get locked in the standard order, minimizing deadlock risks. Also in RelationGetPartitionDispatchInfo, avoid opening tables which are not partitioned; there's no need. Amit Langote, reviewed by Ashutosh Bapat and Amit Khandekar Discussion: http://postgr.es/m/91b36fa1-c197-b72f-ca6e-56c593bae68c@lab.ntt.co.jp
1 parent de1ca69 commit 7c0ca29

File tree

3 files changed

+37
-31
lines changed

3 files changed

+37
-31
lines changed

src/backend/catalog/partition.c

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,12 +1000,16 @@ get_partition_qual_relid(Oid relid)
10001000
* RelationGetPartitionDispatchInfo
10011001
* Returns information necessary to route tuples down a partition tree
10021002
*
1003-
* All the partitions will be locked with lockmode, unless it is NoLock.
1004-
* A list of the OIDs of all the leaf partitions of rel is returned in
1005-
* *leaf_part_oids.
1003+
* The number of elements in the returned array (that is, the number of
1004+
* PartitionDispatch objects for the partitioned tables in the partition tree)
1005+
* is returned in *num_parted and a list of the OIDs of all the leaf
1006+
* partitions of rel is returned in *leaf_part_oids.
1007+
*
1008+
* All the relations in the partition tree (including 'rel') must have been
1009+
* locked (using at least the AccessShareLock) by the caller.
10061010
*/
10071011
PartitionDispatch *
1008-
RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
1012+
RelationGetPartitionDispatchInfo(Relation rel,
10091013
int *num_parted, List **leaf_part_oids)
10101014
{
10111015
PartitionDispatchData **pd;
@@ -1020,14 +1024,18 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
10201024
offset;
10211025

10221026
/*
1023-
* Lock partitions and make a list of the partitioned ones to prepare
1024-
* their PartitionDispatch objects below.
1027+
* We rely on the relcache to traverse the partition tree to build both
1028+
* the leaf partition OIDs list and the array of PartitionDispatch objects
1029+
* for the partitioned tables in the tree. That means every partitioned
1030+
* table in the tree must be locked, which is fine since we require the
1031+
* caller to lock all the partitions anyway.
10251032
*
1026-
* Cannot use find_all_inheritors() here, because then the order of OIDs
1027-
* in parted_rels list would be unknown, which does not help, because we
1028-
* assign indexes within individual PartitionDispatch in an order that is
1029-
* predetermined (determined by the order of OIDs in individual partition
1030-
* descriptors).
1033+
* For every partitioned table in the tree, starting with the root
1034+
* partitioned table, add its relcache entry to parted_rels, while also
1035+
* queuing its partitions (in the order in which they appear in the
1036+
* partition descriptor) to be looked at later in the same loop. This is
1037+
* a bit tricky but works because the foreach() macro doesn't fetch the
1038+
* next list element until the bottom of the loop.
10311039
*/
10321040
*num_parted = 1;
10331041
parted_rels = list_make1(rel);
@@ -1036,29 +1044,24 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
10361044
APPEND_REL_PARTITION_OIDS(rel, all_parts, all_parents);
10371045
forboth(lc1, all_parts, lc2, all_parents)
10381046
{
1039-
Relation partrel = heap_open(lfirst_oid(lc1), lockmode);
1047+
Oid partrelid = lfirst_oid(lc1);
10401048
Relation parent = lfirst(lc2);
1041-
PartitionDesc partdesc = RelationGetPartitionDesc(partrel);
10421049

1043-
/*
1044-
* If this partition is a partitioned table, add its children to the
1045-
* end of the list, so that they are processed as well.
1046-
*/
1047-
if (partdesc)
1050+
if (get_rel_relkind(partrelid) == RELKIND_PARTITIONED_TABLE)
10481051
{
1052+
/*
1053+
* Already locked by the caller. Note that it is the
1054+
* responsibility of the caller to close the below relcache entry,
1055+
* once done using the information being collected here (for
1056+
* example, in ExecEndModifyTable).
1057+
*/
1058+
Relation partrel = heap_open(partrelid, NoLock);
1059+
10491060
(*num_parted)++;
10501061
parted_rels = lappend(parted_rels, partrel);
10511062
parted_rel_parents = lappend(parted_rel_parents, parent);
10521063
APPEND_REL_PARTITION_OIDS(partrel, all_parts, all_parents);
10531064
}
1054-
else
1055-
heap_close(partrel, NoLock);
1056-
1057-
/*
1058-
* We keep the partitioned ones open until we're done using the
1059-
* information being collected here (for example, see
1060-
* ExecEndModifyTable).
1061-
*/
10621065
}
10631066

10641067
/*

src/backend/executor/execMain.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "access/xact.h"
4444
#include "catalog/namespace.h"
4545
#include "catalog/partition.h"
46+
#include "catalog/pg_inherits_fn.h"
4647
#include "catalog/pg_publication.h"
4748
#include "commands/matview.h"
4849
#include "commands/trigger.h"
@@ -3249,9 +3250,12 @@ ExecSetupPartitionTupleRouting(Relation rel,
32493250
int i;
32503251
ResultRelInfo *leaf_part_rri;
32513252

3252-
/* Get the tuple-routing information and lock partitions */
3253-
*pd = RelationGetPartitionDispatchInfo(rel, RowExclusiveLock, num_parted,
3254-
&leaf_parts);
3253+
/*
3254+
* Get the information about the partition tree after locking all the
3255+
* partitions.
3256+
*/
3257+
(void) find_all_inheritors(RelationGetRelid(rel), RowExclusiveLock, NULL);
3258+
*pd = RelationGetPartitionDispatchInfo(rel, num_parted, &leaf_parts);
32553259
*num_partitions = list_length(leaf_parts);
32563260
*partitions = (ResultRelInfo *) palloc(*num_partitions *
32573261
sizeof(ResultRelInfo));

src/include/catalog/partition.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ extern Expr *get_partition_qual_relid(Oid relid);
8787

8888
/* For tuple routing */
8989
extern PartitionDispatch *RelationGetPartitionDispatchInfo(Relation rel,
90-
int lockmode, int *num_parted,
91-
List **leaf_part_oids);
90+
int *num_parted, List **leaf_part_oids);
9291
extern void FormPartitionKeyDatum(PartitionDispatch pd,
9392
TupleTableSlot *slot,
9493
EState *estate,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy