diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index f63b5ef420b..7604f1a0064 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1301,6 +1301,7 @@ RemoveFunctionById(Oid funcOid)
 	Relation	relation;
 	HeapTuple	tup;
 	char		prokind;
+	remove_function_plancache RemoveFunctionPlanCacheById;
 
 	/*
 	 * Delete the pg_proc tuple.
@@ -1311,6 +1312,11 @@ RemoveFunctionById(Oid funcOid)
 	if (!HeapTupleIsValid(tup)) /* should not happen */
 		elog(ERROR, "cache lookup failed for function %u", funcOid);
 
+	/* Try to release plancache */
+	RemoveFunctionPlanCacheById = (remove_function_plancache) *find_rendezvous_variable("RemoveFunctionPlanCacheById");
+	if (RemoveFunctionPlanCacheById != NULL)
+		RemoveFunctionPlanCacheById(funcOid);
+
 	prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
 
 	CatalogTupleDelete(relation, &tup->t_self);
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index a443181d416..a8e6388a330 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -233,4 +233,5 @@ extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource,
 extern CachedExpression *GetCachedExpression(Node *expr);
 extern void FreeCachedExpression(CachedExpression *cexpr);
 
+typedef void (*remove_function_plancache) (Oid funcoid);
 #endif							/* PLANCACHE_H */
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index a341cde2c14..12adcc37ef9 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -67,6 +67,23 @@ typedef struct plpgsql_hashent
 	PLpgSQL_function *function;
 } plpgsql_HashEnt;
 
+/* ----------
+ * Hash table for recording funcOid and functions
+ * ----------
+ */
+static HTAB *plpgsql_funcOid_HashTable = NULL;
+
+typedef struct PLpgSQL_funcOid_hashkey
+{
+	Oid			funcOid;
+} PLpgSQL_funcOid_hashkey;
+
+typedef struct plpgsql_function_hashent
+{
+	PLpgSQL_funcOid_hashkey key;
+	PLpgSQL_function *function;
+} plpgsql_function_hashent;
+
 #define FUNCS_PER_USER		128 /* initial table size */
 
 /* ----------
@@ -121,6 +138,9 @@ static void plpgsql_HashTableInsert(PLpgSQL_function *function,
 									PLpgSQL_func_hashkey *func_key);
 static void plpgsql_HashTableDelete(PLpgSQL_function *function);
 static void delete_function(PLpgSQL_function *func);
+static PLpgSQL_function *plpgsql_funcOid_HashTableLookup(PLpgSQL_funcOid_hashkey *func_key);
+static void plpgsql_funcOid_HashTableInsert(PLpgSQL_function *function);
+static void plpgsql_funcOid_HashTableDelete(PLpgSQL_funcOid_hashkey *func_key);
 
 /* ----------
  * plpgsql_compile		Make an execution tree for a PL/pgSQL function.
@@ -223,6 +243,9 @@ recheck:
 		 */
 		function = do_compile(fcinfo, procTup, function,
 							  &hashkey, forValidator);
+
+		/* Record the relationship between funcOid and function */
+		plpgsql_funcOid_HashTableInsert(function);
 	}
 
 	ReleaseSysCache(procTup);
@@ -2670,3 +2693,87 @@ plpgsql_HashTableDelete(PLpgSQL_function *function)
 	/* remove back link, which no longer points to allocated storage */
 	function->fn_hashkey = NULL;
 }
+
+/* Try to delete and release the plan cache from the hash table */
+void
+RemoveFunctionPlanCacheById(Oid funcoid)
+{
+	PLpgSQL_funcOid_hashkey func_key;
+	PLpgSQL_function 	*function = NULL;
+
+	func_key.funcOid = funcoid;
+	function = plpgsql_funcOid_HashTableLookup(&func_key);
+	if (function)
+	{
+		plpgsql_funcOid_HashTableDelete(&func_key);
+		delete_function(function);
+	}
+}
+
+void
+plpgsql_funcOid_HashTableInit(void)
+{
+	HASHCTL		ctl;
+
+	/* don't allow double-initialization */
+	Assert(plpgsql_funcOid_HashTable == NULL);
+
+	ctl.keysize = sizeof(PLpgSQL_funcOid_hashkey);
+	ctl.entrysize = sizeof(plpgsql_function_hashent);
+	plpgsql_funcOid_HashTable = hash_create("PLpgSQL function Oid hash",
+											FUNCS_PER_USER,
+											&ctl,
+											HASH_ELEM | HASH_BLOBS);
+}
+
+static PLpgSQL_function *
+plpgsql_funcOid_HashTableLookup(PLpgSQL_funcOid_hashkey *func_key)
+{
+	plpgsql_function_hashent *hentry;
+
+	hentry = (plpgsql_function_hashent *) hash_search(plpgsql_funcOid_HashTable,
+													  func_key,
+													  HASH_FIND,
+													  NULL);
+	if (hentry)
+		return hentry->function;
+	else
+		return NULL;
+}
+
+static void
+plpgsql_funcOid_HashTableInsert(PLpgSQL_function *function)
+{
+	bool		found;
+	plpgsql_function_hashent *hentry;
+	PLpgSQL_funcOid_hashkey func_key;
+	func_key.funcOid = function->fn_oid;
+
+	if (plpgsql_funcOid_HashTableLookup(&func_key))
+		return;
+
+	hentry = (plpgsql_function_hashent *) hash_search(plpgsql_funcOid_HashTable,
+													  &func_key,
+													  HASH_ENTER,
+													  &found);
+
+	hentry->function = function;
+	hentry->key.funcOid = func_key.funcOid;
+}
+
+static void
+plpgsql_funcOid_HashTableDelete(PLpgSQL_funcOid_hashkey *func_key)
+{
+	plpgsql_function_hashent *hentry;
+
+	hentry = (plpgsql_function_hashent *) hash_search(plpgsql_funcOid_HashTable,
+													  func_key,
+													  HASH_REMOVE,
+													  NULL);
+	if (hentry == NULL)
+		elog(WARNING, "trying to delete function that does not exist");
+
+	/* remove back link, which no longer points to allocated storage */
+	hentry->function = NULL;
+	hentry->key.funcOid = InvalidOid;
+}
\ No newline at end of file
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index d8994538b76..7edbf974979 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -146,6 +146,7 @@ _PG_init(void)
 {
 	/* Be sure we do initialization only once (should be redundant now) */
 	static bool inited = false;
+	remove_function_plancache *remove_function_plancache_ptr;
 
 	if (inited)
 		return;
@@ -203,6 +204,10 @@ _PG_init(void)
 	RegisterXactCallback(plpgsql_xact_cb, NULL);
 	RegisterSubXactCallback(plpgsql_subxact_cb, NULL);
 
+	plpgsql_funcOid_HashTableInit();
+	remove_function_plancache_ptr = (remove_function_plancache *) find_rendezvous_variable("RemoveFunctionPlanCacheById");
+	*remove_function_plancache_ptr = &RemoveFunctionPlanCacheById;
+
 	/* Set up a rendezvous point with optional instrumentation plugin */
 	plpgsql_plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin");
 
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index cead9eb7263..3ce25635009 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -1263,6 +1263,8 @@ extern PLpgSQL_condition *plpgsql_parse_err_condition(char *condname);
 extern void plpgsql_adddatum(PLpgSQL_datum *newdatum);
 extern int	plpgsql_add_initdatums(int **varnos);
 extern void plpgsql_HashTableInit(void);
+extern void plpgsql_funcOid_HashTableInit(void);
+extern void RemoveFunctionPlanCacheById(Oid funcoid);
 
 /*
  * Functions in pl_exec.c
