1
0
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:
Thirunarayanan Balathandayuthapani
2026-09-29 17:50:55 +05:30
parent 60ea725e7e
commit db8f1b29aa
4 changed files with 52 additions and 1 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,"

View File

@@ -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 */