diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result
index 5c28203ecf8..50da3dc7b2b 100644
--- a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result
+++ b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result
@@ -44,7 +44,6 @@ ALTER TABLE t1 DISCARD TABLESPACE;
 restore: t1 .ibd and .cfg files
 ALTER TABLE t1 DISCARD TABLESPACE;
 Warnings:
-Warning	1814	Tablespace has been discarded for table `t1`
 Warning	1812	Tablespace is missing for table 'test/t1'
 restore: t1 .ibd and .cfg files
 ALTER TABLE t1 IMPORT TABLESPACE;
diff --git a/mysql-test/suite/innodb/r/import_tablespace_race.result b/mysql-test/suite/innodb/r/import_tablespace_race.result
new file mode 100644
index 00000000000..786b8cbd261
--- /dev/null
+++ b/mysql-test/suite/innodb/r/import_tablespace_race.result
@@ -0,0 +1,26 @@
+#
+# MDEV-29144 ER_TABLE_SCHEMA_MISMATCH or crash on DISCARD/IMPORT
+#
+CREATE TABLE t (pk int PRIMARY KEY, c varchar(1024))
+ENGINE=InnoDB CHARSET latin1;
+INSERT INTO t SELECT seq, 'x' FROM seq_1_to_100;
+connect  con1,localhost,root,,test;
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT 0;
+REPEAT
+SET a= a+1;
+UPDATE t SET c = 'xx' WHERE pk = a;
+UNTIL a = 100
+END REPEAT;
+END
+$
+connection default;
+ALTER TABLE t NOWAIT ADD INDEX (c);
+connection con1;
+connection default;
+FLUSH TABLE t FOR EXPORT;
+UNLOCK TABLES;
+DROP TABLE t;
+ALTER TABLE t DISCARD TABLESPACE;
+ALTER TABLE t IMPORT TABLESPACE;
+DROP TABLE t;
diff --git a/mysql-test/suite/innodb/t/import_tablespace_race.test b/mysql-test/suite/innodb/t/import_tablespace_race.test
new file mode 100644
index 00000000000..532c2684dde
--- /dev/null
+++ b/mysql-test/suite/innodb/t/import_tablespace_race.test
@@ -0,0 +1,54 @@
+--source include/have_innodb.inc
+--source include/have_sequence.inc
+
+--echo #
+--echo # MDEV-29144 ER_TABLE_SCHEMA_MISMATCH or crash on DISCARD/IMPORT
+--echo #
+
+CREATE TABLE t (pk int PRIMARY KEY, c varchar(1024))
+ENGINE=InnoDB CHARSET latin1;
+INSERT INTO t SELECT seq, 'x' FROM seq_1_to_100;
+
+--connect (con1,localhost,root,,test)
+--delimiter $
+--send
+  BEGIN NOT ATOMIC
+    DECLARE a INT DEFAULT 0;
+    REPEAT
+      SET a= a+1;
+      UPDATE t SET c = 'xx' WHERE pk = a;
+    UNTIL a = 100
+    END REPEAT;
+  END
+$
+--delimiter ;
+
+--connection default
+--error 0,ER_LOCK_WAIT_TIMEOUT
+ALTER TABLE t NOWAIT ADD INDEX (c);
+
+--connection con1
+--reap
+
+--connection default
+
+--let $datadir= `select @@datadir`
+
+FLUSH TABLE t FOR EXPORT;
+--let $create= query_get_value(SHOW CREATE TABLE t, Create Table, 1)
+--copy_file $datadir/test/t.cfg $MYSQL_TMP_DIR/t.cfg
+--copy_file $datadir/test/t.ibd $MYSQL_TMP_DIR/t.ibd
+UNLOCK TABLES;
+
+DROP TABLE t;
+--disable_query_log
+eval $create;
+--enable_query_log
+
+ALTER TABLE t DISCARD TABLESPACE;
+--move_file $MYSQL_TMP_DIR/t.cfg $datadir/test/t.cfg
+--move_file $MYSQL_TMP_DIR/t.ibd $datadir/test/t.ibd
+ALTER TABLE t IMPORT TABLESPACE;
+
+# Cleanup
+DROP TABLE t;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 042ed9e1d6f..62a46dbf430 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6075,6 +6075,10 @@ int mysql_discard_or_import_tablespace(THD *thd,
   if (unlikely(error))
     goto err;
 
+  if (discard)
+    tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, table_list->table->s->db.str,
+                     table_list->table->s->table_name.str, true);
+
   /*
     The 0 in the call below means 'not in a transaction', which means
     immediate invalidation; that is probably what we wish here
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index aa1bc5844e3..a1f58091a90 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -6268,11 +6268,6 @@ no_such_table:
 	MONITOR_INC(MONITOR_TABLE_OPEN);
 
 	if ((ib_table->flags2 & DICT_TF2_DISCARDED)) {
-
-		ib_senderrf(thd,
-			IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED,
-			table->s->table_name.str);
-
 		/* Allow an open because a proper DISCARD should have set
 		all the flags and index root page numbers to FIL_NULL that
 		should prevent any DML from running but it should allow DDL
@@ -13631,6 +13626,12 @@ int ha_innobase::truncate()
 	if (ib_table->is_temporary()) {
 		info.options|= HA_LEX_CREATE_TMP_TABLE;
 	} else {
+		if (!ib_table->space) {
+			ib_senderrf(m_user_thd,
+				    IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED,
+				    table->s->table_name.str);
+		}
+
 		dict_get_and_save_data_dir_path(ib_table, false);
 	}
 
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index cd40fe3145e..19c90fed74c 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1013,6 +1013,12 @@ ha_innobase::check_if_supported_inplace_alter(
 
 	update_thd();
 
+	if (!m_prebuilt->table->space) {
+		ib_senderrf(m_user_thd, IB_LOG_LEVEL_WARN,
+			    ER_TABLESPACE_DISCARDED,
+			    table->s->table_name.str);
+	}
+
 	if (ha_alter_info->handler_flags
 	    & ~(INNOBASE_INPLACE_IGNORE
 		| INNOBASE_ALTER_INSTANT
diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc
index 94a372bd046..5af026ecbe8 100644
--- a/storage/innobase/row/row0quiesce.cc
+++ b/storage/innobase/row/row0quiesce.cc
@@ -106,11 +106,17 @@ row_quiesce_write_indexes(
 	FILE*			file,	/*!< in: file to write to */
 	THD*			thd)	/*!< in/out: session */
 {
+	ulint n_indexes = 0;
+	for (const dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
+	     index; index = UT_LIST_GET_NEXT(indexes, index)) {
+		n_indexes += index->is_committed();
+	}
+
 	{
 		byte		row[sizeof(ib_uint32_t)];
 
 		/* Write the number of indexes in the table. */
-		mach_write_to_4(row, UT_LIST_GET_LEN(table->indexes));
+		mach_write_to_4(row, n_indexes);
 
 		DBUG_EXECUTE_IF("ib_export_io_write_failure_11",
 				close(fileno(file)););
@@ -132,6 +138,12 @@ row_quiesce_write_indexes(
 	     index != 0 && err == DB_SUCCESS;
 	     index = UT_LIST_GET_NEXT(indexes, index)) {
 
+		if (!index->is_committed()) {
+			continue;
+		}
+
+		ut_ad(n_indexes); ut_d(n_indexes--);
+
 		byte*		ptr;
 		byte		row[sizeof(index_id_t)
 				    + sizeof(ib_uint32_t) * 8];
@@ -202,6 +214,7 @@ row_quiesce_write_indexes(
 		err = row_quiesce_write_index_fields(index, file, thd);
 	}
 
+	ut_ad(!n_indexes);
 	return(err);
 }