mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-40274 Server aborts while reloading the table after failed DISCARD TABLESPACE
Problem: ======== row_discard_tablespace() updates SYS_TABLES, SYS_INDEXES and reassigns the table identifier in SYSTEM TABLES. These changes cannot be rolled back, and row_discard_tablespace_for_mysql() commits the transaction even when row_discard_tablespace() returned an error. If the reassignment in row_mysql_table_id_reassign() fails in the middle then the committed data dictionary is inconsistent and the table can no longer be loaded from it, while the in-memory table definition stays in the dictionary cache and remains usable. Solution: ========= row_discard_tablespace_for_mysql(): If row_discard_tablespace() failed, flag the table as corrupted and report the data dictionary inconsistency in the error log. dict_table_open_on_name(): Check dict_table_t::space before reading fil_space_t::get_compression_algo() from it.
This commit is contained in:
@@ -388,3 +388,20 @@ CHECK TABLE t1 EXTENDED;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-40274 Server aborts while reloading the table after
|
||||
# DISCARD TABLESPACE
|
||||
#
|
||||
call mtr.add_suppression("InnoDB: DISCARD TABLESPACE of table `test`\\.`t1` failed");
|
||||
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
|
||||
call mtr.add_suppression("Table `test`\\.`t1` is corrupted");
|
||||
CREATE TABLE t1(c1 INT) ENGINE=InnoDB;
|
||||
SET STATEMENT debug_dbug='+d,row_ins_sec_index_entry_timeout' FOR
|
||||
ALTER TABLE t1 DISCARD TABLESPACE;
|
||||
ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB
|
||||
ALTER TABLE t1 ADD COLUMN cg16 INT AS(c1) VIRTUAL;
|
||||
ERROR 42000: Can't open table
|
||||
FLUSH TABLES;
|
||||
SELECT * FROM t1;
|
||||
ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate.
|
||||
DROP TABLE t1;
|
||||
|
||||
@@ -363,3 +363,23 @@ SET GLOBAL innodb_max_purge_lag_wait=0;
|
||||
|
||||
CHECK TABLE t1 EXTENDED;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40274 Server aborts while reloading the table after
|
||||
--echo # DISCARD TABLESPACE
|
||||
--echo #
|
||||
|
||||
call mtr.add_suppression("InnoDB: DISCARD TABLESPACE of table `test`\\.`t1` failed");
|
||||
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted");
|
||||
call mtr.add_suppression("Table `test`\\.`t1` is corrupted");
|
||||
|
||||
CREATE TABLE t1(c1 INT) ENGINE=InnoDB;
|
||||
--error ER_GET_ERRNO
|
||||
SET STATEMENT debug_dbug='+d,row_ins_sec_index_entry_timeout' FOR
|
||||
ALTER TABLE t1 DISCARD TABLESPACE;
|
||||
--error ER_CHECK_NO_SUCH_TABLE
|
||||
ALTER TABLE t1 ADD COLUMN cg16 INT AS(c1) VIRTUAL;
|
||||
FLUSH TABLES;
|
||||
--error ER_TABLE_CORRUPT
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
@@ -1038,7 +1038,8 @@ dict_table_open_on_name(
|
||||
if (!(ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY) &&
|
||||
!table->is_readable() && table->corrupted)
|
||||
{
|
||||
ulint algo= table->space->get_compression_algo();
|
||||
const ulint algo= table->space
|
||||
? table->space->get_compression_algo() : ULINT_UNDEFINED;
|
||||
if (algo <= PAGE_ALGORITHM_LAST && !fil_comp_algo_loaded(algo))
|
||||
my_printf_error(ER_PROVIDER_NOT_LOADED,
|
||||
"Table %`.*s.%`s is compressed with %s,"
|
||||
|
||||
@@ -2460,6 +2460,19 @@ rollback:
|
||||
table->space= nullptr;
|
||||
table->flags2|= DICT_TF2_DISCARDED;
|
||||
err= row_discard_tablespace(trx, table);
|
||||
if (UNIV_UNLIKELY(err != DB_SUCCESS))
|
||||
{
|
||||
/* In case of error, table cannot be loaded from the data
|
||||
dictionary any longer. Flag the table as corrupted, so that no
|
||||
operation other than DROP TABLE will be attempted on it. */
|
||||
table->corrupted= true;
|
||||
ib::error() << "DISCARD TABLESPACE of table " << table->name
|
||||
<< " failed: " << ut_strerr(err)
|
||||
<< "; the data dictionary is now inconsistent. Please"
|
||||
" DROP TABLE " << table->name
|
||||
<< " and restore it from a backup.";
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("ib_discard_before_commit_crash",
|
||||
log_buffer_flush_to_disk(); DBUG_SUICIDE(););
|
||||
/* FTS_ tables may be deleted */
|
||||
|
||||
Reference in New Issue
Block a user