MySQL提示:ERROR 1146 (42S02): Table 'xxx.xxx' doesn't exist

问题现象

在重启RDS MySQL实例后,进行表相关操作时,提示如下错误:

ERROR 1146 (42S02): Table 'xxx.xxx' doesn't exist

同时,在error log中可见如下记录:

[Warning] InnoDB: Load table `xxx`.`xxx` failed, the table has missing foreign key indexes. Turn off 'foreign_key_checks' and try again.
[Warning] InnoDB: Cannot open table xxx/xxx from the internal data dictionary of InnoDB though the .frm file for the table exists.

可能原因

MySQL中添加外键需要满足相应条件和限制,详情请见官方文档FOREIGN KEY Constraints

MySQL的外键限制检查是通过变量foreign_key_checks来控制的,该变量可以在RDS MySQL实例运行时修改,不需要重启实例,默认值为ON。若将foreign_key_checks设为OFF,除特殊情况外(详情请参见官方文档FOREIGN KEY Constraints),将关闭外键限制检查。

如果在关闭外键限制检查后,对外键进行了变更使其不满足外键限制,在RDS MySQL实例运行时不会报错。在重启实例时,由于重启时froeign_key_checks默认开启,InnoDB打开表时会进行外键限制检查,此时会报错。

常见的情况有以下两种:

  • 更改了父表和子表外键相关列的字符集

    MySQL 5.6、5.7、8.0允许在foreign_key_checks设置为OFF的情况下,修改父表和子表外键相关列的字符集。实例重启以后:

    • MySQL 5.6、5.7会在error log中提示warning,同时无法使用父表。

    • MySQL 8.0不会在error log中提示warning,可以使用父表。

  • 删除了父表和子表外键相关列的索引

    • 对于MySQL 5.7、8.0:不允许在foreign_key_checks设置为OFF的情况下,删除父表和子表外键相关列的索引。

    • 对于MySQL 5.6:允许在foreign_key_checks设置为OFF的情况下,删除父表和子表外键相关列的索引。删除相关列索引后,重启实例会提示warning,同时被删除索引的表无法使用。

解决方案

  • 对于修改字符集导致的问题,将foreign_key_checks设置为OFF,将父表和子表外键相关列的字符集修改一致。

  • 对于删除索引导致的问题,将foreign_key_checks设置为OFF,重建索引。