千家信息网

如何解析MYSQL ERROR 1146 Table doesnt exist

发表于:2024-10-18 作者:千家信息网编辑
千家信息网最后更新 2024年10月18日,今天就跟大家聊聊有关如何解析MYSQL ERROR 1146 Table doesnt exist ,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收
千家信息网最后更新 2024年10月18日如何解析MYSQL ERROR 1146 Table doesnt exist

今天就跟大家聊聊有关如何解析MYSQL ERROR 1146 Table doesnt exist ,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

源码版本 5.7.14


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

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

首先总结下原因:

  • 缺少frm文件

  • innodb数据字典不包含这个表

我们重点讨论情况2,因为情况1是显而易见的。
?在使用innodb存储引擎的时候某些时候我们show tables能够看到这个表,但是如果进行任何操作会报错如下:

mysql> show tables;| test1bak          |mysql> desc test1bak ;ERROR 1146 (42S02): Table 'test.test1bak' doesn't 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 fileformat except for the low order bit, which is used differently depending onwhere the flags are stored.==================== Low order flags bit =========================                    | REDUNDANT | COMPACT | COMPRESSED and DYNAMICSYS_TABLES.TYPE     |     1     |    1    |     1dict_table_t::flags |     0     |    1    |     1FSP_SPACE_FLAGS     |     0     |    0    |     1fil_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 upBLOB 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_tto cache the BLOB prefixes. */#define DICT_TF_WIDTH_ATOMIC_BLOBS  1/** If a table is created with the MYSQL option DATA DIRECTORY andinnodb-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 andallows 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 willnot be able to find that table. This flag prevents older engines from attemptingto 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_tableDATA 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 Files

 502  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_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_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: | | | | | | | | | | | | | | | btr_cur_search_to_nth_level   519  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: | | | | | | | | | | | | | 

其实大概步骤就是

  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 doesn't exist ,而从原理上讲show tables只是查看了frm文件。


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

/**********************************************************************//**Gets a pointer to the dictionary header and x-latches its page.@return pointer to the dictionary header, page x-latched */dict_hdr_t*dict_hdr_get(/*=========*/    mtr_t*  mtr)    /*!< in: mtr */{    buf_block_t*    block;    dict_hdr_t* header;    block = buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO),                 univ_page_size, RW_X_LATCH, mtr);    header = DICT_HDR + buf_block_get_frame(block);    buf_block_dbg_add_level(block, SYNC_DICT_HEADER);    return(header);}

注意这里的 DICT_HDR_SPACE, DICT_HDR_PAGE_NO分别是宏定义

/* Space id and page no where the dictionary header resides */#define DICT_HDR_SPACE      0   /* the SYSTEM tablespace */#define DICT_HDR_PAGE_NO    FSP_DICT_HDR_PAGE_NO#define FSP_DICT_HDR_PAGE_NO        7   /*!< data dictionary header                                   page, in tablespace 0 */

space 0就是ibdata1的space_no,7当然就是引导块,这哥们连ibdata1都没拷贝,当然innodb数据字典自然不包含这些表了。其实也是上面描述的原理 。
?那么正确的拷贝的方式一定是停机后,整个数据目录进行拷贝,而不是仅仅拷贝需要的库的目录,否则innodb数据字典是不能正常加载的。

最后附带space 0的部分块解释

/*--------------------------------------*/#define FSP_XDES_OFFSET         0   /* !< extent descriptor */#define FSP_IBUF_BITMAP_OFFSET      1   /* !< insert buffer bitmap */                /* The ibuf bitmap pages are the ones whose                page number is the number above plus a                multiple of XDES_DESCRIBED_PER_PAGE */#define FSP_FIRST_INODE_PAGE_NO     2   /*!< in every tablespace */                /* The following pages exist                in the system tablespace (space 0). */#define FSP_IBUF_HEADER_PAGE_NO     3   /*!< insert buffer                        header page, in                        tablespace 0 */#define FSP_IBUF_TREE_ROOT_PAGE_NO  4   /*!< insert buffer                        B-tree root page in                        tablespace 0 */                /* The ibuf tree root page number in                tablespace 0; its fseg inode is on the page                number FSP_FIRST_INODE_PAGE_NO */#define FSP_TRX_SYS_PAGE_NO     5   /*!< transaction                        system header, in                        tablespace 0 */#define FSP_FIRST_RSEG_PAGE_NO      6   /*!< first rollback segment                        page, in tablespace 0 */#define FSP_DICT_HDR_PAGE_NO        7   /*!< data dictionary header                        page, in tablespace 0 */****/*--------------------------------------*/****

看完上述内容,你们对如何解析MYSQL ERROR 1146 Table doesnt exist 有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

0