diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index 719396836ec..8da589ae4c0 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -37,6 +37,7 @@ Full Text Search interface
 #include "fts0plugin.h"
 #include "dict0stats.h"
 #include "btr0pcur.h"
+#include "row0ins.h"
 
 static const ulint FTS_MAX_ID_LEN = 32;
 
@@ -155,6 +156,32 @@ const  fts_index_selector_t fts_index_selector[] = {
 	{  0 , NULL	 }
 };
 
+dberr_t fts_system_table_query::insert_operation(
+   dict_table_t *table, dtuple_t *tuple)
+{
+  dberr_t err= lock_table(table, nullptr, LOCK_IX, m_thr);
+  if (err!= DB_SUCCESS)
+    return err;
+  dict_index_t *index= dict_table_get_first_index(table);
+  while (index)
+  {
+    dtuple_t *entry= dtuple_create(m_heap, index->n_fields);
+    dict_index_copy_types(entry, index, index->n_fields);
+    dtuple_set_n_fields_cmp(entry, index->n_uniq);
+    err= row_ins_index_entry_set_vals(index, entry, tuple);
+    if (err != DB_SUCCESS)
+      return err;
+    if (index->is_primary())
+      err= row_ins_clust_index_entry(index, entry, m_thr, 0);
+    else err= row_ins_sec_index_entry(index, entry, m_thr);
+
+    if (err != DB_SUCCESS)
+      return err;
+    index= dict_table_get_next_index(index);
+  }
+  return err;
+}
+
 /** Default config values for FTS indexes on a table. */
 static const char* fts_config_table_insert_values_sql =
 	"PROCEDURE P() IS\n"
@@ -256,6 +283,14 @@ static
 void
 fts_cache_destroy(fts_cache_t* cache)
 {
+	for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) {
+		fts_index_cache_t* index_cache =
+			static_cast<fts_index_cache_t*>(
+				ib_vector_get(cache->indexes, i));
+		delete index_cache->aux_tables;
+	}
+
+	delete cache->common_tables;
 	mysql_mutex_destroy(&cache->lock);
 	mysql_mutex_destroy(&cache->init_lock);
 	mysql_mutex_destroy(&cache->deleted_lock);
@@ -835,6 +870,7 @@ fts_drop_index(
 				rbt_free(index_cache->words);
 			}
 
+			delete index_cache->aux_tables;
 			ib_vector_remove(cache->indexes, *(void**) index_cache);
 		}
 
@@ -1291,7 +1327,7 @@ fts_cache_add_doc(
 				ib_vector_last(word->nodes));
 		}
 
