diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 3aeef30b28..d3a0fbfb9c 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2534,9 +2534,6 @@ CopyMultiInsertBufferCleanup(CopyMultiInsertInfo *miinfo,
 	for (i = 0; i < MAX_BUFFERED_TUPLES && buffer->slots[i] != NULL; i++)
 		ExecDropSingleTupleTableSlot(buffer->slots[i]);
 
-	table_finish_bulk_insert(buffer->resultRelInfo->ri_RelationDesc,
-							 miinfo->ti_options);
-
 	pfree(buffer);
 }
 
@@ -3355,10 +3352,24 @@ CopyFrom(CopyState cstate)
 		target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
 															  target_resultRelInfo);
 
-	/* Tear down the multi-insert buffer data */
+	/* Tear down the multi-insert buffer data. */
 	if (insertMethod != CIM_SINGLE)
+	{
 		CopyMultiInsertInfoCleanup(&multiInsertInfo);
 
+		/* Finalize bulk inserts for each relation we inserted tuples into. */
+		if (proute)
+		{
+			List	   *rels = ExecGetRoutedToRelations(proute);
+			ListCell   *lc;
+
+			foreach(lc, rels)
+				table_finish_bulk_insert((Relation) lfirst(lc), multiInsertInfo.ti_options);
+		}
+		else
+			table_finish_bulk_insert(cstate->rel, multiInsertInfo.ti_options);
+	}
+
 	ExecCloseIndices(target_resultRelInfo);
 
 	/* Close all the partitioned tables, leaf partitions, and their indices */
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 729dc396a9..9dccce7cd2 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -1097,6 +1097,26 @@ ExecInitPartitionDispatchInfo(EState *estate,
 	return pd;
 }
 
+/*
+ * ExecGetRoutedToRelations -- Return all leaf partition relations which were
+ * found by ExecFindPartition() for this proute.
+ */
+List *
+ExecGetRoutedToRelations(PartitionTupleRouting *proute)
+{
+	List	   *result = NIL;
+	int			i;
+
+	for (i = 0; i < proute->num_partitions; i++)
+	{
+		ResultRelInfo *resultRelInfo = proute->partitions[i];
+
+		result = lappend(result, resultRelInfo->ri_RelationDesc);
+	}
+
+	return result;
+}
+
 /*
  * ExecCleanupTupleRouting -- Clean up objects allocated for partition tuple
  * routing.
diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h
index 580734e9c9..98a7819227 100644
--- a/src/include/executor/execPartition.h
+++ b/src/include/executor/execPartition.h
@@ -145,6 +145,7 @@ extern ResultRelInfo *ExecFindPartition(ModifyTableState *mtstate,
 										PartitionTupleRouting *proute,
 										TupleTableSlot *slot,
 										EState *estate);
+extern List *ExecGetRoutedToRelations(PartitionTupleRouting *proute);
 extern void ExecCleanupTupleRouting(ModifyTableState *mtstate,
 									PartitionTupleRouting *proute);
 extern PartitionPruneState *ExecCreatePartitionPruneState(PlanState *planstate,
