summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mariadb.org>2019-03-07 13:43:53 +0400
committerSergey Vojtovich <svoj@mariadb.org>2019-03-11 22:46:12 +0400
commit149b75476837fb96c28739d5368e977e39fd671b (patch)
treebcd2f7f80870032d0e3fcff82b472f4a7a3537f8 /sql/sql_table.cc
parent0a0eed80164dac0d3bfb7dcc57eb416cfba89386 (diff)
downloadmariadb-git-149b75476837fb96c28739d5368e977e39fd671b.tar.gz
MDEV-17595 - ALTER TABLE ADD FOREIGN KEY crash
ALTER TABLE ... ADD FOREIGN KEY may trigger assertion failure when it has LOCK=EXCLUSIVE clause or concurrent FLUSH TABLES is being executed. In both cases being altered table is marked as flushed, which forces subsequent attempt to open parent table to re-open. Which in turn is not allowed while transaction is running. Rather than opening parent table, just take appropriate MDL lock. Also removed table_already_fk_prelocked() check: MDL itself has much better methods to handle duplicate locks. E.g. the former won't acquire MDL_SHARED_NO_WRITE if it already has MDL_SHARED_READ.
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc20
1 files changed, 8 insertions, 12 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 8a4c6e025fb..3b4ba72b1f1 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -9074,6 +9074,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_table->file->get_foreign_key_list(thd, &fk_list);
while ((fk= fk_list_it++))
{
+ MDL_request mdl_request;
+
if (lower_case_table_names)
{
char buf[NAME_LEN];
@@ -9085,20 +9087,14 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
len = my_casedn_str(files_charset_info, buf);
thd->make_lex_string(fk->referenced_table, buf, len);
}
- if (table_already_fk_prelocked(table_list, fk->referenced_db,
- fk->referenced_table, TL_READ_NO_INSERT))
- continue;
- TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
- tl->init_one_table_for_prelocking(fk->referenced_db->str, fk->referenced_db->length,
- fk->referenced_table->str, fk->referenced_table->length,
- NULL, TL_READ_NO_INSERT, false, NULL, 0,
- &thd->lex->query_tables_last);
+ mdl_request.init(MDL_key::TABLE,
+ fk->referenced_db->str, fk->referenced_table->str,
+ MDL_SHARED_NO_WRITE, MDL_TRANSACTION);
+ if (thd->mdl_context.acquire_lock(&mdl_request,
+ thd->variables.lock_wait_timeout))
+ goto err_new_table_cleanup;
}
-
- if (open_tables(thd, &table_list->next_global, &tables_opened, 0,
- &alter_prelocking_strategy))
- goto err_new_table_cleanup;
}
}
/*