diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index cc0db663200f09309280e460f8021c751dea0d2e..8c4270ca1d776aeacc15382545ba933577c2e991 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -79,12 +79,12 @@ TableInfo *
 getSchemaData(int *numTablesPtr)
 {
 	NamespaceInfo *nsinfo;
+	ExtensionInfo *extinfo;
 	AggInfo    *agginfo;
 	InhInfo    *inhinfo;
 	RuleInfo   *ruleinfo;
 	ProcLangInfo *proclanginfo;
 	CastInfo   *castinfo;
-	ExtensionInfo *extinfo;
 	OpclassInfo *opcinfo;
 	OpfamilyInfo *opfinfo;
 	ConvInfo   *convinfo;
@@ -96,12 +96,12 @@ getSchemaData(int *numTablesPtr)
 	ForeignServerInfo *srvinfo;
 	DefaultACLInfo *daclinfo;
 	int			numNamespaces;
+	int			numExtensions;
 	int			numAggregates;
 	int			numInherits;
 	int			numRules;
 	int			numProcLangs;
 	int			numCasts;
-	int			numExtensions;
 	int			numOpclasses;
 	int			numOpfamilies;
 	int			numConversions;
@@ -117,6 +117,10 @@ getSchemaData(int *numTablesPtr)
 		write_msg(NULL, "reading schemas\n");
 	nsinfo = getNamespaces(&numNamespaces);
 
+	if (g_verbose)
+		write_msg(NULL, "reading extensions\n");
+	extinfo = getExtensions(&numExtensions);
+
 	if (g_verbose)
 		write_msg(NULL, "reading user-defined functions\n");
 	funinfo = getFuncs(&numFuncs);
@@ -146,6 +150,10 @@ getSchemaData(int *numTablesPtr)
 		write_msg(NULL, "reading user-defined operator classes\n");
 	opcinfo = getOpclasses(&numOpclasses);
 
+	if (g_verbose)
+		write_msg(NULL, "reading user-defined operator families\n");
+	opfinfo = getOpfamilies(&numOpfamilies);
+
 	if (g_verbose)
 		write_msg(NULL, "reading user-defined text search parsers\n");
 	prsinfo = getTSParsers(&numTSParsers);
@@ -174,14 +182,14 @@ getSchemaData(int *numTablesPtr)
 		write_msg(NULL, "reading default privileges\n");
 	daclinfo = getDefaultACLs(&numDefaultACLs);
 
-	if (g_verbose)
-		write_msg(NULL, "reading user-defined operator families\n");
-	opfinfo = getOpfamilies(&numOpfamilies);
-
 	if (g_verbose)
 		write_msg(NULL, "reading user-defined conversions\n");
 	convinfo = getConversions(&numConversions);
 
+	if (g_verbose)
+		write_msg(NULL, "reading type casts\n");
+	castinfo = getCasts(&numCasts);
+
 	if (g_verbose)
 		write_msg(NULL, "reading user-defined tables\n");
 	tblinfo = getTables(&numTables);
@@ -195,14 +203,14 @@ getSchemaData(int *numTablesPtr)
 		write_msg(NULL, "reading rewrite rules\n");
 	ruleinfo = getRules(&numRules);
 
+	/*
+	 * Identify extension member objects and mark them as not to be dumped.
+	 * This must happen after reading all objects that can be direct members
+	 * of extensions, but before we begin to process table subsidiary objects.
+	 */
 	if (g_verbose)
-		write_msg(NULL, "reading type casts\n");
-	castinfo = getCasts(&numCasts);
-
-	/* this must be after getTables */
-	if (g_verbose)
-		write_msg(NULL, "reading extensions\n");
-	extinfo = getExtensions(&numExtensions);
+		write_msg(NULL, "finding extension members\n");
+	getExtensionMembership(extinfo, numExtensions);
 
 	/* Link tables to parents, mark parents of target tables interesting */
 	if (g_verbose)
@@ -525,9 +533,9 @@ findObjectByDumpId(DumpId dumpId)
  * Returns NULL for unknown ID
  *
  * We use binary search in a sorted list that is built on first call.
- * If AssignDumpId() and findObjectByCatalogId() calls were intermixed,
+ * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed,
  * the code would work, but possibly be very slow.	In the current usage
- * pattern that does not happen, indeed we only need to build the list once.
+ * pattern that does not happen, indeed we build the list at most twice.
  */
 DumpableObject *
 findObjectByCatalogId(CatalogId catalogId)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index dec96bc0253119e77c454febc377ec0abcbf3fdf..83850a8849b48569fde4ef9937dd8496a79775f8 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -766,9 +766,6 @@ main(int argc, char **argv)
 
 	/*
 	 * Collect dependency data to assist in ordering the objects.
-	 *
-	 * (In 9.1 and later, this also marks extension member objects as
-	 * not to be dumped.)
 	 */
 	getDependencies();
 
@@ -1504,15 +1501,10 @@ static void
 dumpTableData(Archive *fout, TableDataInfo *tdinfo)
 {
 	TableInfo  *tbinfo = tdinfo->tdtable;
-	PQExpBuffer copyBuf;
+	PQExpBuffer copyBuf = createPQExpBuffer();
 	DataDumperPtr dumpFn;
 	char	   *copyStmt;
 
-	if (!tdinfo->dobj.dump)
-		return;
-
-	copyBuf = createPQExpBuffer();
-
 	if (!dump_inserts)
 	{
 		/* Dump/restore using COPY */
@@ -1597,7 +1589,6 @@ makeTableDataInfo(TableInfo *tbinfo, bool oids)
 	tdinfo->dobj.dump = true;
 	tdinfo->tdtable = tbinfo;
 	tdinfo->oids = oids;
-	tdinfo->ext_config = false;				/* might get set later */
 	tdinfo->filtercond = NULL;				/* might get set later */
 	addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);
 
@@ -2636,7 +2627,6 @@ getExtensions(int *numExtensions)
 	PGresult   *res;
 	int			ntups;
 	int			i;
-	int			j;
 	PQExpBuffer query;
 	ExtensionInfo *extinfo;
 	int			i_tableoid;
@@ -2681,55 +2671,17 @@ getExtensions(int *numExtensions)
 
 	for (i = 0; i < ntups; i++)
 	{
-		char   *extconfig;
-		char   *extcondition;
-		char  **extconfigarray = NULL;
-		char  **extconditionarray = NULL;
-		int		nconfigitems;
-		int		nconditionitems;
-
 		extinfo[i].dobj.objType = DO_EXTENSION;
 		extinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
 		extinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
 		AssignDumpId(&extinfo[i].dobj);
 		extinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_extname));
 		extinfo[i].namespace = strdup(PQgetvalue(res, i, i_nspname));
+		extinfo[i].extconfig = strdup(PQgetvalue(res, i, i_extconfig));
+		extinfo[i].extcondition = strdup(PQgetvalue(res, i, i_extcondition));
 
 		/* For the moment, all extensions are considered dumpable */
 		extinfo->dobj.dump = true;
-
-		/*
-		 * Find and mark any configuration tables for this extension.
-		 *
-		 * Note that we create TableDataInfo objects even in schemaOnly mode,
-		 * ie, user data in a configuration table is treated like schema data.
-		 * This seems appropriate since system data in a config table would
-		 * get reloaded by CREATE EXTENSION.
-		 */
-		extconfig = PQgetvalue(res, i, i_extconfig);
-		extcondition = PQgetvalue(res, i, i_extcondition);
-		if (parsePGArray(extconfig, &extconfigarray, &nconfigitems) &&
-			parsePGArray(extcondition, &extconditionarray, &nconditionitems) &&
-			nconfigitems == nconditionitems)
-		{
-			for (j = 0; j < nconfigitems; j++)
-			{
-				TableInfo *configtbl;
-
-				configtbl = findTableByOid(atooid(extconfigarray[j]));
-				if (configtbl && configtbl->dataObj == NULL)
-				{
-					makeTableDataInfo(configtbl, false);
-					configtbl->dataObj->ext_config = true;
-					if (strlen(extconditionarray[j]) > 0)
-						configtbl->dataObj->filtercond = strdup(extconditionarray[j]);
-				}
-			}
-		}
-		if (extconfigarray)
-			free(extconfigarray);
-		if (extconditionarray)
-			free(extconditionarray);
 	}
 
 	PQclear(res);
