Description:
(1). When replaying Log_Type::RENAME_SPACE_LOG, fil_op_replay_rename use new_name in converted format like 'test/t@002d1' which should be 'test/t-1'.
(2). After space cache is polluted, dd_load_tablespace (invokded when opening table)
will find nothing in cache then invoke fil_ibd_open
(3). fil_ibd_open read page 0 directly, however page 0 may have not be flushed, then
we get a file_space_t containing inconsistent info.
(4). If the table is encrypted (TDE), key info is stored in page 0, if key info is inconsistent, DML may return with error ER_CANNOT_FIND_KEY_IN_KEYRING.
(1) (2) always happen, while (3) (4) is rare but what we encountered.
How to repeat:
(1) (2)
gdb attach mysqld and break at fil_op_replay_rename_for_ddl.
block bage_flush with some method if you want to repeat (3) and (4)
create table `t-1` (
`id` int primary key auto_increment,
`type` text DEFAULT NULL,
`info` varchar(50) DEFAULT NULL
) engine=InnoDB encryption='Y';
set global debug = "+d,ib_truncate_fail_after_rename";
truncate table test.`t-1`;
fil_op_replay_rename_for_ddl will be invoked in post_ddl. Step in and you
will see that space->name is replaced with test/t@002d1.
(3) (4)
you should evict dict_table_t by some method, like opening a large number of tables (more that cache capicity).
insert into `t-1` (`type`, `info`) values (repeat("#",3000), repeat("#",5));
ER_CANNOT_FIND_KEY_IN_KEYRING will be return
Suggested fix:
1. Convert space name(test/t@002d1) back to user-defined format(test/t-1) in fil_op_replay_rename.
2. dd_load_tablespace can be invoked in runtime and read page 0 directly
from disk (skip buffer pool), this is somewhat unreasonable.