From 124e8123c78e8db5117820a1153d759c6d4d58d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@mariadb.com>
Date: Thu, 14 Dec 2017 14:08:55 +0200
Subject: [PATCH 4/6] Remove the non-ACID InnoDB 'background drop table' queue

InnoDB worked around the lack of proper SQL-level locking for
FOREIGN KEY operations with a hack that would postpone
DROP TABLE operations if foreign key checks were running.
Because MariaDB implements proper MDL around FOREIGN KEY operations
(the corresponding task in MySQL was filed as WL#6049 but not
implemented as of MySQL 5.7), we do not really need this hack.

The same hack was also necessary during the error handling of
CREATE TABLE t2 (PRIMARY KEY (a)) SELECT * FROM t1;
where the SQL layer would invoke DROP TABLE t2 on a duplicate key error.

FIXME: On a failure of CREATE...SELECT, actually let the
transaction rollback drop the table.
---
 .../suite/innodb/r/drop_table_background.result    |  24 --
 .../innodb/r/innodb_skip_innodb_is_tables.result   |   2 -
 mysql-test/suite/innodb/r/monitor.result           |   2 -
 .../suite/innodb/t/drop_table_background.test      |  44 ---
 mysql-test/unstable-tests                          |   1 -
 storage/innobase/btr/btr0scrub.cc                  |   4 -
 storage/innobase/fts/fts0fts.cc                    |   3 +-
 storage/innobase/handler/ha_innodb.cc              |  42 +--
 storage/innobase/handler/handler0alter.cc          |  15 -
 storage/innobase/include/dict0mem.h                |   7 -
 storage/innobase/include/row0mysql.h               |  37 ---
 storage/innobase/include/srv0mon.h                 |   2 -
 storage/innobase/row/row0ins.cc                    |   4 +-
 storage/innobase/row/row0mysql.cc                  | 358 +--------------------
 storage/innobase/srv/srv0mon.cc                    |  10 -
 storage/innobase/srv/srv0srv.cc                    |  44 +--
 storage/innobase/srv/srv0start.cc                  |   5 -
 17 files changed, 23 insertions(+), 581 deletions(-)
 delete mode 100644 mysql-test/suite/innodb/r/drop_table_background.result
 delete mode 100644 mysql-test/suite/innodb/t/drop_table_background.test

diff --git a/mysql-test/suite/innodb/r/drop_table_background.result b/mysql-test/suite/innodb/r/drop_table_background.result
deleted file mode 100644
index e74bcd5e780..00000000000
--- a/mysql-test/suite/innodb/r/drop_table_background.result
+++ /dev/null
@@ -1,24 +0,0 @@
-CREATE TABLE t(c0 SERIAL, c1 INT, c2 INT, c3 INT, c4 INT,
-KEY(c1), KEY(c2), KEY(c2,c1),
-KEY(c3), KEY(c3,c1), KEY(c3,c2), KEY(c3,c2,c1),
-KEY(c4), KEY(c4,c1), KEY(c4,c2), KEY(c4,c2,c1),
-KEY(c4,c3), KEY(c4,c3,c1), KEY(c4,c3,c2), KEY(c4,c3,c2,c1)) ENGINE=InnoDB;
-CREATE TABLE `#mysql50##sql-ib-foo`(a SERIAL) ENGINE=InnoDB;
-INSERT INTO t (c1) VALUES (1),(2),(1);
-SET DEBUG_DBUG='+d,row_drop_table_add_to_background';
-CREATE TABLE target (PRIMARY KEY(c1)) ENGINE=InnoDB SELECT * FROM t;
-ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
-SELECT * from target;
-ERROR 42S02: Table 'test.target' doesn't exist
-DROP TABLE t;
-CREATE TABLE t (a INT) ENGINE=InnoDB;
-DROP TABLE t;
-DROP TABLE target;
-ERROR 42S02: Unknown table 'test.target'
-CREATE TABLE target (a INT) ENGINE=InnoDB;
-DROP TABLE target;
-SELECT * FROM `#mysql50##sql-ib-foo`;
-ERROR 42S02: Table 'test.#mysql50##sql-ib-foo' doesn't exist in engine
-DROP TABLE `#mysql50##sql-ib-foo`;
-Warnings:
-Warning	1932	Table 'test.#mysql50##sql-ib-foo' doesn't exist in engine
diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result
index 79f0e73e745..36e9b063ebe 100644
--- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result
+++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result
@@ -249,7 +249,6 @@ innodb_master_thread_sleeps	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	N
 innodb_activity_count	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	status_counter	Current server activity count
 innodb_master_active_loops	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Number of times master thread performs its tasks when server is active
 innodb_master_idle_loops	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Number of times master thread performs its tasks when server is idle
-innodb_background_drop_table_usec	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Time (in microseconds) spent to process drop table list
 innodb_ibuf_merge_usec	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Time (in microseconds) spent to process change buffer merge
 innodb_log_flush_usec	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Time (in microseconds) spent to flush log records
 innodb_mem_validate_usec	server	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Time (in microseconds) spent to do memory validation
@@ -279,7 +278,6 @@ dml_system_inserts	dml	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	dis
 dml_system_deletes	dml	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	status_counter	Number of system rows deleted
 dml_system_updates	dml	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	status_counter	Number of system rows updated
 ddl_background_drop_indexes	ddl	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Number of indexes waiting to be dropped after failed index creation
-ddl_background_drop_tables	ddl	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Number of tables in background drop table list
 ddl_online_create_index	ddl	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Number of indexes being created online
 ddl_pending_alter_table	ddl	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Number of ALTER TABLE, CREATE INDEX, DROP INDEX in progress
 ddl_sort_file_alter_table	ddl	0	NULL	NULL	NULL	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	disabled	counter	Number of sort files created during alter table
diff --git a/mysql-test/suite/innodb/r/monitor.result b/mysql-test/suite/innodb/r/monitor.result
index 2700479e7f7..f92950cdfac 100644
--- a/mysql-test/suite/innodb/r/monitor.result
+++ b/mysql-test/suite/innodb/r/monitor.result
@@ -214,7 +214,6 @@ innodb_master_thread_sleeps	disabled
 innodb_activity_count	disabled
 innodb_master_active_loops	disabled
 innodb_master_idle_loops	disabled
-innodb_background_drop_table_usec	disabled
 innodb_ibuf_merge_usec	disabled
 innodb_log_flush_usec	disabled
 innodb_mem_validate_usec	disabled
@@ -244,7 +243,6 @@ dml_system_inserts	disabled
 dml_system_deletes	disabled
 dml_system_updates	disabled
 ddl_background_drop_indexes	disabled
-ddl_background_drop_tables	disabled
 ddl_online_create_index	disabled
 ddl_pending_alter_table	disabled
 ddl_sort_file_alter_table	disabled
diff --git a/mysql-test/suite/innodb/t/drop_table_background.test b/mysql-test/suite/innodb/t/drop_table_background.test
deleted file mode 100644
index 8d82bea9675..00000000000
--- a/mysql-test/suite/innodb/t/drop_table_background.test
+++ /dev/null
@@ -1,44 +0,0 @@
---source include/have_innodb.inc
---source include/have_debug.inc
-# Embedded server does not support restarting
---source include/not_embedded.inc
-
-CREATE TABLE t(c0 SERIAL, c1 INT, c2 INT, c3 INT, c4 INT,
-KEY(c1), KEY(c2), KEY(c2,c1),
-KEY(c3), KEY(c3,c1), KEY(c3,c2), KEY(c3,c2,c1),
-KEY(c4), KEY(c4,c1), KEY(c4,c2), KEY(c4,c2,c1),
-KEY(c4,c3), KEY(c4,c3,c1), KEY(c4,c3,c2), KEY(c4,c3,c2,c1)) ENGINE=InnoDB;
-
-CREATE TABLE `#mysql50##sql-ib-foo`(a SERIAL) ENGINE=InnoDB;
-INSERT INTO t (c1) VALUES (1),(2),(1);
-
-let $n= 10;
-
-SET DEBUG_DBUG='+d,row_drop_table_add_to_background';
---disable_query_log
-let $i= $n;
-while ($i) {
-  eval CREATE TABLE t$i LIKE t;
-  dec $i;
-}
-let $i= $n;
-while ($i) {
-  eval DROP TABLE t$i;
-  dec $i;
-}
---enable_query_log
---error ER_DUP_ENTRY
-CREATE TABLE target (PRIMARY KEY(c1)) ENGINE=InnoDB SELECT * FROM t;
---error ER_NO_SUCH_TABLE
-SELECT * from target;
-DROP TABLE t;
---source include/restart_mysqld.inc
-CREATE TABLE t (a INT) ENGINE=InnoDB;
-DROP TABLE t;
---error ER_BAD_TABLE_ERROR
-DROP TABLE target;
-CREATE TABLE target (a INT) ENGINE=InnoDB;
-DROP TABLE target;
---error ER_NO_SUCH_TABLE_IN_ENGINE
-SELECT * FROM `#mysql50##sql-ib-foo`;
-DROP TABLE `#mysql50##sql-ib-foo`;
diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests
index 288df9233a5..a750cfbad81 100644
--- a/mysql-test/unstable-tests
+++ b/mysql-test/unstable-tests
@@ -237,7 +237,6 @@ innodb.alter_missing_tablespace      : Modified in 10.2.7
 innodb.deadlock_detect               : MDEV-13262 - Wrong error code
 innodb.defrag_mdl-9155               : MDEV-11336	- Timeout
 innodb.doublewrite                   : Modified in 10.2.7
-innodb.drop_table_background         : Added in 10.2.7
 innodb.foreign_key                   : Modified in 10.2.8
 innodb.group_commit_binlog_pos       : Modified in 10.2.7
 innodb.group_commit_binlog_pos_no_optimize_thread : Modified in 10.2.7
diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc
index 376a106bf8a..5b6e3af98e3 100644
--- a/storage/innobase/btr/btr0scrub.cc
+++ b/storage/innobase/btr/btr0scrub.cc
@@ -568,10 +568,6 @@ btr_scrub_table_needs_scrubbing(
 		return false;
 	}
 
