Skip to content

Commit

Permalink
MDEV-21983: Crash on DROP/RENAME TABLE after DISCARD TABLESPACE
Browse files Browse the repository at this point in the history
fil_delete_tablespace(): Remove the unused parameter drop_ahi,
and add the parameter if_exists=false. We want to suppress
error messages if we know that the tablespace has been discarded.

dict_table_rename_in_cache(): Pass the new parameter to
fil_delete_tablespace(), that is, do not complain about
missing tablespace if the tablespace has been discarded.

row_make_new_pathname(): Declare as static.

row_drop_table_for_mysql(): Tolerate !table->data_dir_path
when the tablespace has been discarded.

row_rename_table_for_mysql(): Skip part of the RENAME TABLE
when fil_space_get_first_path() returns NULL.
  • Loading branch information
dr-m committed Mar 19, 2020
1 parent 9fd692a commit 6960e9e
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 42 deletions.
4 changes: 3 additions & 1 deletion mysql-test/suite/innodb/r/alter_missing_tablespace.result
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ ALTER TABLE t DISCARD TABLESPACE;
Warnings:
Warning 1812 Tablespace is missing for table 'test/t'
Warning 1812 Tablespace is missing for table 'test/t'
DROP TABLE t;
RENAME TABLE t TO u;
RENAME TABLE u TO v;
DROP TABLE v;
SELECT * FROM `x..d`;
ERROR HY000: Got error 194 "Tablespace is missing for a table" from storage engine InnoDB
DROP TABLE `x..d`;
Expand Down
4 changes: 3 additions & 1 deletion mysql-test/suite/innodb/t/alter_missing_tablespace.test
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ ALTER TABLE t ALGORITHM=COPY, DISCARD TABLESPACE;
--error ER_PARSE_ERROR
ALTER TABLE t ALGORITHM=DEFAULT, DISCARD TABLESPACE;
ALTER TABLE t DISCARD TABLESPACE;
DROP TABLE t;
RENAME TABLE t TO u;
RENAME TABLE u TO v;
DROP TABLE v;
--error ER_GET_ERRNO
SELECT * FROM `x..d`;
DROP TABLE `x..d`;
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/dict/dict0dict.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1630,7 +1630,8 @@ dict_table_rename_in_cache(
return(DB_OUT_OF_MEMORY);
}

fil_delete_tablespace(table->space);
fil_delete_tablespace(table->space,
dict_table_is_discarded(table));

/* Delete any temp file hanging around. */
if (os_file_status(filepath, &exists, &ftype)
Expand Down
18 changes: 7 additions & 11 deletions storage/innobase/fil/fil0fil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2861,14 +2861,9 @@ bool fil_table_accessible(const dict_table_t* table)

/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] if_exists whether to ignore missing tablespace
@return DB_SUCCESS or error */
dberr_t
fil_delete_tablespace(
ulint id
#ifdef BTR_CUR_HASH_ADAPT
, bool drop_ahi /*!< whether to drop the adaptive hash index */
#endif /* BTR_CUR_HASH_ADAPT */
)
dberr_t fil_delete_tablespace(ulint id, bool if_exists)
{
char* path = 0;
fil_space_t* space = 0;
Expand All @@ -2879,10 +2874,11 @@ fil_delete_tablespace(
id, FIL_OPERATION_DELETE, &space, &path);

if (err != DB_SUCCESS) {

ib::error() << "Cannot delete tablespace " << id
<< " because it is not found in the tablespace"
" memory cache.";
if (!if_exists) {
ib::error() << "Cannot delete tablespace " << id
<< " because it is not found"
" in the tablespace memory cache.";
}

return(err);
}
Expand Down
11 changes: 3 additions & 8 deletions storage/innobase/include/fil0fil.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2019, MariaDB Corporation.
Copyright (c) 2013, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Expand Down Expand Up @@ -964,14 +964,9 @@ bool fil_table_accessible(const dict_table_t* table)

/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] if_exists whether to ignore missing tablespace
@return DB_SUCCESS or error */
dberr_t
fil_delete_tablespace(
ulint id
#ifdef BTR_CUR_HASH_ADAPT
, bool drop_ahi = false /*!< whether to drop the adaptive hash index */
#endif /* BTR_CUR_HASH_ADAPT */
);
dberr_t fil_delete_tablespace(ulint id, bool if_exists= false);

/** Prepare to truncate an undo tablespace.
@param[in] space_id undo tablespace id
Expand Down
14 changes: 1 addition & 13 deletions storage/innobase/include/row0merge.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2019, MariaDB Corporation.
Copyright (c) 2015, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Expand Down Expand Up @@ -202,18 +202,6 @@ row_merge_file_destroy_low(
/*=======================*/
int fd); /*!< in: merge file descriptor */

/*********************************************************************//**
Provide a new pathname for a table that is being renamed if it belongs to
a file-per-table tablespace. The caller is responsible for freeing the
memory allocated for the return value.
@return new pathname of tablespace file, or NULL if space = 0 */
char*
row_make_new_pathname(
/*==================*/
dict_table_t* table, /*!< in: table to be renamed */
const char* new_name) /*!< in: new name */
MY_ATTRIBUTE((nonnull, warn_unused_result));

/*********************************************************************//**
Rename the tables in the data dictionary. The data dictionary must
have been locked exclusively by the caller, because the transaction
Expand Down
1 change: 1 addition & 0 deletions storage/innobase/row/row0merge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4149,6 +4149,7 @@ Provide a new pathname for a table that is being renamed if it belongs to
a file-per-table tablespace. The caller is responsible for freeing the
memory allocated for the return value.
@return new pathname of tablespace file, or NULL if space = 0 */
static
char*
row_make_new_pathname(
/*==================*/
Expand Down
14 changes: 7 additions & 7 deletions storage/innobase/row/row0mysql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3725,10 +3725,12 @@ row_drop_table_for_mysql(
dict_table_t. Free this memory before returning. */
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
dict_get_and_save_data_dir_path(table, true);
ut_a(table->data_dir_path);
ut_ad(table->data_dir_path
|| dict_table_is_discarded(table));
filepath = fil_make_filepath(
table->data_dir_path,
table->name.m_name, IBD, true);
table->name.m_name, IBD,
table->data_dir_path != NULL);
} else {
filepath = fil_make_filepath(
NULL, table->name.m_name, IBD, false);
Expand Down Expand Up @@ -4304,11 +4306,9 @@ row_rename_table_for_mysql(

/* SYS_TABLESPACES and SYS_DATAFILES need to be updated if
the table is in a single-table tablespace. */
if (err == DB_SUCCESS
&& dict_table_is_file_per_table(table)) {
/* Make a new pathname to update SYS_DATAFILES. */
char* new_path = row_make_new_pathname(table, new_name);
char* old_path = fil_space_get_first_path(table->space);
if (err != DB_SUCCESS || !dict_table_is_file_per_table(table)) {
} else if (char* old_path = fil_space_get_first_path(table->space)) {
char* new_path = os_file_make_new_pathname(old_path, new_name);

/* If old path and new path are the same means tablename
has not changed and only the database name holding the table
Expand Down

0 comments on commit 6960e9e

Please sign in to comment.