Commit a7b984d2 authored by unknown's avatar unknown

row0ins.c:

  Fix bug: if we dropped a table where an INSERT was waiting for a lock to check a FOREIGN KEY constraint, then an assertion would fail in lock_reset_all_on_table(), since that operation assumes no waiting locks on the table or its records
row0mysql.c:
  Fix bug: InnoDB failed to drop a table in the background drop queue if the table was referenced by a foreign key constraint


innobase/row/row0mysql.c:
  Fix bug: InnoDB failed to drop a table in the background drop queue if the table was referenced by a foreign key constraint
innobase/row/row0ins.c:
  Fix bug: if we dropped a table where an INSERT was waiting for a lock to check a FOREIGN KEY constraint, then an assertion would fail in lock_reset_all_on_table(), since that operation assumes no waiting locks on the table or its records
parent 50bd606d
...@@ -1373,8 +1373,34 @@ row_ins_check_foreign_constraints( ...@@ -1373,8 +1373,34 @@ row_ins_check_foreign_constraints(
row_mysql_freeze_data_dictionary(trx); row_mysql_freeze_data_dictionary(trx);
} }
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
(foreign->referenced_table
->n_foreign_key_checks_running)++;
mutex_exit(&(dict_sys->mutex));
}
/* NOTE that if the thread ends up waiting for a lock
we will release dict_operation_lock temporarily!
But the counter on the table protects the referenced
table from being dropped while the check is running. */
err = row_ins_check_foreign_constraint(TRUE, foreign, err = row_ins_check_foreign_constraint(TRUE, foreign,
table, entry, thr); table, entry, thr);
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
ut_a(foreign->referenced_table
->n_foreign_key_checks_running > 0);
(foreign->referenced_table
->n_foreign_key_checks_running)--;
mutex_exit(&(dict_sys->mutex));
}
if (got_s_lock) { if (got_s_lock) {
row_mysql_unfreeze_data_dictionary(trx); row_mysql_unfreeze_data_dictionary(trx);
} }
......
...@@ -1761,6 +1761,12 @@ row_drop_table_for_mysql_in_background( ...@@ -1761,6 +1761,12 @@ row_drop_table_for_mysql_in_background(
trx = trx_allocate_for_background(); 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;
/* fputs("InnoDB: Error: Dropping table ", stderr); /* fputs("InnoDB: Error: Dropping table ", stderr);
ut_print_name(stderr, name); ut_print_name(stderr, name);
fputs(" in background drop list\n", stderr); */ fputs(" in background drop list\n", stderr); */
...@@ -1834,16 +1840,16 @@ loop: ...@@ -1834,16 +1840,16 @@ loop:
goto already_dropped; goto already_dropped;
} }
if (table->n_mysql_handles_opened > 0 if (DB_SUCCESS != row_drop_table_for_mysql_in_background(
|| table->n_foreign_key_checks_running > 0) { drop->table_name)) {
/* If the DROP fails for some table, we return, and let the
main thread retry later */
return(n_tables + n_tables_dropped); return(n_tables + n_tables_dropped);
} }
n_tables_dropped++; n_tables_dropped++;
row_drop_table_for_mysql_in_background(drop->table_name);
already_dropped: already_dropped:
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
......
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