-	if (table->to_be_dropped) {
-		return false;
-	}
-
 	if (!table->is_readable()) {
 		return false;
 	}
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index 7f2b45bf81e..e58b6270fcf 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -4266,8 +4266,7 @@ fts_sync(
 		index_cache = static_cast<fts_index_cache_t*>(
 			ib_vector_get(cache->indexes, i));
 
-		if (index_cache->index->to_be_dropped
-		   || index_cache->index->table->to_be_dropped) {
+		if (index_cache->index->to_be_dropped) {
 			continue;
 		}
 
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 42582d430e9..3f08f84a4cd 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -13338,6 +13338,16 @@ ha_innobase::delete_table(
 {
 	dberr_t	err;
 	THD*	thd = ha_thd();
+	int	sql_command = thd_sql_command(thd);
+
+	if (sql_command == SQLCOM_CREATE_TABLE) {
+		/* On an error, CREATE TABLE...SELECT may invoke
+		the DROP TABLE functionality. Let us ignore this,
+		and instead let the transaction rollback
+		drop the table. */
+		return 0;
+	}
+
 	char	norm_name[FN_REFLEN];
 
 	DBUG_ENTER("ha_innobase::delete_table");
@@ -13401,7 +13411,7 @@ ha_innobase::delete_table(
 	/* Drop the table in InnoDB */
 
 	err = row_drop_table_for_mysql(
-		norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB,
+		norm_name, trx, sql_command == SQLCOM_DROP_DB,
 		false);
 
 	if (err == DB_TABLE_NOT_FOUND
@@ -13427,7 +13437,7 @@ ha_innobase::delete_table(
 #endif
 			err = row_drop_table_for_mysql(
 				par_case_name, trx,
-				thd_sql_command(thd) == SQLCOM_DROP_DB,
+				sql_command == SQLCOM_DROP_DB,
 				FALSE);
 		}
 	}
@@ -13492,7 +13502,7 @@ ha_innobase::delete_table(
 #endif /* _WIN32 */
 			err = row_drop_table_for_mysql(
 				par_case_name, trx,
-				thd_sql_command(thd) == SQLCOM_DROP_DB,
+				sql_command == SQLCOM_DROP_DB,
 				true);
 		}
 	}
@@ -19131,30 +19141,11 @@ innobase_fts_find_ranking(FT_INFO* fts_hdl, uchar*, uint)
 }
 
 #ifdef UNIV_DEBUG
-static my_bool	innodb_background_drop_list_empty = TRUE;
 static my_bool	innodb_log_checkpoint_now = TRUE;
 static my_bool	innodb_buf_flush_list_now = TRUE;
 static uint	innodb_merge_threshold_set_all_debug
 	= DICT_INDEX_MERGE_THRESHOLD_DEFAULT;
 
-/** Wait for the background drop list to become empty. */
-static
-void
-wait_background_drop_list_empty(
-	THD*				thd	/*!< in: thread handle */
-					MY_ATTRIBUTE((unused)),
-	struct st_mysql_sys_var*	var	/*!< in: pointer to system
-						variable */
-					MY_ATTRIBUTE((unused)),
-	void*				var_ptr	/*!< out: where the formal
-						string goes */
-					MY_ATTRIBUTE((unused)),
-	const void*			save)	/*!< in: immediate result from
-						check function */
-{
-	row_wait_for_background_drop_list_empty();
-}
-
 /****************************************************************//**
 Force innodb to checkpoint. */
 static
@@ -19915,12 +19906,6 @@ static MYSQL_SYSVAR_ULONG(idle_flush_pct,
   NULL, NULL, 100, 0, 100, 0);
 
 #ifdef UNIV_DEBUG
-static MYSQL_SYSVAR_BOOL(background_drop_list_empty,
-  innodb_background_drop_list_empty,
-  PLUGIN_VAR_OPCMDARG,
-  "Wait for the background drop list to become empty",
-  NULL, wait_background_drop_list_empty, FALSE);
-
 static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now,
   PLUGIN_VAR_OPCMDARG,
   "Force checkpoint now",
@@ -21139,7 +21124,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
   MYSQL_SYSVAR(purge_threads),
   MYSQL_SYSVAR(purge_batch_size),
 #ifdef UNIV_DEBUG
-  MYSQL_SYSVAR(background_drop_list_empty),
   MYSQL_SYSVAR(log_checkpoint_now),
   MYSQL_SYSVAR(buf_flush_list_now),
   MYSQL_SYSVAR(merge_threshold_set_all_debug),
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 7d4b15fc40e..fc79b9cb4f3 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -9464,21 +9464,6 @@ ha_innobase::commit_inplace_alter_table(
 			ctx->new_table, altered_table->s);
 
 		if (new_clustered) {
-			/* We will reload and refresh the
-			in-memory foreign key constraint
-			metadata. This is a rename operation
-			in preparing for dropping the old
-			table. Set the table to_be_dropped bit
-			here, so to make sure DML foreign key
-			constraint check does not use the
-			stale dict_foreign_t. This is done
-			because WL#6049 (FK MDL) has not been
-			implemented yet. */
-			ctx->old_table->to_be_dropped = true;
-
-			DBUG_PRINT("to_be_dropped",
-				   ("table: %s", ctx->old_table->name.m_name));
-
 			/* Rename the tablespace files. */
 			commit_cache_rebuild(ctx);
 
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 726a98a2984..279886c040c 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -1563,13 +1563,6 @@ struct dict_table_t {
 	/** TRUE if the table object has been added to the dictionary cache. */
 	unsigned				cached:1;
 
-	/** TRUE if the table is to be dropped, but not yet actually dropped
-	(could in the background drop list). It is turned on at the beginning
-	of row_drop_table_for_mysql() and turned off just before we start to
-	update system tables for the drop. It is protected by
-	dict_operation_lock. */
-	unsigned				to_be_dropped:1;
-
 	/** Number of non-virtual columns defined so far. */
 	unsigned				n_def:10;
 
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 044e732c22d..5f1bb7e76fb 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -404,26 +404,6 @@ row_table_add_foreign_constraints(
 	ibool			reject_fks)
 	MY_ATTRIBUTE((warn_unused_result));
 
-/*********************************************************************//**
-The master thread in srv0srv.cc calls this regularly to drop tables which
-we must drop in background after queries to them have ended. Such lazy
-dropping of tables is needed in ALTER TABLE on Unix.
-@return how many tables dropped + remaining tables in list */
-ulint
-row_drop_tables_for_mysql_in_background(void);
-/*=========================================*/
-/*********************************************************************//**
-Get the background drop list length. NOTE: the caller must own the kernel
-mutex!
-@return how many tables in list */
-ulint
-row_get_background_drop_list_len_low(void);
-/*======================================*/
-
-/** Drop garbage tables during recovery. */
-void
-row_mysql_drop_garbage_tables();
-
 /*********************************************************************//**
 Sets an exclusive lock on a table.
 @return error code or DB_SUCCESS */
@@ -535,17 +515,6 @@ row_scan_index_for_mysql(
 	ulint*			n_rows)		/*!< out: number of entries
 						seen in the consistent read */
 	MY_ATTRIBUTE((warn_unused_result));
-/*********************************************************************//**
-Initialize this module */
-void
-row_mysql_init(void);
-/*================*/
-
-/*********************************************************************//**
-Close this module */
-void
-row_mysql_close(void);
-/*=================*/
 
 /* A struct describing a place for an individual column in the MySQL
 row format which is presented to the table handler in ha_innobase.
@@ -918,10 +887,4 @@ innobase_rename_vc_templ(
 #define ROW_READ_TRY_SEMI_CONSISTENT	1
 #define ROW_READ_DID_SEMI_CONSISTENT	2
 
-#ifdef UNIV_DEBUG
-/** Wait for the background drop list to become empty. */
-void
-row_wait_for_background_drop_list_empty();
-#endif /* UNIV_DEBUG */
-
 #endif /* row0mysql.h */
diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h
index e4034f3a6ff..82e84f643f1 100644
--- a/storage/innobase/include/srv0mon.h
+++ b/storage/innobase/include/srv0mon.h
@@ -397,7 +397,6 @@ enum monitor_id_t {
 	MONITOR_OVLD_SERVER_ACTIVITY,
 	MONITOR_MASTER_ACTIVE_LOOPS,
 	MONITOR_MASTER_IDLE_LOOPS,
-	MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND,
 	MONITOR_SRV_IBUF_MERGE_MICROSECOND,
 	MONITOR_SRV_LOG_FLUSH_MICROSECOND,
 	MONITOR_SRV_MEM_VALIDATE_MICROSECOND,
@@ -433,7 +432,6 @@ enum monitor_id_t {
 	/* Data DDL related counters */
 	MONITOR_MODULE_DDL_STATS,
 	MONITOR_BACKGROUND_DROP_INDEX,
-	MONITOR_BACKGROUND_DROP_TABLE,
 	MONITOR_ONLINE_CREATE_INDEX,
 	MONITOR_PENDING_ALTER_TABLE,
 	MONITOR_ALTER_TABLE_SORT_FILES,
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 51b299e1215..7b4f67057e5 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1912,9 +1912,7 @@ row_ins_check_foreign_constraint(
 
 		thr->lock_state = QUE_THR_LOCK_NOLOCK;
 
-		err = check_table->to_be_dropped
-			? DB_LOCK_WAIT_TIMEOUT
-			: trx->error_state;
+		err = trx->error_state;
 	}
 
 exit_func:
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 7582f3afb18..4c718244258 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -74,26 +74,6 @@ Created 9/17/2000 Heikki Tuuri
 /** Provide optional 4.x backwards compatibility for 5.0 and above */
 ibool	row_rollback_on_timeout	= FALSE;
 
-/** Chain node of the list of tables to drop in the background. */
-struct row_mysql_drop_t{
-	table_id_t			table_id;	/*!< table id */
-	UT_LIST_NODE_T(row_mysql_drop_t)row_mysql_drop_list;
-							/*!< list chain node */
-};
-
-/** @brief List of tables we should drop in background.
-
-ALTER TABLE in MySQL requires that the table handler can drop the
-table in background when there are no queries to it any
-more.  Protected by row_drop_list_mutex. */
-static UT_LIST_BASE_NODE_T(row_mysql_drop_t)	row_mysql_drop_list;
-
-/** Mutex protecting the background table drop list. */
-static ib_mutex_t row_drop_list_mutex;
-
-/** Flag: has row_mysql_drop_list been initialized? */
-static ibool	row_mysql_drop_list_inited	= FALSE;
-
 /*******************************************************************//**
 Determine if the given name is a name reserved for MySQL system tables.
 @return TRUE if name is a MySQL system table name */
@@ -113,21 +93,6 @@ row_mysql_is_system_table(
 	       || 0 == strcmp(name + 6, "db"));
 }
 
-#ifdef UNIV_DEBUG
-/** Wait for the background drop list to become empty. */
-void
-row_wait_for_background_drop_list_empty()
-{
-	bool	empty = false;
-	while (!empty) {
-		mutex_enter(&row_drop_list_mutex);
-		empty = (UT_LIST_GET_LEN(row_mysql_drop_list) == 0);
-		mutex_exit(&row_drop_list_mutex);
-		os_thread_sleep(100000);
-	}
-}
-#endif /* UNIV_DEBUG */
-
 /*******************************************************************//**
 Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
 static
@@ -2750,239 +2715,6 @@ row_table_add_foreign_constraints(
 	DBUG_RETURN(err);
 }
 
-/*********************************************************************//**
-Drops a table for MySQL as a background operation. MySQL relies on Unix
-in ALTER TABLE to the fact that the table handler does not remove the
-table before all handles to it has been removed. Furhermore, the MySQL's
-call to drop table must be non-blocking. Therefore we do the drop table
-as a background operation, which is taken care of by the master thread
-in srv0srv.cc.
-@return error code or DB_SUCCESS */
-static
-dberr_t
-row_drop_table_for_mysql_in_background(
-/*===================================*/
-	const char*	name)	/*!< in: table name */
-{
-	dberr_t	error;
-	trx_t*	trx;
-
-	trx = trx_allocate_for_background();
-
-	/* If the original transaction was dropping a table referenced by
-	foreign keys, we must set the following to be able to drop the
-	table: */
-
-	trx->check_foreigns = false;
-
-	/* Try to drop the table in InnoDB */
-
-	error = row_drop_table_for_mysql(name, trx, FALSE, FALSE);
-
-	trx_commit_for_mysql(trx);
-
-	trx_free_for_background(trx);
-
-	return(error);
-}
-
-/*********************************************************************//**
-The master thread in srv0srv.cc calls this regularly to drop tables which
-we must drop in background after queries to them have ended. Such lazy
-dropping of tables is needed in ALTER TABLE on Unix.
-@return how many tables dropped + remaining tables in list */
-ulint
-row_drop_tables_for_mysql_in_background(void)
-/*=========================================*/
-{
-	row_mysql_drop_t*	drop;
-	dict_table_t*		table;
-	ulint			n_tables;
-	ulint			n_tables_dropped = 0;
-loop:
-	mutex_enter(&row_drop_list_mutex);
-
-	ut_a(row_mysql_drop_list_inited);
-next:
-	drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
-
-	n_tables = UT_LIST_GET_LEN(row_mysql_drop_list);
-
-	mutex_exit(&row_drop_list_mutex);
-
-	if (drop == NULL) {
-		/* All tables dropped */
-
-		return(n_tables + n_tables_dropped);
-	}
-
-	/* On fast shutdown, just empty the list without dropping tables. */
-	table = srv_shutdown_state == SRV_SHUTDOWN_NONE || !srv_fast_shutdown
-		? dict_table_open_on_id(drop->table_id, FALSE,
-					DICT_TABLE_OP_OPEN_ONLY_IF_CACHED)
-		: NULL;
-
-	if (!table) {
-		n_tables_dropped++;
-		mutex_enter(&row_drop_list_mutex);
-		UT_LIST_REMOVE(row_mysql_drop_list, drop);
-		MONITOR_DEC(MONITOR_BACKGROUND_DROP_TABLE);
-		ut_free(drop);
-		goto next;
-	}
-
-	ut_a(!table->can_be_evicted);
-
-	if (!table->to_be_dropped) {
-		dict_table_close(table, FALSE, FALSE);
-
-		mutex_enter(&row_drop_list_mutex);
-		UT_LIST_REMOVE(row_mysql_drop_list, drop);
-		UT_LIST_ADD_LAST(row_mysql_drop_list, drop);
-		goto next;
-	}
-
-	dict_table_close(table, FALSE, FALSE);
-
-	if (DB_SUCCESS != row_drop_table_for_mysql_in_background(
-		    table->name.m_name)) {
-		/* If the DROP fails for some table, we return, and let the
-		main thread retry later */
-		return(n_tables + n_tables_dropped);
-	}
-
-	goto loop;
-}
-
-/*********************************************************************//**
-Get the background drop list length. NOTE: the caller must own the
-drop list mutex!
-@return how many tables in list */
-ulint
-row_get_background_drop_list_len_low(void)
-/*======================================*/
-{
-	ulint	len;
-
-	mutex_enter(&row_drop_list_mutex);
-
-	ut_a(row_mysql_drop_list_inited);
-
-	len = UT_LIST_GET_LEN(row_mysql_drop_list);
-
-	mutex_exit(&row_drop_list_mutex);
-
-	return(len);
-}
-
-/** Drop garbage tables during recovery. */
-void
-row_mysql_drop_garbage_tables()
-{
-	mem_heap_t*	heap = mem_heap_create(FN_REFLEN);
-	btr_pcur_t	pcur;
-	mtr_t		mtr;
-	trx_t*		trx = trx_allocate_for_background();
-	trx->op_info = "dropping garbage tables";
-	row_mysql_lock_data_dictionary(trx);
-
-	mtr.start();
-	btr_pcur_open_at_index_side(
-		true, dict_table_get_first_index(dict_sys->sys_tables),
-		BTR_SEARCH_LEAF, &pcur, true, 0, &mtr);
-
-	for (;;) {
-		const rec_t*	rec;
-		const byte*	field;
-		ulint		len;
-		const char*	table_name;
-
-		btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-
-		if (!btr_pcur_is_on_user_rec(&pcur)) {
-			break;
-		}
-
-		rec = btr_pcur_get_rec(&pcur);
-		if (rec_get_deleted_flag(rec, 0)) {
-			continue;
-		}
-
-		field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
-		if (len == UNIV_SQL_NULL || len == 0) {
-			/* Corrupted SYS_TABLES.NAME */
-			continue;
-		}
-
-		table_name = mem_heap_strdupl(
-			heap,
-			reinterpret_cast<const char*>(field), len);
-		if (strstr(table_name, "/" TEMP_FILE_PREFIX "-")) {
-			btr_pcur_store_position(&pcur, &mtr);
-			btr_pcur_commit_specify_mtr(&pcur, &mtr);
-
-			if (dict_load_table(table_name, true,
-					    DICT_ERR_IGNORE_ALL)) {
-				row_drop_table_for_mysql(
-					table_name, trx, FALSE, FALSE);
-				trx_commit_for_mysql(trx);
-			}
-
-			mtr.start();
-			btr_pcur_restore_position(BTR_SEARCH_LEAF,
-						  &pcur, &mtr);
-		}
-
-		mem_heap_empty(heap);
-	}
-
-	btr_pcur_close(&pcur);
-	mtr.commit();
-	row_mysql_unlock_data_dictionary(trx);
-	trx_free_for_background(trx);
-	mem_heap_free(heap);
-}
-
-/*********************************************************************//**
-If a table is not yet in the drop list, adds the table to the list of tables
-which the master thread drops in background. We need this on Unix because in
-ALTER TABLE MySQL may call drop table even if the table has running queries on
-it. Also, if there are running foreign key checks on the table, we drop the
-table lazily.
-@return	whether background DROP TABLE was scheduled for the first time */
-static
-bool
-row_add_table_to_background_drop_list(table_id_t table_id)
-{
-	row_mysql_drop_t*	drop;
-	bool			added = true;
-
-	mutex_enter(&row_drop_list_mutex);
-
-	ut_a(row_mysql_drop_list_inited);
-
-	/* Look if the table already is in the drop list */
-	for (drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
-	     drop != NULL;
-	     drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop)) {
-
-		if (drop->table_id == table_id) {
-			added = false;
-			goto func_exit;
-		}
-	}
-
-	drop = static_cast<row_mysql_drop_t*>(ut_malloc_nokey(sizeof *drop));
-	drop->table_id = table_id;
-
-	UT_LIST_ADD_LAST(row_mysql_drop_list, drop);
-
-	MONITOR_INC(MONITOR_BACKGROUND_DROP_TABLE);
-func_exit:
-	mutex_exit(&row_drop_list_mutex);
-	return added;
-}
-
 /** Reassigns the table identifier of a table.
 @param[in,out]	table	table
 @param[in,out]	trx	transaction
@@ -3601,10 +3333,6 @@ row_drop_table_for_mysql(
 		}
 	}
 
-	/* Turn on this drop bit before we could release the dictionary
-	latch */
-	table->to_be_dropped = true;
-
 	if (nonatomic) {
 		/* This trx did not acquire any locks on dictionary
 		table records yet. Thus it is safe to release and
@@ -3703,63 +3431,14 @@ row_drop_table_for_mysql(
 		}
 	}
 
-
-	DBUG_EXECUTE_IF("row_drop_table_add_to_background", goto defer;);
-
-	/* TODO: could we replace the counter n_foreign_key_checks_running
-	with lock checks on the table? Acquire here an exclusive lock on the
-	table, and rewrite lock0lock.cc and the lock wait in srv0srv.cc so that
-	they can cope with the table having been dropped here? Foreign key
-	checks take an IS or IX lock on the table. */
-
-	if (table->n_foreign_key_checks_running > 0) {
-defer:
-		if (!strstr(table->name.m_name, "/" TEMP_FILE_PREFIX_INNODB)) {
-			heap = mem_heap_create(FN_REFLEN);
-			const char* tmp_name
-				= dict_mem_create_temporary_tablename(
-					heap, table->name.m_name, table->id);
-			ib::info() << "Deferring DROP TABLE " << table->name
-				   << "; renaming to " << tmp_name;
-			err = row_rename_table_for_mysql(
-				table->name.m_name, tmp_name, trx, false);
-		} else {
-			err = DB_SUCCESS;
-		}
-		if (err == DB_SUCCESS) {
-			row_add_table_to_background_drop_list(table->id);
-		}
-		goto funct_exit;
-	}
-
-	/* Remove all locks that are on the table or its records, if there
-	are no references to the table but it has record locks, we release
-	the record locks unconditionally. One use case is:
-
-		CREATE TABLE t2 (PRIMARY KEY (a)) SELECT * FROM t1;
-
-	If after the user transaction has done the SELECT and there is a
-	problem in completing the CREATE TABLE operation, MySQL will drop
-	the table. InnoDB will create a new background transaction to do the
-	actual drop, the trx instance that is passed to this function. To
-	preserve existing behaviour we remove the locks but ideally we
-	shouldn't have to. There should never be record locks on a table
-	that is going to be dropped. */
+	ut_ad(!table->n_foreign_key_checks_running);
 
 	/* Wait on background threads to stop using table */
 	fil_wait_crypt_bg_threads(table);
 
-	if (table->get_ref_count() > 0 || table->n_rec_locks > 0
-	    || lock_table_has_locks(table)) {
-		goto defer;
-	}
-
-	/* The "to_be_dropped" marks table that is to be dropped, but
-	has not been dropped, instead, was put in the background drop
-	list due to being used by concurrent DML operations. Clear it
-	here since there are no longer any concurrent activities on it,
-	and it is free to be dropped */
-	table->to_be_dropped = false;
+	ut_a(table->get_ref_count() == 0);
+	ut_a(table->n_rec_locks == 0);
+	ut_a(!lock_table_has_locks(table));
 
 	switch (trx_get_dict_operation(trx)) {
 	case TRX_DICT_OP_NONE:
@@ -5092,32 +4771,3 @@ row_scan_index_for_mysql(
 
 	goto loop;
 }
-
-/*********************************************************************//**
-Initialize this module */
-void
-row_mysql_init(void)
-/*================*/
-{
-	mutex_create(LATCH_ID_ROW_DROP_LIST, &row_drop_list_mutex);
-
-	UT_LIST_INIT(
-		row_mysql_drop_list,
-		&row_mysql_drop_t::row_mysql_drop_list);
-
-	row_mysql_drop_list_inited = TRUE;
-}
-
-/*********************************************************************//**
-Close this module */
-void
-row_mysql_close(void)
-/*================*/
-{
-	ut_a(UT_LIST_GET_LEN(row_mysql_drop_list) == 0);
-
-	if (row_mysql_drop_list_inited) {
-		mutex_free(&row_drop_list_mutex);
-		row_mysql_drop_list_inited = FALSE;
-	}
-}
diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc
index f6c388f2dcf..b12535b7403 100644
--- a/storage/innobase/srv/srv0mon.cc
+++ b/storage/innobase/srv/srv0mon.cc
@@ -1191,11 +1191,6 @@ static monitor_info_t	innodb_counter_info[] =
 	 MONITOR_NONE,
 	 MONITOR_DEFAULT_START, MONITOR_MASTER_IDLE_LOOPS},
 
-	{"innodb_background_drop_table_usec", "server",
-	 "Time (in microseconds) spent to process drop table list",
-	 MONITOR_NONE,
-	 MONITOR_DEFAULT_START, MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND},
-
 	{"innodb_ibuf_merge_usec", "server",
 	 "Time (in microseconds) spent to process change buffer merge",
 	 MONITOR_NONE,
@@ -1364,11 +1359,6 @@ static monitor_info_t	innodb_counter_info[] =
 	 MONITOR_NONE,
 	 MONITOR_DEFAULT_START, MONITOR_BACKGROUND_DROP_INDEX},
 
-	{"ddl_background_drop_tables", "ddl",
-	 "Number of tables in background drop table list",
-	 MONITOR_NONE,
-	 MONITOR_DEFAULT_START, MONITOR_BACKGROUND_DROP_TABLE},
-
 	{"ddl_online_create_index", "ddl",
 	 "Number of indexes being created online",
 	 MONITOR_NONE,
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 8ed5c30634b..6277f0a270b 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1146,7 +1146,6 @@ srv_boot(void)
 	/* Reset the system variables in the recovery module. */
 	recv_sys_var_init();
 	trx_pool_init();
-	row_mysql_init();
 
 	/* Initialize this module */
 
@@ -2097,8 +2096,6 @@ srv_shutdown_print_master_pending(
 /*==============================*/
 	ib_time_t*	last_print_time,	/*!< last time the function
 						print the message */
-	ulint		n_tables_to_drop,	/*!< number of tables to
-						be dropped */
 	ulint		n_bytes_merged)		/*!< number of change buffer
 						just merged */
 {
@@ -2111,11 +2108,6 @@ srv_shutdown_print_master_pending(
 	if (time_elapsed > 60) {
 		*last_print_time = current_time;
 
-		if (n_tables_to_drop) {
-			ib::info() << "Waiting for " << n_tables_to_drop
-				<< " table(s) to be dropped";
-		}
-
 		/* Check change buffer merge, we only wait for change buffer
 		merge if it is a slow shutdown */
 		if (!srv_fast_shutdown && n_bytes_merged) {
@@ -2193,7 +2185,6 @@ srv_master_do_active_tasks(void)
 /*============================*/
 {
 	ib_time_t	cur_time = ut_time();
-	uintmax_t	counter_time = ut_time_us(NULL);
 
 	/* First do the tasks that we are suppose to do at each
 	invocation of this function. */
@@ -2202,14 +2193,6 @@ srv_master_do_active_tasks(void)
 
 	MONITOR_INC(MONITOR_MASTER_ACTIVE_LOOPS);
 
-	/* ALTER TABLE in MySQL requires on Unix that the table handler
-	can drop tables lazily after there no longer are SELECT
-	queries to them. */
-	srv_main_thread_op_info = "doing background drop tables";
-	row_drop_tables_for_mysql_in_background();
-	MONITOR_INC_TIME_IN_MICRO_SECS(
-		MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND, counter_time);
-
 	ut_d(srv_master_do_disabled_loop());
 
 	if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
@@ -2223,7 +2206,7 @@ srv_master_do_active_tasks(void)
 
 	/* Do an ibuf merge */
 	srv_main_thread_op_info = "doing insert buffer merge";
-	counter_time = ut_time_us(NULL);
+	uintmax_t	counter_time = ut_time_us(NULL);
 	ibuf_merge_in_background(false);
 	MONITOR_INC_TIME_IN_MICRO_SECS(
 		MONITOR_SRV_IBUF_MERGE_MICROSECOND, counter_time);
@@ -2278,23 +2261,10 @@ void
 srv_master_do_idle_tasks(void)
 /*==========================*/
 {
-	uintmax_t	counter_time;
-
 	++srv_main_idle_loops;
 
 	MONITOR_INC(MONITOR_MASTER_IDLE_LOOPS);
 
-
-	/* ALTER TABLE in MySQL requires on Unix that the table handler
-	can drop tables lazily after there no longer are SELECT
-	queries to them. */
-	counter_time = ut_time_us(NULL);
-	srv_main_thread_op_info = "doing background drop tables";
-	row_drop_tables_for_mysql_in_background();
-	MONITOR_INC_TIME_IN_MICRO_SECS(
-		MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND,
-			 counter_time);
-
 	ut_d(srv_master_do_disabled_loop());
 
 	if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
@@ -2307,7 +2277,7 @@ srv_master_do_idle_tasks(void)
 	log_free_check();
 
 	/* Do an ibuf merge */
-	counter_time = ut_time_us(NULL);
+	uintmax_t counter_time = ut_time_us(NULL);
 	srv_main_thread_op_info = "doing insert buffer merge";
 	ibuf_merge_in_background(true);
 	MONITOR_INC_TIME_IN_MICRO_SECS(
@@ -2349,7 +2319,6 @@ void
 srv_shutdown(bool ibuf_merge)
 {
 	ulint		n_bytes_merged	= 0;
-	ulint		n_tables_to_drop;
 	ib_time_t	now = ut_time();
 
 	do {
@@ -2357,11 +2326,6 @@ srv_shutdown(bool ibuf_merge)
 		ut_ad(srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
 		++srv_main_shutdown_loops;
 
-		/* FIXME: Remove the background DROP TABLE queue; it is not
-		crash-safe and breaks ACID. */
-		srv_main_thread_op_info = "doing background drop tables";
-		n_tables_to_drop = row_drop_tables_for_mysql_in_background();
-
 		if (ibuf_merge) {
 			srv_main_thread_op_info = "checking free log space";
 			log_free_check();
@@ -2375,9 +2339,9 @@ srv_shutdown(bool ibuf_merge)
 		/* Print progress message every 60 seconds during shutdown */
 		if (srv_print_verbose_log) {
 			srv_shutdown_print_master_pending(
-				&now, n_tables_to_drop, n_bytes_merged);
+				&now, n_bytes_merged);
 		}
-	} while (n_bytes_merged || n_tables_to_drop);
+	} while (n_bytes_merged);
 }
 
 /*********************************************************************//**
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 9135f2e19f7..4009dbcc0bf 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -2760,10 +2760,6 @@ srv_shutdown_bg_undo_sources()
 		ut_ad(!srv_read_only_mode);
 		fts_optimize_shutdown();
 		dict_stats_shutdown();
-		while (row_get_background_drop_list_len_low()) {
-			srv_wake_master_thread();
-			os_thread_yield();
-		}
 		srv_undo_sources = false;
 	}
 }
@@ -2884,7 +2880,6 @@ innodb_shutdown()
 	/* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
 	them */
 	os_aio_free();
-	row_mysql_close();
 	srv_free();
 	fil_close();
 
-- 
2.15.1