-		if (fts_node == NULL || fts_node->ilist_size > FTS_ILIST_MAX_SIZE
+		if (!fts_node || fts_node->ilist_size > FTS_ILIST_MAX_SIZE
 		    || doc_id < fts_node->last_doc_id) {
 
 			fts_node = static_cast<fts_node_t*>(
@@ -1850,6 +1886,7 @@ fts_create_common_tables(
 				[MAX_FULL_NAME_LEN];
 
 	dict_index_t*					index = NULL;
+	fts_cache_t*	fts_cache = table->fts->cache;
 
 	FTS_INIT_FTS_TABLE(&fts_table, NULL, FTS_COMMON_TABLE, table);
 
@@ -1874,6 +1911,13 @@ fts_create_common_tables(
 			goto func_exit;
 		}
 
+		dict_sys.prevent_eviction(common_table);
+
+		if (fts_cache->common_tables == nullptr) {
+			fts_cache->common_tables = new fts_aux_list();
+		}
+
+		fts_cache->common_tables->push_back(common_table);
 		mem_heap_empty(heap);
 	}
 
@@ -2013,17 +2057,30 @@ CREAT TABLE $FTS_PREFIX_INDEX_[1-6](
 dberr_t
 fts_create_index_tables(trx_t* trx, const dict_index_t* index, table_id_t id)
 {
-	ulint		i;
 	fts_table_t	fts_table;
 	dberr_t		error = DB_SUCCESS;
 	mem_heap_t*	heap = mem_heap_create(1024);
-
+	fts_cache_t*	fts_cache = index->table->fts->cache;
+	fts_index_cache_t* index_cache= nullptr;
 	fts_table.type = FTS_INDEX_TABLE;
 	fts_table.index_id = index->id;
 	fts_table.table_id = id;
 	fts_table.table = index->table;
 
-	for (i = 0; i < FTS_NUM_AUX_INDEX && error == DB_SUCCESS; ++i) {
+	for (ulint i = 0; i < ib_vector_size(fts_cache->indexes); i++) {
+		fts_index_cache_t *temp_cache =
+			static_cast<fts_index_cache_t*>(
+				ib_vector_get(fts_cache->indexes, i));
+		if (temp_cache->index != index) {
+			continue;
+		}
+
+		index_cache = temp_cache;
+	}
+
+	ut_ad(index_cache);
+
+	for (ulint i = 0; i < FTS_NUM_AUX_INDEX && error == DB_SUCCESS; ++i) {
 		dict_table_t*	new_table;
 
 		/* Create the FTS auxiliary tables that are specific
@@ -2038,6 +2095,14 @@ fts_create_index_tables(trx_t* trx, const dict_index_t* index, table_id_t id)
 			break;
 		}
 
+		dict_sys.prevent_eviction(new_table);
+
+		if (index_cache->aux_tables == nullptr) {
+			index_cache->aux_tables = new fts_aux_list();
+		}
+
+		index_cache->aux_tables->push_back(new_table);
+
 		mem_heap_empty(heap);
 	}
 
@@ -3673,6 +3738,72 @@ fts_doc_fetch_by_doc_id(
 	return(error);
 }
 
+static dtuple_t* fts_write_construct_aux_tuple(
+	dict_table_t *aux_table, fts_string_t *word,
+	fts_node_t *node, byte *sys_buf, mem_heap_t *heap)
+{
+  dtuple_t *tuple= dtuple_create(heap, aux_table->n_cols);
+
+  dict_table_copy_types(tuple, aux_table);
+
+  dfield_set_data(dtuple_get_nth_field(tuple, 0), word->f_str, word->f_len);
+
+  byte *first_doc_id= static_cast<byte*>(mem_heap_alloc(heap, 8));
+  mach_write_to_8(first_doc_id, node->first_doc_id);
+  dfield_set_data(dtuple_get_nth_field(tuple, 1), first_doc_id, 8);
+
+  byte *last_doc_id= static_cast<byte*>(mem_heap_alloc(heap, 8));
+  mach_write_to_8(last_doc_id, node->last_doc_id);
+  dfield_set_data(dtuple_get_nth_field(tuple, 2), last_doc_id, 8);
+
+  byte *doc_count= static_cast<byte*>(mem_heap_alloc(heap, 4));
+  mach_write_to_4(doc_count, node->doc_count);
+  dfield_set_data(dtuple_get_nth_field(tuple, 3), doc_count, 4);
+
+  dfield_set_data(
+    dtuple_get_nth_field(tuple, 4), node->ilist, node->ilist_size);
+
+  dfield_set_data(
+    dtuple_get_nth_field(tuple, 5), sys_buf, DATA_ROW_ID_LEN);
+
+  dfield_set_data(
+    dtuple_get_nth_field(tuple, 6), &sys_buf[DATA_ROW_ID_LEN],
+    DATA_TRX_ID_LEN);
+
+  dfield_set_data(
+    dtuple_get_nth_field(tuple, 7),
+    &sys_buf[DATA_ROW_ID_LEN + DATA_TRX_ID_LEN], DATA_ROLL_PTR_LEN);
+
+  return tuple;
+}
+
+dberr_t fts_write_insert(
+  dict_table_t *table, que_thr_t *thr,		       
+  dtuple_t *tuple, mem_heap_t *heap)
+{
+  dberr_t err= lock_table(table, nullptr, LOCK_IX, thr);
+  if (err != DB_SUCCESS)
+    return err;
+  dict_index_t *index= dict_table_get_first_index(table);
+  while (index != nullptr)
+  {
+    dtuple_t *entry= dtuple_create(heap, index->n_fields);
+    dict_index_copy_types(entry, index, index->n_fields);
+    dtuple_set_n_fields_cmp(entry, index->n_uniq);
+    err= row_ins_index_entry_set_vals(index, entry, tuple);
+    if (err != DB_SUCCESS)
+      return err;
+    if (index->is_primary())
+      err= row_ins_clust_index_entry(index, entry, thr, 0);
+    else err= row_ins_sec_index_entry(index, entry, thr);
+    
+    if (err != DB_SUCCESS)
+      return err;
+    index= dict_table_get_next_index(index);
+  }
+  return err;
+}
+
 /*********************************************************************//**
 Write out a single word's data as new entry/entries in the INDEX table.
 @return DB_SUCCESS if all OK. */
@@ -3812,15 +3943,19 @@ fts_sync_write_words(
 	trx_t*			trx,
 	fts_index_cache_t*	index_cache)
 {
-	fts_table_t	fts_table;
 	ulint		n_nodes = 0;
 	ulint		n_words = 0;
 	const ib_rbt_node_t* rbt_node;
 	dberr_t		error = DB_SUCCESS;
 	dict_table_t*	table = index_cache->index->table;
+	mem_heap_t*	heap = mem_heap_create(512);
+	que_fork_t*	fork = que_fork_create(heap);
+	que_thr_t*	thr = que_thr_create(fork, heap, nullptr);
+	byte* sys_buf = static_cast<byte*>(mem_heap_zalloc(
+		heap,
+		DATA_ROW_ID_LEN + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN));
 
-	FTS_INIT_INDEX_TABLE(
-		&fts_table, NULL, FTS_INDEX_TABLE, index_cache->index);
+	fork->trx = trx;
 
 	n_words = rbt_size(index_cache->words);
 
@@ -3845,16 +3980,21 @@ fts_sync_write_words(
 			index_cache->charset, word->text.f_str,
 			word->text.f_len);
 
-		fts_table.suffix = fts_get_suffix(selected);
+		dict_table_t *aux_table = static_cast<dict_table_t*>(
+			index_cache->aux_tables->at(selected));
+
 
 		for (i = 0; i < ib_vector_size(word->nodes); ++i) {
 
 			fts_node_t* fts_node = static_cast<fts_node_t*>(
 				ib_vector_get(word->nodes, i));
 
-			error = fts_write_node(
-				trx, &index_cache->ins_graph[selected],
-				&fts_table, &word->text, fts_node);
+			dtuple_t *tuple = fts_write_construct_aux_tuple(
+				aux_table, &word->text, fts_node,
+				sys_buf, heap);
+
+			error = fts_write_insert(
+				aux_table, thr, tuple, heap);
 
 			DEBUG_SYNC_C("fts_write_node");
 			DBUG_EXECUTE_IF("fts_write_node_crash",
@@ -3865,9 +4005,6 @@ fts_sync_write_words(
 						std::chrono::seconds(1)););
 
 			if (error != DB_SUCCESS) {
-				ib::error() << "(" << error << ") writing "
-					"word node to FTS auxiliary "
-					"index table " << table->name;
 				goto err_exit;
 			}
 		}
@@ -3886,6 +4023,7 @@ fts_sync_write_words(
 		       (double) n_nodes / (double) (n_words > 1 ? n_words : 1));
 	}
 
+	mem_heap_free(heap);
 	return(error);
 }
 
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 9cc56f184fd..090c21747c1 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -1440,7 +1440,12 @@ fts_optimize_write_word(
 	ulint		selected;
 	dberr_t		error = DB_SUCCESS;
 	char		table_name[MAX_FULL_NAME_LEN];
-
+#if 0
+	mem_heap_t*	heap = nullptr;
+	byte*		sys_buf = nullptr;
+	que_fork_t*	fork = nullptr;
+	que_thr_t*	thr = nullptr;
+#endif
 	info = pars_info_create();
 
 	ut_ad(fts_table->charset);
@@ -1469,7 +1474,10 @@ fts_optimize_write_word(
 
 	que_graph_free(graph);
 	graph = NULL;
-
+#if 0
+	dict_table_t *aux_table = static_cast<dict_table_t*>(
+		index_cache->aux_tables->at(selected));
+#endif
 	/* Even if the operation needs to be rolled back and redone,
 	we iterate over the nodes in order to free the ilist. */
 	for (i = 0; i < ib_vector_size(nodes); ++i) {
@@ -1482,10 +1490,29 @@ fts_optimize_write_word(
 				ut_ad(node->ilist_size == 0);
 				continue;
 			}
+#if 0
+			if (heap == nullptr) {
+				heap = mem_heap_create(512);
+				fork = que_fork_create(heap);
+				thr = que_thr_create(fork, heap, nullptr);
+				sys_buf = static_cast<byte*>(
+					mem_heap_zalloc(
+						heap,
+						DATA_ROW_ID_LEN +
+						DATA_TRX_ID_LEN +
+						DATA_ROLL_PTR_LEN));
+				fork->trx = trx;
+			}
+
+			dtuple_t *tuple = fts_write_construct_aux_tuple(
+				aux_table, word, node, sys_buf, heap);
 
+			error = fts_write_insert(
+				aux_table, thr, tuple, heap);
+#endif
 			error = fts_write_node(
 				trx, &graph, fts_table, word, node);
-
+			
 			if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
 				ib::error() << "(" << error << ")"
 					" during optimize, while adding a"
@@ -1501,7 +1528,11 @@ fts_optimize_write_word(
 	if (graph != NULL) {
 		que_graph_free(graph);
 	}
-
+#if 0
+	if (heap) {
+		mem_heap_free(heap);
+	}
+#endif
 	return(error);
 }
 
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 7fe70b969d4..d26295f9a72 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -11405,9 +11405,7 @@ ha_innobase::commit_inplace_alter_table(
 			     ctx->new_table, CHECK_ABORTED_OK));
 
 #ifdef UNIV_DEBUG
-		if (ctx->new_table->fts != NULL) {
-			ut_a(fts_check_cached_index(ctx->new_table));
-		}
+		ut_ad(!ctx->new_table->fts || fts_check_cacheed_index(ctx->new_table));
 #endif
 	}
 
diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h
index ae0bb036e37..59a43cd1e60 100644
--- a/storage/innobase/include/fts0priv.h
+++ b/storage/innobase/include/fts0priv.h
@@ -198,6 +198,17 @@ fts_query_expansion_fetch_doc(
 	void*		row,		/*!< in: sel_node_t* */
 	void*		user_arg)	/*!< in: fts_doc_t* */
 	MY_ATTRIBUTE((nonnull));
+
+/** Insert into the fts related tables
+@param  aux_table	auxilary table
+@param	thr		query thread
+@param	tuple		tuple to be inserted
+@param	heap		heap to be used for insert
+@return error code */
+dberr_t fts_write_insert(
+  dict_table_t *table, que_thr_t *thr,
+  dtuple_t *tuple, mem_heap_t *heap);
+
 /********************************************************************
 Write out a single word's data as new entry/entries in the INDEX table.
 @return DB_SUCCESS if all OK. */
@@ -210,7 +221,6 @@ fts_write_node(
 	fts_string_t*	word,		/*!< in: word in UTF-8 */
 	fts_node_t*	node)		/*!< in: node columns */
 	MY_ATTRIBUTE((nonnull, warn_unused_result));
-
 /** Check if a fts token is a stopword or less than fts_min_token_size
 or greater than fts_max_token_size.
 @param[in]	token		token string
@@ -480,6 +490,132 @@ fts_config_create_index_param_name(
 	const dict_index_t*	index)	/*!< in: index for config */
 	MY_ATTRIBUTE((nonnull, malloc, warn_unused_result));
 
+class fts_system_table_query
+{
+private:
+  mem_heap_t *m_heap= nullptr;
+  que_thr_t *m_thr= nullptr;
+  que_fork_t *m_fork= nullptr;
+  byte *m_sys_buf= nullptr;
+public:
+  void init_query(trx_t *trx)
+  {
+    m_fork= que_fork_create(m_heap);
+    m_thr= que_thr_create(m_fork, m_heap, nullptr);
+    m_sys_buf= static_cast<byte*>(mem_heap_zalloc(
+     m_heap, DATA_ROW_ID_LEN + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN));
+    m_fork->trx= trx;
+  }
+
+  fts_system_table_query(trx_t *trx)
+  {
+    m_heap= mem_heap_create(512);
+    init_query(trx);
+  }
+
+  ~fts_system_table_query()
+  {
+    mem_heap_free(m_heap);
+  }
+
+  void complete_query()
+  {
+    mem_heap_empty(m_heap);
+    m_fork= nullptr;
+    m_thr= nullptr;
+    m_sys_buf= nullptr;
+  }
+
+  fts_index_cache_t* fts_find_cache_index(dict_index_t *index)
+  {
+    fts_cache_t *fts_cache= index->table->fts->cache;
+    for (ulint i= 0; i < ib_vector_size(fts_cache->indexes); i++)
+    {
+      fts_index_cache_t *index_cache= static_cast<fts_index_cache_t*>(
+        ib_vector_get(fts_cache->indexes, i));
+      if (index_cache->index == index)
+	return index_cache;
+    }
+
+    return nullptr;
+  }
+
+  dtuple_t *construct_aux_tuple(dict_table_t *aux_table,
+                                fts_string_t *word,
+				fts_node_t *node)
+  {
+    dtuple_t *tuple= dtuple_create(m_heap, aux_table->n_cols);
+    dict_table_copy_types(tuple, aux_table);
+    /* Field 1: Word */
+    dfield_set_data(dtuple_get_nth_field(tuple, 0),
+		    word->f_str, word->f_len);
+
+    /* Field 2: First doc id */
+    byte *first_doc_id= static_cast<byte*>(mem_heap_alloc(m_heap, 8));
+    mach_write_to_8(first_doc_id, node->first_doc_id);
+    dfield_set_data(dtuple_get_nth_field(tuple, 1), first_doc_id, 8);
+
+    /* Field 3: Last doc id */
+    byte *last_doc_id= static_cast<byte*>(mem_heap_alloc(m_heap, 8));
+    mach_write_to_8(last_doc_id, node->last_doc_id);
+    dfield_set_data(dtuple_get_nth_field(tuple, 2), last_doc_id, 8);
+
+    /* Field 4: Doc count */
+    byte *doc_count= static_cast<byte*>(mem_heap_alloc(m_heap, 4));
+    mach_write_to_4(doc_count, node->doc_count);
+    dfield_set_data(dtuple_get_nth_field(tuple, 3), doc_count, 4);   
+
+    /* Field 5: ilist */
+    dfield_set_data(
+      dtuple_get_nth_field(tuple, 4), node->ilist, node->ilist_size);
+
+    /* Field 6: DB_ROW_ID */
+    dfield_set_data(
+      dtuple_get_nth_field(tuple, 5), m_sys_buf, DATA_ROW_ID_LEN);
+
+    /* Field 7: DB_TRX_ID */
+    dfield_set_data(
+      dtuple_get_nth_field(tuple, 6), &m_sys_buf[DATA_ROW_ID_LEN],
+      DATA_TRX_ID_LEN);
+
+    /* Field 8: DB_ROW_PTR */
+    dfield_set_data(
+      dtuple_get_nth_field(tuple, 7),
+      &m_sys_buf[DATA_ROW_ID_LEN + DATA_TRX_ID_LEN],
+      DATA_ROLL_PTR_LEN);
+
+    return tuple;
+  }
+
+  dberr_t insert_operation(dict_table_t *table, dtuple_t *tuple);
+#if 0
+  {
+    dberr_t err= lock_table(table, nullptr, LOCK_IX, m_thr);
+    if (err!= DB_SUCCESS)
+      return err;
+    dict_index_t *index= dict_table_get_first_index(table);
+    while (index)
+    {
+      dtuple_t *entry= dtuple_create(m_heap, index->n_fields);
+      dict_index_copy_types(entry, index, index->n_fields);
+      dtuple_set_n_fields_cmp(entry, index->n_uniq);
+      err= row_ins_index_entry_set_vals(index, entry, tuple);
+      if (err != DB_SUCCESS)
+        return err;
+      if (index->is_primary())
+        err= row_ins_clust_index_entry(index, entry, m_thr, 0);
+      else err= row_ins_sec_index_entry(index, entry, m_thr);
+
+      if (err != DB_SUCCESS)
+        return err;
+      index= dict_table_get_next_index(index);
+    }
+
+    return err;
+  }
+#endif
+};
+
 #include "fts0priv.inl"
 
 #endif /* INNOBASE_FTS0PRIV_H */
diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h
index 20f1f45a0ae..02482d6fb62 100644
--- a/storage/innobase/include/fts0types.h
+++ b/storage/innobase/include/fts0types.h
@@ -42,6 +42,8 @@ struct fts_node_t;
 typedef pars_user_func_cb_t fts_sql_callback;
 typedef void (*fts_filter)(void*, fts_node_t*, void*, ulint len);
 
+typedef std::vector<dict_table_t*>	fts_aux_list;
+
 /** Statistics relevant to a particular document, used during retrieval. */
 struct fts_doc_stats_t {
 	doc_id_t	doc_id;		/*!< Document id */
@@ -77,6 +79,8 @@ struct fts_index_cache_t {
 	que_t**		ins_graph;	/*!< Insert query graphs */
 
 	CHARSET_INFO*	charset;	/*!< charset */
+
+	fts_aux_list*	aux_tables;
 };
 
 /** Stop word control infotmation. */
@@ -166,6 +170,9 @@ struct fts_cache_t
 					the deleted lock */
 
 	fts_stopword_t	stopword_info;	/*!< Cached stopwords for the FTS */
+
+	fts_aux_list*	common_tables;
+
 	mem_heap_t*	cache_heap;	/*!< Cache Heap */
 };
 
diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h
index 25c09258b3c..ce541a9c83c 100644
--- a/storage/innobase/include/row0ins.h
+++ b/storage/innobase/include/row0ins.h
@@ -151,6 +151,18 @@ row_ins_step(
 /*=========*/
 	que_thr_t*	thr);	/*!< in: query thread */
 
+/** Sets the values of the dtuple fields in entry from the values of appropriate
+columns in row.
+@param[in]      index   index handler
+@param[out]     entry   index entry to make
+@param[in]      row     row
+@return DB_SUCCESS if the set is successful */
+dberr_t
+row_ins_index_entry_set_vals(
+        const dict_index_t*     index,
+        dtuple_t*               entry,
+        const dtuple_t*         row);
+
 /* Insert node types */
 #define INS_SEARCHED	0	/* INSERT INTO ... SELECT ... */
 #define INS_VALUES	1	/* INSERT INTO ... VALUES ... */
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index a002f104516..0470297b9a2 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -3300,7 +3300,6 @@ columns in row.
 @param[out]	entry	index entry to make
 @param[in]	row	row
 @return DB_SUCCESS if the set is successful */
-static
 dberr_t
 row_ins_index_entry_set_vals(
 	const dict_index_t*	index,
