1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-21983: Crash on DROP/RENAME TABLE after DISCARD TABLESPACE

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.
This commit is contained in:
Marko Mäkelä
2020-03-19 14:23:47 +02:00
parent 9fd692aeca
commit 6960e9ed24
8 changed files with 27 additions and 42 deletions

View File

@ -35,7 +35,9 @@ ALTER TABLE t DISCARD TABLESPACE;
Warnings: Warnings:
Warning 1812 Tablespace is missing for table 'test/t' Warning 1812 Tablespace is missing for table 'test/t'
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`; SELECT * FROM `x..d`;
ERROR HY000: Got error 194 "Tablespace is missing for a table" from storage engine InnoDB ERROR HY000: Got error 194 "Tablespace is missing for a table" from storage engine InnoDB
DROP TABLE `x..d`; DROP TABLE `x..d`;

View File

@ -58,7 +58,9 @@ ALTER TABLE t ALGORITHM=COPY, DISCARD TABLESPACE;
--error ER_PARSE_ERROR --error ER_PARSE_ERROR
ALTER TABLE t ALGORITHM=DEFAULT, DISCARD TABLESPACE; ALTER TABLE t ALGORITHM=DEFAULT, DISCARD TABLESPACE;
ALTER TABLE t 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 --error ER_GET_ERRNO
SELECT * FROM `x..d`; SELECT * FROM `x..d`;
DROP TABLE `x..d`; DROP TABLE `x..d`;

View File

@ -1630,7 +1630,8 @@ dict_table_rename_in_cache(
return(DB_OUT_OF_MEMORY); 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. */ /* Delete any temp file hanging around. */
if (os_file_status(filepath, &exists, &ftype) if (os_file_status(filepath, &exists, &ftype)

View File

@ -2861,14 +2861,9 @@ bool fil_table_accessible(const dict_table_t* table)
/** Delete a tablespace and associated .ibd file. /** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier @param[in] id tablespace identifier
@param[in] if_exists whether to ignore missing tablespace
@return DB_SUCCESS or error */ @return DB_SUCCESS or error */
dberr_t dberr_t fil_delete_tablespace(ulint id, bool if_exists)
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 */
)
{ {
char* path = 0; char* path = 0;
fil_space_t* space = 0; fil_space_t* space = 0;
@ -2879,10 +2874,11 @@ fil_delete_tablespace(
id, FIL_OPERATION_DELETE, &space, &path); id, FIL_OPERATION_DELETE, &space, &path);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
if (!if_exists) {
ib::error() << "Cannot delete tablespace " << id ib::error() << "Cannot delete tablespace " << id
<< " because it is not found in the tablespace" << " because it is not found"
" memory cache."; " in the tablespace memory cache.";
}
return(err); return(err);
} }

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
@ -964,14 +964,9 @@ bool fil_table_accessible(const dict_table_t* table)
/** Delete a tablespace and associated .ibd file. /** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier @param[in] id tablespace identifier
@param[in] if_exists whether to ignore missing tablespace
@return DB_SUCCESS or error */ @return DB_SUCCESS or error */
dberr_t dberr_t fil_delete_tablespace(ulint id, bool if_exists= false);
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 */
);
/** Prepare to truncate an undo tablespace. /** Prepare to truncate an undo tablespace.
@param[in] space_id undo tablespace id @param[in] space_id undo tablespace id

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
@ -202,18 +202,6 @@ row_merge_file_destroy_low(
/*=======================*/ /*=======================*/
int fd); /*!< in: merge file descriptor */ 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 Rename the tables in the data dictionary. The data dictionary must
have been locked exclusively by the caller, because the transaction have been locked exclusively by the caller, because the transaction

View File

@ -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 a file-per-table tablespace. The caller is responsible for freeing the
memory allocated for the return value. memory allocated for the return value.
@return new pathname of tablespace file, or NULL if space = 0 */ @return new pathname of tablespace file, or NULL if space = 0 */
static
char* char*
row_make_new_pathname( row_make_new_pathname(
/*==================*/ /*==================*/

View File

@ -3725,10 +3725,12 @@ do_drop:
dict_table_t. Free this memory before returning. */ dict_table_t. Free this memory before returning. */
if (DICT_TF_HAS_DATA_DIR(table->flags)) { if (DICT_TF_HAS_DATA_DIR(table->flags)) {
dict_get_and_save_data_dir_path(table, true); 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( filepath = fil_make_filepath(
table->data_dir_path, table->data_dir_path,
table->name.m_name, IBD, true); table->name.m_name, IBD,
table->data_dir_path != NULL);
} else { } else {
filepath = fil_make_filepath( filepath = fil_make_filepath(
NULL, table->name.m_name, IBD, false); NULL, table->name.m_name, IBD, false);
@ -4304,11 +4306,9 @@ row_rename_table_for_mysql(
/* SYS_TABLESPACES and SYS_DATAFILES need to be updated if /* SYS_TABLESPACES and SYS_DATAFILES need to be updated if
the table is in a single-table tablespace. */ the table is in a single-table tablespace. */
if (err == DB_SUCCESS if (err != DB_SUCCESS || !dict_table_is_file_per_table(table)) {
&& dict_table_is_file_per_table(table)) { } else if (char* old_path = fil_space_get_first_path(table->space)) {
/* Make a new pathname to update SYS_DATAFILES. */ char* new_path = os_file_make_new_pathname(old_path, new_name);
char* new_path = row_make_new_pathname(table, new_name);
char* old_path = fil_space_get_first_path(table->space);
/* If old path and new path are the same means tablename /* If old path and new path are the same means tablename
has not changed and only the database name holding the table has not changed and only the database name holding the table