summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2004-12-27 20:06:40 +0200
committerunknown <heikki@hundin.mysql.fi>2004-12-27 20:06:40 +0200
commit4ba981e5214cfb3d7af1db1faa7d6cc79d2b2295 (patch)
tree7117348f9c8bea37398643e13abbfe696ed626b5 /innobase
parenta7b984d2336135100c09998d653f331d3b9df996 (diff)
downloadmariadb-git-4ba981e5214cfb3d7af1db1faa7d6cc79d2b2295.tar.gz
row0mysql.c:
Fix the previous bug fix: dropping a table with FOREIGN KEY checks running on it caused a cascade of failed drops while the foreign key check was waiting for a lock innobase/row/row0mysql.c: Fix the previous bug fix: dropping a table with FOREIGN KEY checks running on it caused a cascade of failed drops while the foreign key check was waiting for a lock
Diffstat (limited to 'innobase')
-rw-r--r--innobase/row/row0mysql.c100
1 files changed, 66 insertions, 34 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index ad5efc160c8..1ab7bb1deb0 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1771,16 +1771,9 @@ row_drop_table_for_mysql_in_background(
ut_print_name(stderr, name);
fputs(" in background drop list\n", stderr); */
- /* Drop the table in InnoDB */
+ /* Try to drop the table in InnoDB */
error = row_drop_table_for_mysql(name, trx, FALSE);
-
- if (error != DB_SUCCESS) {
- ut_print_timestamp(stderr);
- fputs(" InnoDB: Error: Dropping table ", stderr);
- ut_print_name(stderr, name);
- fputs(" in background drop list failed\n", stderr);
- }
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -1792,7 +1785,7 @@ row_drop_table_for_mysql_in_background(
trx_free_for_background(trx);
- return(DB_SUCCESS);
+ return(error);
}
/*************************************************************************
@@ -1826,6 +1819,7 @@ loop:
mutex_exit(&kernel_mutex);
if (drop == NULL) {
+ /* All tables dropped */
return(n_tables + n_tables_dropped);
}
@@ -1893,21 +1887,21 @@ row_get_background_drop_list_len_low(void)
}
/*************************************************************************
-Adds a 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. */
+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. */
static
-void
+ibool
row_add_table_to_background_drop_list(
/*==================================*/
+ /* out: TRUE if the table was not yet in the
+ drop list, and was added there */
dict_table_t* table) /* in: table */
{
row_mysql_drop_t* drop;
- drop = mem_alloc(sizeof(row_mysql_drop_t));
-
- drop->table_name = mem_strdup(table->name);
-
mutex_enter(&kernel_mutex);
if (!row_mysql_drop_list_inited) {
@@ -1915,6 +1909,25 @@ row_add_table_to_background_drop_list(
UT_LIST_INIT(row_mysql_drop_list);
row_mysql_drop_list_inited = TRUE;
}
+
+ /* Look if the table already is in the drop list */
+ drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
+
+ while (drop != NULL) {
+ if (strcmp(drop->table_name, table->name) == 0) {
+ /* Already in the list */
+
+ mutex_exit(&kernel_mutex);
+
+ return(FALSE);
+ }
+
+ drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
+ }
+
+ drop = mem_alloc(sizeof(row_mysql_drop_t));
+
+ drop->table_name = mem_strdup(table->name);
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
@@ -1923,6 +1936,8 @@ row_add_table_to_background_drop_list(
fputs(" to background drop list\n", stderr); */
mutex_exit(&kernel_mutex);
+
+ return(TRUE);
}
/*************************************************************************
@@ -2157,36 +2172,53 @@ row_drop_table_for_mysql(
}
if (table->n_mysql_handles_opened > 0) {
+ ibool added;
- ut_print_timestamp(stderr);
- fputs(" InnoDB: Warning: MySQL is trying to drop table ",
- stderr);
- ut_print_name(stderr, table->name);
- fputs("\n"
- "InnoDB: though there are still open handles to it.\n"
- "InnoDB: Adding the table to the background drop queue.\n",
- stderr);
+ added = row_add_table_to_background_drop_list(table);
- row_add_table_to_background_drop_list(table);
+ if (added) {
+ ut_print_timestamp(stderr);
+fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr);
+ ut_print_name(stderr, table->name);
+ fputs("\n"
+"InnoDB: though there are still open handles to it.\n"
+"InnoDB: Adding the table to the background drop queue.\n",
+ stderr);
+
+ /* We return DB_SUCCESS to MySQL though the drop will
+ happen lazily later */
- err = DB_SUCCESS;
+ err = DB_SUCCESS;
+ } else {
+ /* The table is already in the background drop list */
+ err = DB_ERROR;
+ }
goto funct_exit;
}
if (table->n_foreign_key_checks_running > 0) {
+ ibool added;
- ut_print_timestamp(stderr);
- fputs(" InnoDB: You are trying to drop table ", stderr);
+ added = row_add_table_to_background_drop_list(table);
+
+ if (added) {
+ ut_print_timestamp(stderr);
+fputs(" InnoDB: You are trying to drop table ", stderr);
ut_print_name(stderr, table->name);
- fputs("\n"
- "InnoDB: though there is a foreign key check running on it.\n"
- "InnoDB: Adding the table to the background drop queue.\n",
+ fputs("\n"
+"InnoDB: though there is a foreign key check running on it.\n"
+"InnoDB: Adding the table to the background drop queue.\n",
stderr);
- row_add_table_to_background_drop_list(table);
+ /* We return DB_SUCCESS to MySQL though the drop will
+ happen lazily later */
- err = DB_SUCCESS;
+ err = DB_SUCCESS;
+ } else {
+ /* The table is already in the background drop list */
+ err = DB_ERROR;
+ }
goto funct_exit;
}