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:
@ -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`;
|
||||||
|
@ -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`;
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
/*==================*/
|
/*==================*/
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user