@@ -5200,7 +5152,7 @@ getProcLangs(int *numProcLangs)
 		else
 			planginfo[i].lanowner = strdup("");
 
-		/* Assume it should be dumped (getDependencies may override this) */
+		/* Assume it should be dumped (getExtensionMembership may override) */
 		planginfo[i].dobj.dump = true;
 
 		if (g_fout->remoteVersion < 70300)
@@ -5310,7 +5262,7 @@ getCasts(int *numCasts)
 		castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext));
 		castinfo[i].castmethod = *(PQgetvalue(res, i, i_castmethod));
 
-		/* Assume it should be dumped (getDependencies may override this) */
+		/* Assume it should be dumped (getExtensionMembership may override) */
 		castinfo[i].dobj.dump = true;
 
 		/*
@@ -12855,6 +12807,160 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
 	destroyPQExpBuffer(delcmd);
 }
 
+/*
+ * getExtensionMembership --- obtain extension membership data
+ */
+void
+getExtensionMembership(ExtensionInfo extinfo[], int numExtensions)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+	int			ntups,
+				i;
+	int			i_classid,
+				i_objid,
+				i_refclassid,
+				i_refobjid;
+	DumpableObject *dobj,
+			   *refdobj;
+
+	/* Nothing to do if no extensions */
+	if (numExtensions == 0)
+		return;
+
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
+	query = createPQExpBuffer();
+
+	/* refclassid constraint is redundant but may speed the search */
+	appendPQExpBuffer(query, "SELECT "
+					  "classid, objid, refclassid, refobjid "
+					  "FROM pg_depend "
+					  "WHERE refclassid = 'pg_extension'::regclass "
+					  "AND deptype = 'e' "
+					  "ORDER BY 3,4");
+
+	res = PQexec(g_conn, query->data);
+	check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+	ntups = PQntuples(res);
+
+	i_classid = PQfnumber(res, "classid");
+	i_objid = PQfnumber(res, "objid");
+	i_refclassid = PQfnumber(res, "refclassid");
+	i_refobjid = PQfnumber(res, "refobjid");
+
+	/*
+	 * Since we ordered the SELECT by referenced ID, we can expect that
+	 * multiple entries for the same extension will appear together; this
+	 * saves on searches.
+	 */
+	refdobj = NULL;
+
+	for (i = 0; i < ntups; i++)
+	{
+		CatalogId	objId;
+		CatalogId	refobjId;
+
+		objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
+		objId.oid = atooid(PQgetvalue(res, i, i_objid));
+		refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid));
+		refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
+
+		if (refdobj == NULL ||
+			refdobj->catId.tableoid != refobjId.tableoid ||
+			refdobj->catId.oid != refobjId.oid)
+			refdobj = findObjectByCatalogId(refobjId);
+
+		/*
+		 * Failure to find objects mentioned in pg_depend is not unexpected,
+		 * since for example we don't collect info about TOAST tables.
+		 */
+		if (refdobj == NULL)
+		{
+#ifdef NOT_USED
+			fprintf(stderr, "no referenced object %u %u\n",
+					refobjId.tableoid, refobjId.oid);
+#endif
+			continue;
+		}
+
+		dobj = findObjectByCatalogId(objId);
+
+		if (dobj == NULL)
+		{
+#ifdef NOT_USED
+			fprintf(stderr, "no referencing object %u %u\n",
+					objId.tableoid, objId.oid);
+#endif
+			continue;
+		}
+
+		/* Record dependency so that getDependencies needn't repeat this */
+		addObjectDependency(dobj, refdobj->dumpId);
+
+		/*
+		 * Mark the member object as not to be dumped.  We still need the
+		 * dependency link, to ensure that sorting is done correctly.
+		 */
+		dobj->dump = false;
+	}
+
+	PQclear(res);
+
+	/*
+	 * Now identify extension configuration tables and create TableDataInfo
+	 * objects for them, ensuring their data will be dumped even though the
+	 * tables themselves won't be.
+	 *
+	 * Note that we create TableDataInfo objects even in schemaOnly mode,
+	 * ie, user data in a configuration table is treated like schema data.
+	 * This seems appropriate since system data in a config table would
+	 * get reloaded by CREATE EXTENSION.
+	 */
+	for (i = 0; i < numExtensions; i++)
+	{
+		char   *extconfig = extinfo[i].extconfig;
+		char   *extcondition = extinfo[i].extcondition;
+		char  **extconfigarray = NULL;
+		char  **extconditionarray = NULL;
+		int		nconfigitems;
+		int		nconditionitems;
+
+		if (parsePGArray(extconfig, &extconfigarray, &nconfigitems) &&
+			parsePGArray(extcondition, &extconditionarray, &nconditionitems) &&
+			nconfigitems == nconditionitems)
+		{
+			int		j;
+
+			for (j = 0; j < nconfigitems; j++)
+			{
+				TableInfo *configtbl;
+
+				configtbl = findTableByOid(atooid(extconfigarray[j]));
+				if (configtbl && configtbl->dataObj == NULL)
+				{
+					/*
+					 * Note: config tables are dumped without OIDs regardless
+					 * of the --oids setting.  This is because row filtering
+					 * conditions aren't compatible with dumping OIDs.
+					 */
+					makeTableDataInfo(configtbl, false);
+					if (strlen(extconditionarray[j]) > 0)
+						configtbl->dataObj->filtercond = strdup(extconditionarray[j]);
+				}
+			}
+		}
+		if (extconfigarray)
+			free(extconfigarray);
+		if (extconditionarray)
+			free(extconditionarray);
+	}
+
+	destroyPQExpBuffer(query);
+}
+
 /*
  * getDependencies --- obtain available dependency data
  */
