row0mysql.c:

  Manually merge the latest FOREIGN KEY lock wait + DROP TABLE fix from 4.0
parent a4d046d5
...@@ -1843,16 +1843,9 @@ row_drop_table_for_mysql_in_background( ...@@ -1843,16 +1843,9 @@ row_drop_table_for_mysql_in_background(
ut_print_name(stderr, name); ut_print_name(stderr, name);
fputs(" in background drop list\n", stderr); */ 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); 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, trx, name);
fputs(" in background drop list failed\n", stderr);
}
/* Flush the log to reduce probability that the .frm files and /* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs the InnoDB data dictionary get out-of-sync if the user runs
...@@ -1864,7 +1857,7 @@ row_drop_table_for_mysql_in_background( ...@@ -1864,7 +1857,7 @@ row_drop_table_for_mysql_in_background(
trx_free_for_background(trx); trx_free_for_background(trx);
return(DB_SUCCESS); return(error);
} }
/************************************************************************* /*************************************************************************
...@@ -1898,6 +1891,7 @@ loop: ...@@ -1898,6 +1891,7 @@ loop:
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
if (drop == NULL) { if (drop == NULL) {
/* All tables dropped */
return(n_tables + n_tables_dropped); return(n_tables + n_tables_dropped);
} }
...@@ -1965,21 +1959,21 @@ row_get_background_drop_list_len_low(void) ...@@ -1965,21 +1959,21 @@ row_get_background_drop_list_len_low(void)
} }
/************************************************************************* /*************************************************************************
Adds a table to the list of tables which the master thread drops in If a table is not yet in the drop list, adds the table to the list of tables
background. We need this on Unix because in ALTER TABLE MySQL may call which the master thread drops in background. We need this on Unix because in
drop table even if the table has running queries on it. */ 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 static
void ibool
row_add_table_to_background_drop_list( 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 */ dict_table_t* table) /* in: table */
{ {
row_mysql_drop_t* drop; row_mysql_drop_t* drop;
drop = mem_alloc(sizeof(row_mysql_drop_t));
drop->table_name = mem_strdup(table->name);
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
if (!row_mysql_drop_list_inited) { if (!row_mysql_drop_list_inited) {
...@@ -1987,7 +1981,26 @@ row_add_table_to_background_drop_list( ...@@ -1987,7 +1981,26 @@ row_add_table_to_background_drop_list(
UT_LIST_INIT(row_mysql_drop_list); UT_LIST_INIT(row_mysql_drop_list);
row_mysql_drop_list_inited = TRUE; 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); UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
/* fputs("InnoDB: Adding table ", stderr); /* fputs("InnoDB: Adding table ", stderr);
...@@ -1995,6 +2008,8 @@ row_add_table_to_background_drop_list( ...@@ -1995,6 +2008,8 @@ row_add_table_to_background_drop_list(
fputs(" to background drop list\n", stderr); */ fputs(" to background drop list\n", stderr); */
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
return(TRUE);
} }
/************************************************************************* /*************************************************************************
...@@ -2347,7 +2362,7 @@ funct_exit: ...@@ -2347,7 +2362,7 @@ funct_exit:
} }
/************************************************************************* /*************************************************************************
Drops a table for MySQL. If the name of the table to be dropped is equal Drops a table for MySQL. If the name of the table to be dropped is equal
with one of the predefined magic table names, then this also stops printing with one of the predefined magic table names, then this also stops printing
the corresponding monitor output by the master thread. */ the corresponding monitor output by the master thread. */
...@@ -2581,19 +2596,27 @@ row_drop_table_for_mysql( ...@@ -2581,19 +2596,27 @@ row_drop_table_for_mysql(
} }
if (table->n_mysql_handles_opened > 0) { if (table->n_mysql_handles_opened > 0) {
ibool added;
ut_print_timestamp(stderr); added = row_add_table_to_background_drop_list(table);
fputs(" InnoDB: Warning: MySQL is trying to drop table ",
stderr);
ut_print_name(stderr, trx, 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);
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, trx, 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; goto funct_exit;
} }
...@@ -2606,17 +2629,27 @@ row_drop_table_for_mysql( ...@@ -2606,17 +2629,27 @@ row_drop_table_for_mysql(
if (table->n_foreign_key_checks_running > 0) { if (table->n_foreign_key_checks_running > 0) {
ut_print_timestamp(stderr); ibool added;
fputs(" InnoDB: You are trying to drop table ", stderr);
ut_print_name(stderr, trx, table->name); added = row_add_table_to_background_drop_list(table);
fputs("\n"
"InnoDB: though there is a foreign key check running on it.\n" if (added) {
"InnoDB: Adding the table to the background drop queue.\n", ut_print_timestamp(stderr);
fputs(" InnoDB: You are trying to drop table ", stderr);
ut_print_name(stderr, trx, 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",
stderr); 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; goto funct_exit;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment