关于MySQL ERROR 1146 Table doesnt exist的解析

☉源码版本 5.7.14

在MYSQL使用innodb的关于时候我们有时候会看到如下报错:

ERROR 1146 (42S02): Table test.test1bak doesnt exist 

首先总结下原因:

缺少frm文件 innodb数据字典不包含这个表

我们重点讨论情况2,因为情况1是关于显而易见的。

在使用innodb存储引擎的关于时候某些时候我们show tables能够看到这个表,但是如果进行任何操作会报错如下:

mysql> show tables;    | test1bak          |    mysql> desc test1bak ;    ERROR 1146 (42S02): Table test.test1bak doesnt exist

也许你会说我明明能够看到这个表啊,为什么访问还会报错呢?关于其实要清楚innodb有自己的数据字典,只要有frm 文件存在show tables就能看到,关于但是关于最终是否能够正常打开表结构在innodb中还依赖于innodb的数据字典,主要的关于包含:

1、INNODB_SYS_columns

2、关于INNODB_SYS_FIELDS

3、关于INNODB_SYS_TABLES

4、关于INNODB_SYS_INDEXES

如果报错出现我们需要首先查看的关于是INNODB_SYS_TABLES是否包含了这个表的服务器租用信息。也许在这些数据字典中也许某些列并显示并不是关于那么明确,比如

mysql> select * from information_schema.innodb_sys_tables where name=test/kkkkm1;    +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+    | TABLE_ID | NAME        | FLAG | N_COLS | SPACE | FILE_FORMAT | ROW_FORMAT | ZIP_PAGE_SIZE | SPACE_TYPE |    +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+    |      374 | test/kkkkm1 |   33 |      6 |   540 | Barracuda   | Dynamic    |             0 | Single     |    +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+

比如这里的关于FLAG列为33,他实际上是关于一个位图表示方式,分别表示如下信息:

/* Table and tablespace flags are generally not used for the Antelope file    format except for the low order bit,关于 which is used differently depending on    where the flags are stored.    ==================== Low order flags bit =========================                        | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC    SYS_TABLES.TYPE     |     1     |    1    |     1    dict_table_t::flags |     0     |    1    |     1    FSP_SPACE_FLAGS     |     0     |    0    |     1    fil_space_t::flags  |     0     |    0    |     1    /** Width of the COMPACT flag */    #define DICT_TF_WIDTH_COMPACT       1    /** Width of the ZIP_SSIZE flag */    #define DICT_TF_WIDTH_ZIP_SSIZE     4    /** Width of the ATOMIC_BLOBS flag.  The Antelope file formats broke up    BLOB and TEXT fields, storing the first 768 bytes in the clustered index.    Barracuda row formats store the whole blob or text field off-page atomically.    Secondary indexes are created from this external data using row_ext_t    to cache the BLOB prefixes. */    #define DICT_TF_WIDTH_ATOMIC_BLOBS  1    /** If a table is created with the MYSQL option DATA DIRECTORY and    innodb-file-per-table, an older engine will not be able to find that table.    This flag prevents older engines from attempting to open the table and    allows InnoDB to update_create_info() accordingly. */    #define DICT_TF_WIDTH_DATA_DIR      1    /** Width of the SHARED tablespace flag.    It is used to identify tables that exist inside a shared general tablespace.    If a table is created with the TABLESPACE=tsname option, an older engine will    not be able to find that table. This flag prevents older engines from attempting    to open the table and allows InnoDB to quickly find the tablespace. */    #define DICT_TF_WIDTH_SHARED_SPACE  1

接下来我们分析一下为什么是FLAG是33如下:

33的二进制为00100001从低位开始 1:从源码注释来看本位COMPACT/COMPRESSED/DYNAMIC均为1 0000: ZIP_SSIZE flag 这四位用于支持压缩功能如COMPRESSED 1:ATOMIC_BLOBS flag 这一位是COMPACT和DYNAMIC主要区别所在,请看源码注释 0:DATA DIRECTORY and innodb-file-per-table flag为了支持DATA DIRECTORY语法 0:SHARED tablespace flag为了支持TABLESPACE语法

然后我们测试一下:

如果我们建立如下的表: CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE = innodb_file_per_table DATA DIRECTORY = /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/mysqld.1; 其type为97二进制为 01100001:使用DATA DIRECTORY建立使用ATOMIC_BLOBS且无压缩则DYNAMIC格式 详见:15.5.5 Creating a File-Per-Table Tablespace Outside the Data Directory 如果我们建立如下的表: CREATE TABLESPACE tt1 ADD DATAFILE /root/mysql5.7.14/tt1.ibd; CREATE TABLE tsh (c1 INT ) TABLESPACE tt1 ROW_FORMAT=COMPACT ; 其type为129二进制为 10000001:使用TABLESPACE语法建立不使用ATOMIC_BLOBS且无压缩则为COMPACT格式 详见:15.5.9 InnoDB General Tablespaces

我们可以看到使用8位一个字节而已就可以表示出大量的信息,这也是位图的优势,其他比如 MTYPE/PRTYPE也是这种表示方式

接下来我们回到主题,需要看看这个错到底是哪里报错来的?进行trace后如下,我们来看看主要部分:

注意这里的亿华云计算trace是mysql debug版本下查看函数调用的主要方法参考官方文档26.5.1.2 Creating Trace Files502 T@2: | | | | | | | | | | | >ha_innobase::open_dict_table

503  T@2: | | | | | | | | | | | | >dict_table_open_on_name       504  T@2: | | | | | | | | | | | | | dict_table_open_on_name: table: test/test1bak       505  T@2: | | | | | | | | | | | | | >dict_table_check_if_in_cache_low       506  T@2: | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: test/test1bak       507  T@2: | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125       508  T@2: | | | | | | | | | | | | | >dict_load_table       509  T@2: | | | | | | | | | | | | | | dict_load_table: loading table: test/test1bak       510  T@2: | | | | | | | | | | | | | | >dict_table_check_if_in_cache_low       511  T@2: | | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: test/test1bak       512  T@2: | | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125       513  T@2: | | | | | | | | | | | | | | >dict_load_table_one       514  T@2: | | | | | | | | | | | | | | | dict_load_table_one: table: test/test1bak       515  T@2: | | | | | | | | | | | | | | | >dict_table_check_if_in_cache_low       516  T@2: | | | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: SYS_TABLES       517  T@2: | | | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125       518  T@2: | | | | | | | | | | | | | | | >btr_cur_search_to_nth_level       519  T@2: | | | | | | | | | | | | | | | <btr_cur_search_to_nth_level 2005       520  T@2: | | | | | | | | | | | | | | <dict_load_table_one 3084       521  T@2: | | | | | | | | | | | | | <dict_load_table 2882       522  T@2: | | | | | | | | | | | | <dict_table_open_on_name 1292       523  T@2: | | | | | | | | | | | <ha_innobase::open_dict_table 6676       524  T@2: | | | | | | | | | | | >sql_print_warning       525  T@2: | | | | | | | | | | | | >error_log_print       526  T@2: | | | | | | | | | | | | | >print_buffer_to_file       527  T@2: | | | | | | | | | | | | | | enter: buffer: InnoDB: Cannot open table test/test1bak from the internal data dictionary of InnoDB though the .frm file for the     table exists. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue.       528  T@2: | | | | | | | | | | | | | <print_buffer_to_file 2332       529  T@2: | | | | | | | | | | | | <error_log_print 2357       530  T@2: | | | | | | | | | | | <sql_print_warning 2384

☉其实大概步骤就是

1、Checks if a table is in the dictionary cache

根据dict_sys->table_hash寻找

2、Loads a table definition and also all its index definitions.

通过扫描字典的B+树进行加载

3、如果不能找到则报错

这样也就解释了为什么show tables能够看到但是select却报错Table doesnt exist ,而从原理上讲show tables只是查看了frm文件。

另外这里也提一个案列,曾经有一个朋友问我他将整个库目录都拷贝了,但是表能看到但是一操作就报Table doesnt exist,显然他没有拷贝ibdata1,数据字典的引导信息都存在这里面文件的第7个page中,其b+树也是存在其中,用源码解释一下:

/网站模板
域名
上一篇:当投资者经过第二阶段的认真学习之后又充满了信心,认为自己可以在市场上叱咤风云地大干一场了。但没想到“看花容易绣花难”,由于对理论知识不会灵活运用.从而失去灵活应变的本能,就经常会出现小赢大亏的局面,结果往往仍以失败告终。这使投资者很是困惑和痛苦,不知该如何办,甚至开始怀疑这个市场是不是不适合自己。在这种情况下,有的人选择了放弃,但有的意志坚定者则决定做最后的尝试。
下一篇:顶级域名可以增加企业品牌的价值。随着经济的快速发展,域名已不再是企业在网络中的独立地位。顶级域名的服务范围、企业产品、综合形象体现等,对于企业单位来说,顶级域名的重要性不言而喻。