@@ -12885,10 +12991,14 @@ getDependencies(void)
 
 	query = createPQExpBuffer();
 
+	/*
+	 * PIN dependencies aren't interesting, and EXTENSION dependencies were
+	 * already processed by getExtensionMembership.
+	 */
 	appendPQExpBuffer(query, "SELECT "
 					  "classid, objid, refclassid, refobjid, deptype "
 					  "FROM pg_depend "
-					  "WHERE deptype != 'p' "
+					  "WHERE deptype != 'p' AND deptype != 'e' "
 					  "ORDER BY 1,2");
 
 	res = PQexec(g_conn, query->data);
@@ -12964,24 +13074,6 @@ getDependencies(void)
 		else
 			/* normal case */
 			addObjectDependency(dobj, refdobj->dumpId);
-
-		/*
-		 * If it's an extension-membership dependency, mark the member
-		 * object as not to be dumped.  We still need the dependency links,
-		 * though, to ensure that sorting is done correctly.
-		 */
-		if (deptype == 'e')
-		{
-			dobj->dump = false;
-			if (dobj->objType == DO_TABLE)
-			{
-				/* Mark the data as not to be dumped either, unless config */
-				TableDataInfo *tdinfo = ((TableInfo *) dobj)->dataObj;
-
-				if (tdinfo && !tdinfo->ext_config)
-					tdinfo->dobj.dump = false;
-			}
-		}
 	}
 
 	PQclear(res);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index f0e9ae1e06442d75a3d89c717ec89e8d941f7718..140d02d1f8083890753cc57cece9b0b2247500b4 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -144,6 +144,8 @@ typedef struct _extensionInfo
 {
 	DumpableObject dobj;
 	char       *namespace;		/* schema containing extension's objects */
+	char       *extconfig;		/* info about configuration tables */
+	char       *extcondition;
 } ExtensionInfo;
 
 typedef struct _typeInfo
@@ -295,7 +297,6 @@ typedef struct _tableDataInfo
 	DumpableObject dobj;
 	TableInfo  *tdtable;		/* link to table to dump */
 	bool		oids;			/* include OIDs in data? */
-	bool		ext_config;		/* is table an extension config table? */
 	char	   *filtercond;		/* WHERE condition to limit rows dumped */
 } TableDataInfo;
 
@@ -546,5 +547,6 @@ extern TSConfigInfo *getTSConfigurations(int *numTSConfigs);
 extern FdwInfo *getForeignDataWrappers(int *numForeignDataWrappers);
 extern ForeignServerInfo *getForeignServers(int *numForeignServers);
 extern DefaultACLInfo *getDefaultACLs(int *numDefaultACLs);
+extern void getExtensionMembership(ExtensionInfo extinfo[], int numExtensions);
 
 #endif   /* PG_DUMP_H */