Description:
When a DDL statement related to Log_Type::RENAME_SPACE_LOG type ddl log crashes unexpectedly and the server is subsequently restarted. In such cases, the table involved in the DDL statement may not be found.
Root Cause:
The format of Log_Type::RENAME_SPACE_LOG is similar to
[DDL record: RENAME SPACE, id=13038, thread_id=13, space_id=2436, old_file_path="old_file_path".ibd, new_file_path="new_file_path".ibd].
Both the “old_file_path“ and “new_file_path“ use "my_charset_filename" charset, while the tablespace name uses "system_charset_info" charset. During the DDL recovery process,the "new_space_name" is parsed from the "new_file_path" without converting the charset. As a result, after the server restarts, loading the space related to "new_file_path" fails.
Definition:
The “my_charset_filename” includes the following characters, any other characters being converted to @xxxx as referenced in https://dev.mysql.com/doc/refman/8.0/en/identifier-mapping.html
1. '\0' NULL
2. A..Z capital letters,
3. a..z small letters
4. 0..9 digits
5. _ underscore
The “system_charset_info” is Unicode (UTF-8).
How to repeat:
1. Prepare multiple tables with names containing special characters that are present in "system_charset_info" but not in "my_charset_filename". For example, create 50 tables with name containing the Chinese character "测试". The table names are listed as follows:
create table `测试001` (a int);
create table `测试002`(a int);
...
create table `测试050`(a int);
2. Ensure that the `innodb_print_ddl_logs` variable is enabled and execute the RENAME TABLE statement to rename these tables containing special characters. When you see the DDL logs appear in the error log, immediately kill the server. For example, rename tables `测试001`, `测试002`, ..., `测试050` to `测试101`, `测试102`, ..., `测试150`.
RENAME TABLE `测试001` TO `测试101`, `测试002` TO `测试102`, ..., `测试050` TO `测试150`;
3. Restart the server and then use the SHOW CREATE TABLE statement to display the tables recovered from replaying the DDL log. The result will report "Tablespace is missing for table 测试xxx".
Suggested fix:
The "fil_space_t::name" use "system_charset_info" charset. During the DDL recovery process, the function fil_rename_tablespace parses the tablespace name from “new_file_path“ . it then transfers tablespace name to "fil_space_t::name” by invoking fil_rename_tablespace function.