From 523a3b44e52d022d733f4b6a4d789c280f5c5425 Mon Sep 17 00:00:00 2001 From: "songhuaxiong.shx" Date: Thu, 28 May 2026 18:50:30 +0800 Subject: [PATCH] InnoDB: tablespace marked missing after rollback of copy-style ALTER when schema/table/partition name contains '-' or non-ASCII When a copy-style ALTER (ALGORITHM=COPY) fails into err_with_mdl after both mysql_rename_table() calls have run, the rollback path in Log_DDL::post_ddl -> fil_op_replay_rename enters its "rollback target file does NOT exist" branch, which string-slices the .ibd path with no charset decoding and leaves space->name in filesystem charset (e.g. "schema@002dx/t1"). On the next access, dd_load_tablespace looks up the space under its system-charset name ("schema-x/t1"), fil_space_exists_in_mem misses, and table->ibd_file_missing is set unconditionally even though the .ibd is intact on disk. Surfaces only when a schema/table/partition/sub-partition name contains '-', non-ASCII, or any @NNNN-encoded character; pure ASCII alnum names are byte-identical in both charsets and so hide the bug. Fix consumer-side in dd_load_tablespace: when cache and DD names diverge, reconcile via fil_space_update_name() -- the same primitive boot_tablespaces() uses -- and retry the cache lookup. The producer side (fil_op_replay_rename's string-slice branch) is shared with crash-recovery replay paths and is left untouched. A DBUG hook (force_alter_rollback_after_rename) is added in mysql_alter_table to deterministically reach the err_with_mdl branch from MTR. Tests cover all four name components (schema/table/partition/sub-partition) and both positive (fix engaged) and negative (fix bypassed via dd_load_tablespace_skip_fix -> bug reproduces) halves. --- .../r/alter_rollback_fs_charset_split.result | 154 ++++++++++ .../t/alter_rollback_fs_charset_split.test | 269 ++++++++++++++++++ sql/sql_table.cc | 11 + storage/innobase/dict/dict0dd.cc | 34 ++- 4 files changed, 465 insertions(+), 3 deletions(-) create mode 100644 mysql-test/suite/innodb/r/alter_rollback_fs_charset_split.result create mode 100644 mysql-test/suite/innodb/t/alter_rollback_fs_charset_split.test diff --git a/mysql-test/suite/innodb/r/alter_rollback_fs_charset_split.result b/mysql-test/suite/innodb/r/alter_rollback_fs_charset_split.result new file mode 100644 index 00000000000..616f90b4d7a --- /dev/null +++ b/mysql-test/suite/innodb/r/alter_rollback_fs_charset_split.result @@ -0,0 +1,154 @@ +# === Case 1: schema name with '-' (COPY ALTER) === +CREATE DATABASE `mydb-x`; +USE `mydb-x`; +CREATE TABLE t1 (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'); +FLUSH TABLES t1; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE t1 FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +FLUSH TABLES t1; +SELECT * FROM t1; +id val +1 a +2 b +3 c +include/assert.inc [case 1 positive: checksum stable] +CREATE TABLE t1n (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO t1n VALUES (1, 'a'); +FLUSH TABLES t1n; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE t1n FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES t1n; +SELECT * FROM t1n; +Got one of the listed errors +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; +include/assert_grep.inc [case 1: divergence warning fired for both tables] +DROP TABLE t1, t1n; +DROP DATABASE `mydb-x`; +# === Case 2: table name with '-' (COPY ALTER) === +CREATE DATABASE cleandb; +USE cleandb; +CREATE TABLE `t-name` (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO `t-name` VALUES (10, 'x'), (20, 'y'), (30, 'z'); +FLUSH TABLES `t-name`; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE `t-name` FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +FLUSH TABLES `t-name`; +SELECT * FROM `t-name`; +id val +10 x +20 y +30 z +include/assert.inc [case 2 positive: checksum stable] +CREATE TABLE `t-namen` (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO `t-namen` VALUES (1, 'a'); +FLUSH TABLES `t-namen`; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE `t-namen` FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES `t-namen`; +SELECT * FROM `t-namen`; +Got one of the listed errors +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; +include/assert_grep.inc [case 2: divergence warning fired for both tables] +DROP TABLE `t-name`, `t-namen`; +# === Case 3: partition name with '-' (COPY ALTER) === +CREATE TABLE pt (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) ( +PARTITION `p-low` VALUES LESS THAN (50), +PARTITION `p-high` VALUES LESS THAN (200) +); +INSERT INTO pt VALUES (1, 'a'), (49, 'b'), (100, 'c'); +FLUSH TABLES pt; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE pt FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +FLUSH TABLES pt; +SELECT * FROM pt; +id val +1 a +100 c +49 b +include/assert.inc [case 3 positive: checksum stable] +CREATE TABLE ptn (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) ( +PARTITION `pn-low` VALUES LESS THAN (50), +PARTITION `pn-high` VALUES LESS THAN (200) +); +INSERT INTO ptn VALUES (1, 'a'), (49, 'b'); +FLUSH TABLES ptn; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE ptn FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES ptn; +SELECT * FROM ptn; +Got one of the listed errors +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; +include/assert_grep.inc [case 3: divergence warning fired for all partitions] +DROP TABLE pt, ptn; +# === Case 4: sub-partition name with '-' (COPY ALTER) === +CREATE TABLE st (id INT, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) +SUBPARTITION BY HASH(id) ( +PARTITION p1 VALUES LESS THAN (50) ( +SUBPARTITION `sp-a`, +SUBPARTITION `sp-b` + ), +PARTITION p2 VALUES LESS THAN (200) ( +SUBPARTITION `sp-c`, +SUBPARTITION `sp-d` + ) +); +INSERT INTO st VALUES (1, 'a'), (49, 'b'), (100, 'c'), (150, 'd'); +FLUSH TABLES st; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE st FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +FLUSH TABLES st; +SELECT * FROM st; +id val +1 a +100 c +150 d +49 b +include/assert.inc [case 4 positive: checksum stable] +CREATE TABLE stn (id INT, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) +SUBPARTITION BY HASH(id) ( +PARTITION p1 VALUES LESS THAN (50) ( +SUBPARTITION `sn-a`, +SUBPARTITION `sn-b` + ), +PARTITION p2 VALUES LESS THAN (200) ( +SUBPARTITION `sn-c`, +SUBPARTITION `sn-d` + ) +); +INSERT INTO stn VALUES (1, 'a'), (100, 'c'); +FLUSH TABLES stn; +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +ALTER TABLE stn FORCE, ALGORITHM=COPY; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET SESSION debug = '-d,force_alter_rollback_after_rename'; +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES stn; +SELECT * FROM stn; +Got one of the listed errors +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; +include/assert_grep.inc [case 4: divergence warning fired for all sub-partitions] +DROP TABLE st, stn; +# === Cleanup === +DROP DATABASE cleandb; diff --git a/mysql-test/suite/innodb/t/alter_rollback_fs_charset_split.test b/mysql-test/suite/innodb/t/alter_rollback_fs_charset_split.test new file mode 100644 index 00000000000..4103611febf --- /dev/null +++ b/mysql-test/suite/innodb/t/alter_rollback_fs_charset_split.test @@ -0,0 +1,269 @@ +# Test: alter_rollback_fs_charset_split +# +# InnoDB FIL cache fs-charset vs system-charset split bug after +# atomic-DDL rollback. Reproduced via ALTER ... FORCE, ALGORITHM=COPY: +# the two mysql_rename_table calls (original->backup, new->original) +# leave the FIL cache in a state where Log_DDL::post_ddl -> +# fil_op_replay_rename's "rollback target file does NOT exist" branch +# string-slices the .ibd path with no charset decoding and writes +# space->name in fs charset (e.g. "schema@002dx/t1"). dd_load_tablespace's +# repair reconciles cache vs DD via fil_space_update_name; the +# `dd_load_tablespace_skip_fix` keyword gates the repair off so the +# unfixed pre-fix symptom (ER 1812) can be reproduced. +# +# Single-rename DDL (plain RENAME TABLE / ALTER TABLE ... RENAME TO) +# does NOT trigger the bug: with only one rename in the DDL log, the +# replay hits fil_rename_validate's "already maps" branch instead of +# the string-slice branch, so the FIL cache stays in system charset. +# +# Each case (one per name component: schema, table, partition, +# sub-partition) covers both positive (fix engaged, SELECT works) +# and negative (skip_fix on, SELECT raises ER 1812) halves on paired +# tables to keep the cache state independent. + +--source include/have_debug.inc + +--let $datadir = `SELECT @@datadir` + + +--echo # === Case 1: schema name with '-' (COPY ALTER) === + +CREATE DATABASE `mydb-x`; +USE `mydb-x`; + +# Positive: fix engaged. +CREATE TABLE t1 (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'); +--file_exists $datadir/mydb@002dx/t1.ibd +FLUSH TABLES t1; +--let $checksum1_before = query_get_value(CHECKSUM TABLE t1, Checksum, 1) + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE t1 FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +FLUSH TABLES t1; +--sorted_result +SELECT * FROM t1; + +--let $checksum1_after = query_get_value(CHECKSUM TABLE t1, Checksum, 1) +--let $assert_cond = "$checksum1_before" = "$checksum1_after" +--let $assert_text = case 1 positive: checksum stable +--source include/assert.inc + +# Negative: skip_fix on, ER 1812 must surface. Use a separate table to +# keep cache state independent. +CREATE TABLE t1n (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO t1n VALUES (1, 'a'); +FLUSH TABLES t1n; + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE t1n FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES t1n; +--disable_warnings +--error ER_TABLESPACE_MISSING,ER_NO_SUCH_TABLE +SELECT * FROM t1n; +--enable_warnings +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; + +--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_text = case 1: divergence warning fired for both tables +--let $assert_select = FIL cache name .*mydb@002dx/(t1|t1n).* differs +--let $assert_count = 2 +--source include/assert_grep.inc + +DROP TABLE t1, t1n; +DROP DATABASE `mydb-x`; + + +--echo # === Case 2: table name with '-' (COPY ALTER) === + +CREATE DATABASE cleandb; +USE cleandb; + +CREATE TABLE `t-name` (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO `t-name` VALUES (10, 'x'), (20, 'y'), (30, 'z'); +--file_exists $datadir/cleandb/t@002dname.ibd +FLUSH TABLES `t-name`; +--let $checksum2_before = query_get_value(CHECKSUM TABLE `t-name`, Checksum, 1) + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE `t-name` FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +FLUSH TABLES `t-name`; +--sorted_result +SELECT * FROM `t-name`; + +--let $checksum2_after = query_get_value(CHECKSUM TABLE `t-name`, Checksum, 1) +--let $assert_cond = "$checksum2_before" = "$checksum2_after" +--let $assert_text = case 2 positive: checksum stable +--source include/assert.inc + +CREATE TABLE `t-namen` (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB; +INSERT INTO `t-namen` VALUES (1, 'a'); +FLUSH TABLES `t-namen`; + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE `t-namen` FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES `t-namen`; +--disable_warnings +--error ER_TABLESPACE_MISSING,ER_NO_SUCH_TABLE +SELECT * FROM `t-namen`; +--enable_warnings +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; + +--let $assert_text = case 2: divergence warning fired for both tables +--let $assert_select = FIL cache name .*cleandb/(t@002dname|t@002dnamen).* differs +--let $assert_count = 2 +--source include/assert_grep.inc + +DROP TABLE `t-name`, `t-namen`; + + +--echo # === Case 3: partition name with '-' (COPY ALTER) === + +CREATE TABLE pt (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) ( + PARTITION `p-low` VALUES LESS THAN (50), + PARTITION `p-high` VALUES LESS THAN (200) +); +INSERT INTO pt VALUES (1, 'a'), (49, 'b'), (100, 'c'); +--file_exists $datadir/cleandb/pt#p#p@002dlow.ibd +FLUSH TABLES pt; +--let $checksum3_before = query_get_value(CHECKSUM TABLE pt, Checksum, 1) + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE pt FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +FLUSH TABLES pt; +--sorted_result +SELECT * FROM pt; + +--let $checksum3_after = query_get_value(CHECKSUM TABLE pt, Checksum, 1) +--let $assert_cond = "$checksum3_before" = "$checksum3_after" +--let $assert_text = case 3 positive: checksum stable +--source include/assert.inc + +CREATE TABLE ptn (id INT PRIMARY KEY, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) ( + PARTITION `pn-low` VALUES LESS THAN (50), + PARTITION `pn-high` VALUES LESS THAN (200) +); +INSERT INTO ptn VALUES (1, 'a'), (49, 'b'); +FLUSH TABLES ptn; + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE ptn FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES ptn; +--disable_warnings +--error ER_TABLESPACE_MISSING,ER_NO_SUCH_TABLE +SELECT * FROM ptn; +--enable_warnings +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; + +# pt has 2 partitions (positive), ptn has 2 partitions (negative); 4 warnings total. +--let $assert_text = case 3: divergence warning fired for all partitions +--let $assert_select = FIL cache name .*(pt|ptn)#p#p[n]?@002d(low|high).* differs +--let $assert_count = 4 +--source include/assert_grep.inc + +DROP TABLE pt, ptn; + + +--echo # === Case 4: sub-partition name with '-' (COPY ALTER) === + +CREATE TABLE st (id INT, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) +SUBPARTITION BY HASH(id) ( + PARTITION p1 VALUES LESS THAN (50) ( + SUBPARTITION `sp-a`, + SUBPARTITION `sp-b` + ), + PARTITION p2 VALUES LESS THAN (200) ( + SUBPARTITION `sp-c`, + SUBPARTITION `sp-d` + ) +); +INSERT INTO st VALUES (1, 'a'), (49, 'b'), (100, 'c'), (150, 'd'); +--file_exists $datadir/cleandb/st#p#p1#sp#sp@002da.ibd +FLUSH TABLES st; +--let $checksum4_before = query_get_value(CHECKSUM TABLE st, Checksum, 1) + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE st FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +FLUSH TABLES st; +--sorted_result +SELECT * FROM st; + +--let $checksum4_after = query_get_value(CHECKSUM TABLE st, Checksum, 1) +--let $assert_cond = "$checksum4_before" = "$checksum4_after" +--let $assert_text = case 4 positive: checksum stable +--source include/assert.inc + +CREATE TABLE stn (id INT, val VARCHAR(32)) ENGINE=InnoDB +PARTITION BY RANGE (id) +SUBPARTITION BY HASH(id) ( + PARTITION p1 VALUES LESS THAN (50) ( + SUBPARTITION `sn-a`, + SUBPARTITION `sn-b` + ), + PARTITION p2 VALUES LESS THAN (200) ( + SUBPARTITION `sn-c`, + SUBPARTITION `sn-d` + ) +); +INSERT INTO stn VALUES (1, 'a'), (100, 'c'); +FLUSH TABLES stn; + +SET SESSION debug = '+d,force_alter_rollback_after_rename'; +--error ER_LOCK_DEADLOCK +ALTER TABLE stn FORCE, ALGORITHM=COPY; +SET SESSION debug = '-d,force_alter_rollback_after_rename'; + +SET SESSION debug = '+d,dd_load_tablespace_skip_fix'; +FLUSH TABLES stn; +--disable_warnings +--error ER_TABLESPACE_MISSING,ER_NO_SUCH_TABLE +SELECT * FROM stn; +--enable_warnings +SET SESSION debug = '-d,dd_load_tablespace_skip_fix'; + +# st has 4 sub-partitions (positive), stn has 4 (negative); 8 warnings total. +--let $assert_text = case 4: divergence warning fired for all sub-partitions +--let $assert_select = FIL cache name .*(st|stn)#p#p[12]#sp#s[pn]@002d[a-d].* differs +--let $assert_count = 8 +--source include/assert_grep.inc + +DROP TABLE st, stn; + + +--echo # === Cleanup === + +DROP DATABASE cleandb; + +--disable_query_log +CALL mtr.add_suppression("\\[InnoDB\\] FIL cache name .* differs from data dictionary name"); +# Negative halves leave ibd_file_missing=true on the sub-table, which +# emits the statistics warning on the failing SELECT. +CALL mtr.add_suppression("\\[InnoDB\\] Cannot calculate statistics for table .* because the .ibd file is missing"); +--enable_query_log diff --git a/sql/sql_table.cc b/sql/sql_table.cc index fe603cd8bb9..19b7d93ccb0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -19178,6 +19178,17 @@ end_inplace_noop: uncommitted_tables.add_table(table_list); + /* Repro hook for the FIL-cache fs-charset vs system-charset split + after atomic-DDL rollback (see dd_load_tablespace). Forces a copy- + style ALTER past both mysql_rename_table calls to fail into + err_with_mdl, which triggers the rollback branch in + fil_op_replay_rename. Used by + innodb.alter_rollback_fs_charset_split. */ + DBUG_EXECUTE_IF("force_alter_rollback_after_rename", { + my_error(ER_LOCK_DEADLOCK, MYF(0)); + goto err_with_mdl; + }); + if (update_referencing_views_metadata(thd, table_list, new_db, new_name, !atomic_replace, &uncommitted_tables)) goto err_with_mdl; diff --git a/storage/innobase/dict/dict0dd.cc b/storage/innobase/dict/dict0dd.cc index 55356dcc259..f0660c92ac3 100644 --- a/storage/innobase/dict/dict0dd.cc +++ b/storage/innobase/dict/dict0dd.cc @@ -4853,9 +4853,37 @@ void dd_load_tablespace(const Table *dd_table, dict_table_t *table, char *filepath = fil_space_get_first_path(table->space); if (filepath != nullptr) { - /* If space id is already open with a different space name, then skip - loading the space. It can happen because DDL log recovery might not - have happened yet. */ + /* The space id is already open under a different name. Usually + that means DDL-log recovery has not run yet and the cache will + catch up later. One case does not catch up on its own: a copy- + style ALTER that runs both mysql_rename_table() calls and then + fails into err_with_mdl reaches fil_op_replay_rename's "rollback + target file does NOT exist" branch, which string-slices the .ibd + path with no charset decoding and leaves space->name in filesystem + charset (e.g. "schema@002dx/t1"). space_name here is in system + charset ("schema-x/t1"), so fil_space_exists_in_mem misses and the + table appears missing even though the .ibd is intact. Pure ASCII + alnum names are byte-identical in both charsets and so hide the + bug; names containing '-' or any @NNNN-encoded character expose + it. Reconcile via fil_space_update_name and retry the cache lookup; + fall through to ibd_file_missing on any other divergence. */ + fil_space_t *space = fil_space_get(table->space); + if (space != nullptr && space->name != nullptr && + strcmp(space->name, space_name) != 0) { + ib::warn(ER_IB_MSG_173) + << "FIL cache name '" << space->name + << "' differs from data dictionary name '" << space_name + << "' for space " << table->space << "; reconciling before" + << " opening table " << table->name; + if (DBUG_EVALUATE_IF("dd_load_tablespace_skip_fix", false, true)) { + fil_space_update_name(space, space_name); + if (is_already_opened()) { + ut::free(filepath); + return; + } + } + } + table->ibd_file_missing = true; ut::free(shared_space_name); -- 2.43.7