diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2016-06-22 22:37:28 +0300 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2016-06-23 06:46:05 +0300 |
commit | ef92aaf9ece92c873ae0f3448ab2274c958ba3fe (patch) | |
tree | 0a66b9df3d0d723610d97978066684716e30578f /storage/xtradb | |
parent | a482e76e65a4fee70479e877929381c86b1ec62f (diff) | |
download | mariadb-git-ef92aaf9ece92c873ae0f3448ab2274c958ba3fe.tar.gz |
MDEV-10083: Orphan ibd file when playing with foreign keys
Analysis: row_drop_table_for_mysql did not allow dropping
referenced table even in case when actual creating of the
referenced table was not successfull if foreign_key_checks=1.
Fix: Allow dropping referenced table even if foreign_key_checks=1
if actual table create returned error.
Diffstat (limited to 'storage/xtradb')
-rw-r--r-- | storage/xtradb/dict/dict0crea.c | 8 | ||||
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 4 | ||||
-rw-r--r-- | storage/xtradb/include/row0mysql.h | 5 | ||||
-rw-r--r-- | storage/xtradb/row/row0merge.c | 2 | ||||
-rw-r--r-- | storage/xtradb/row/row0mysql.c | 23 | ||||
-rw-r--r-- | storage/xtradb/trx/trx0roll.c | 2 |
6 files changed, 28 insertions, 16 deletions
diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c index a77acf8b577..b44fdc1d2e4 100644 --- a/storage/xtradb/dict/dict0crea.c +++ b/storage/xtradb/dict/dict0crea.c @@ -1444,14 +1444,14 @@ dict_create_or_check_foreign_constraint_tables(void) fprintf(stderr, "InnoDB: dropping incompletely created" " SYS_FOREIGN table\n"); - row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE); } if (table2) { fprintf(stderr, "InnoDB: dropping incompletely created" " SYS_FOREIGN_COLS table\n"); - row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE); } fprintf(stderr, @@ -1500,8 +1500,8 @@ dict_create_or_check_foreign_constraint_tables(void) "InnoDB: dropping incompletely created" " SYS_FOREIGN tables\n"); - row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); - row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE); error = DB_MUST_GET_MORE_FILE_SPACE; } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 8148c3e1dd5..d5da3825ef0 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -8773,7 +8773,8 @@ ha_innobase::delete_table( error = row_drop_table_for_mysql(norm_name, trx, thd_sql_command(thd) - == SQLCOM_DROP_DB); + == SQLCOM_DROP_DB, + FALSE); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -8858,6 +8859,7 @@ innobase_drop_database( trx_free_for_mysql(trx); return; /* ignore */ } + row_drop_database_for_mysql(namebuf, trx); my_free(namebuf); diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index 35378bf3302..e228289bdae 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -470,7 +470,10 @@ row_drop_table_for_mysql( /*=====================*/ const char* name, /*!< in: table name */ trx_t* trx, /*!< in: transaction handle */ - ibool drop_db);/*!< in: TRUE=dropping whole database */ + ibool drop_db,/*!< in: TRUE=dropping whole database */ + ibool create_failed);/*!<in: TRUE=create table failed + because e.g. foreign key column + type mismatch. */ /*********************************************************************//** Drop all temporary tables during crash recovery. */ UNIV_INTERN diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c index 752e941af7f..3a03c7c8578 100644 --- a/storage/xtradb/row/row0merge.c +++ b/storage/xtradb/row/row0merge.c @@ -2747,7 +2747,7 @@ row_merge_drop_table( /* There must be no open transactions on the table. */ ut_a(table->n_mysql_handles_opened == 0); - return(row_drop_table_for_mysql(table->name, trx, FALSE)); + return(row_drop_table_for_mysql(table->name, trx, FALSE, FALSE)); } /*********************************************************************//** diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c index e6ccf44b884..0182752132a 100644 --- a/storage/xtradb/row/row0mysql.c +++ b/storage/xtradb/row/row0mysql.c @@ -2013,7 +2013,7 @@ err_exit: if (dict_table_get_low(table->name, DICT_ERR_IGNORE_NONE)) { - row_drop_table_for_mysql(table->name, trx, FALSE); + row_drop_table_for_mysql(table->name, trx, FALSE, TRUE); trx_commit_for_mysql(trx); } else { dict_mem_table_free(table); @@ -2143,7 +2143,7 @@ error_handling: trx_general_rollback_for_mysql(trx, NULL); - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, TRUE); trx_commit_for_mysql(trx); @@ -2278,7 +2278,7 @@ row_table_add_foreign_constraints( trx_general_rollback_for_mysql(trx, NULL); - row_drop_table_for_mysql(name, trx, FALSE); + row_drop_table_for_mysql(name, trx, FALSE, TRUE); trx_commit_for_mysql(trx); @@ -2319,7 +2319,7 @@ row_drop_table_for_mysql_in_background( /* 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, FALSE); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -3216,7 +3216,10 @@ row_drop_table_for_mysql( /*=====================*/ const char* name, /*!< in: table name */ trx_t* trx, /*!< in: transaction handle */ - ibool drop_db)/*!< in: TRUE=dropping whole database */ + ibool drop_db,/*!< in: TRUE=dropping whole database */ + ibool create_failed) /*!<in: TRUE=create table failed + because e.g. foreign key column + type mismatch. */ { dict_foreign_t* foreign; dict_table_t* table; @@ -3331,7 +3334,11 @@ check_next_foreign: foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } - if (foreign && trx->check_foreigns + /* We should allow dropping a referenced table if creating + that referenced table has failed for some reason. For example + if referenced table is created but it column types that are + referenced do not match. */ + if (foreign && trx->check_foreigns && !create_failed && !(drop_db && dict_tables_have_same_db( name, foreign->foreign_table_name_lookup))) { FILE* ef = dict_foreign_err_file; @@ -3718,7 +3725,7 @@ row_mysql_drop_temp_tables(void) table = dict_table_get_low(table_name, DICT_ERR_IGNORE_ALL); if (table) { - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, FALSE); trx_commit_for_mysql(trx); } @@ -3848,7 +3855,7 @@ loop: goto loop; } - err = row_drop_table_for_mysql(table_name, trx, TRUE); + err = row_drop_table_for_mysql(table_name, trx, TRUE, FALSE); trx_commit_for_mysql(trx); if (err != DB_SUCCESS) { diff --git a/storage/xtradb/trx/trx0roll.c b/storage/xtradb/trx/trx0roll.c index 25c1d5d4692..236eb88e7a4 100644 --- a/storage/xtradb/trx/trx0roll.c +++ b/storage/xtradb/trx/trx0roll.c @@ -504,7 +504,7 @@ trx_rollback_active( ut_print_name(stderr, trx, TRUE, table->name); fputs(" in recovery\n", stderr); - err = row_drop_table_for_mysql(table->name, trx, TRUE); + err = row_drop_table_for_mysql(table->name, trx, TRUE, FALSE); trx_commit_for_mysql(trx); ut_a(err == (int) DB_SUCCESS); |