关于MySQL ERROR 1146 Table doesnt exist的解析

在MYSQL使用innodb的时候我们有时候会看到如下报错:ERROR 1146 (42S02): Table 'test.test1bak' doesn't exist.本文主要根据innodb数据字典不包含这个表的情况进行解析。 2017-10-11 14:00:50 数据库MySQLERROR解析 为什么SQL正在击败NoSQL,这对未来的数据意味着什么 自从可以利用计算机做事以来,我们一直在收集的数据以指数级的速度在增长,因此对于数据存储、处理和分析技术的要求也越来越高。在过去的十年里,由于SQL无法满足这些要求,软件开发人员就抛弃了它,NoSQL也就因此而渐渐发展起来:MapReduce,Bigtable,Cassandra,MongoDB等等。 2017-10-10 15:04:16 SQL数据库计算机 网易数据运河系统NDC设计与应用 NDC是网易近一年新诞生的结构化数据传输服务,它整合了网易过去在数据传输领域的各种工具和经验,将单机数据库、分布式数据库、OLAP系统以及下游应用通过数据链路串在一起。除了保障高效的数据传输外,NDC的设计遵循了单元化和平台化的设计哲学,本篇文章将带大家近距离了解NDC的设计思路和实现原理。

在MYSQL使用innodb的时候我们有时候会看到如下报错:ERROR 1146 (42S02): Table 'test.test1bak' doesn't exist.本文主要根据innodb数据字典不包含这个表的情况进行解析。

[[205963]]

☉源码版本 5.7.14

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

  1. ERROR1146(42S02):Table'test.test1bak'doesn'texist

首先总结下原因:

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

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

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

  1. mysql>showtables;
  2. |test1bak|
  3. mysql>desctest1bak;
  4. ERROR1146(42S02):Table'test.test1bak'doesn'texist

也许你会说我明明能够看到这个表啊,为什么访问还会报错呢?其实要清楚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是否包含了这个表的信息。也许在这些数据字典中也许某些列并显示并不是那么明确,比如

  1. mysql>select*frominformation_schema.innodb_sys_tableswherename='test/kkkkm1';
  2. +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+
  3. |TABLE_ID|NAME|FLAG|N_COLS|SPACE|FILE_FORMAT|ROW_FORMAT|ZIP_PAGE_SIZE|SPACE_TYPE|
  4. +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+
  5. |374|test/kkkkm1|33|6|540|Barracuda|Dynamic|0|Single|
  6. +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+

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

  1. /*TableandtablespaceflagsaregenerallynotusedfortheAntelopefile
  2. formatexceptfortheloworderbit,whichisuseddifferentlydependingon
  3. wheretheflagsarestored.
  4. ====================Loworderflagsbit=========================
  5. |REDUNDANT|COMPACT|COMPRESSEDandDYNAMIC
  6. SYS_TABLES.TYPE|1|1|1
  7. dict_table_t::flags|0|1|1
  8. FSP_SPACE_FLAGS|0|0|1
  9. fil_space_t::flags|0|0|1
  10. /**WidthoftheCOMPACTflag*/
  11. #defineDICT_TF_WIDTH_COMPACT1
  12. /**WidthoftheZIP_SSIZEflag*/
  13. #defineDICT_TF_WIDTH_ZIP_SSIZE4
  14. /**WidthoftheATOMIC_BLOBSflag.TheAntelopefileformatsbrokeup
  15. BLOBandTEXTfields,storingthefirst768bytesintheclusteredindex.
  16. Barracudarowformatsstorethewholeblobortextfieldoff-pageatomically.
  17. Secondaryindexesarecreatedfromthisexternaldatausingrow_ext_t
  18. tocachetheBLOBprefixes.*/
  19. #defineDICT_TF_WIDTH_ATOMIC_BLOBS1
  20. /**IfatableiscreatedwiththeMYSQLoptionDATADIRECTORYand
  21. innodb-file-per-table,anolderenginewillnotbeabletofindthattable.
  22. Thisflagpreventsolderenginesfromattemptingtoopenthetableand
  23. allowsInnoDBtoupdate_create_info()accordingly.*/
  24. #defineDICT_TF_WIDTH_DATA_DIR1
  25. /**WidthoftheSHAREDtablespaceflag.
  26. Itisusedtoidentifytablesthatexistinsideasharedgeneraltablespace.
  27. IfatableiscreatedwiththeTABLESPACE=tsnameoption,anolderenginewill
  28. notbeabletofindthattable.Thisflagpreventsolderenginesfromattempting
  29. toopenthetableandallowsInnoDBtoquicklyfindthetablespace.*/
  30. #defineDICT_TF_WIDTH_SHARED_SPACE1

接下来我们分析一下为什么是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

  1. 503T@2:||||||||||||>dict_table_open_on_name
  2. 504T@2:|||||||||||||dict_table_open_on_name:table:'test/test1bak'
  3. 505T@2:|||||||||||||>dict_table_check_if_in_cache_low
  4. 506T@2:||||||||||||||dict_table_check_if_in_cache_low:table:'test/test1bak'
  5. 507T@2:|||||||||||||<dict_table_check_if_in_cache_low125
  6. 508T@2:|||||||||||||>dict_load_table
  7. 509T@2:||||||||||||||dict_load_table:loadingtable:'test/test1bak'
  8. 510T@2:||||||||||||||>dict_table_check_if_in_cache_low
  9. 511T@2:|||||||||||||||dict_table_check_if_in_cache_low:table:'test/test1bak'
  10. 512T@2:||||||||||||||<dict_table_check_if_in_cache_low125
  11. 513T@2:||||||||||||||>dict_load_table_one
  12. 514T@2:|||||||||||||||dict_load_table_one:table:test/test1bak
  13. 515T@2:|||||||||||||||>dict_table_check_if_in_cache_low
  14. 516T@2:||||||||||||||||dict_table_check_if_in_cache_low:table:'SYS_TABLES'
  15. 517T@2:|||||||||||||||<dict_table_check_if_in_cache_low125
  16. 518T@2:|||||||||||||||>btr_cur_search_to_nth_level
  17. 519T@2:|||||||||||||||<btr_cur_search_to_nth_level2005
  18. 520T@2:||||||||||||||<dict_load_table_one3084
  19. 521T@2:|||||||||||||<dict_load_table2882
  20. 522T@2:||||||||||||<dict_table_open_on_name1292
  21. 523T@2:|||||||||||<ha_innobase::open_dict_table6676
  22. 524T@2:|||||||||||>sql_print_warning
  23. 525T@2:||||||||||||>error_log_print
  24. 526T@2:|||||||||||||>print_buffer_to_file
  25. 527T@2:||||||||||||||enter:buffer:InnoDB:Cannotopentabletest/test1bakfromtheinternaldatadictionaryofInnoDBthoughthe.frmfileforthe
  26. tableexists.Pleaserefertohttp://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.htmlforhowtoresolvetheissue.
  27. 528T@2:|||||||||||||<print_buffer_to_file2332
  28. 529T@2:||||||||||||<error_log_print2357
  29. 530T@2:|||||||||||<sql_print_warning2384

☉其实大概步骤就是

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+树也是存在其中,用源码解释一下:

  1. /**********************************************************************//**
  2. Getsapointertothedictionaryheaderandx-latchesitspage.
  3. @returnpointertothedictionaryheader,pagex-latched*/
  4. dict_hdr_t*
  5. dict_hdr_get(
  6. /*=========*/
  7. mtr_t*mtr)/*!<in:mtr*/
  8. {
  9. buf_block_t*block;
  10. dict_hdr_t*header;
  11. block=buf_page_get(page_id_t(DICT_HDR_SPACE,DICT_HDR_PAGE_NO),
  12. univ_page_size,RW_X_LATCH,mtr);
  13. header=DICT_HDR+buf_block_get_frame(block);
  14. buf_block_dbg_add_level(block,SYNC_DICT_HEADER);
  15. return(header);
  16. }

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

  1. /*Spaceidandpagenowherethedictionaryheaderresides*/
  2. #defineDICT_HDR_SPACE0/*theSYSTEMtablespace*/
  3. #defineDICT_HDR_PAGE_NOFSP_DICT_HDR_PAGE_NO
  4. #defineFSP_DICT_HDR_PAGE_NO7/*!<datadictionaryheader
  5. page,intablespace0*/

space 0就是ibdata1的space_no,7当然就是引导块,这哥们连ibdata1都没拷贝,当然innodb数据字典自然不包含这些表了。其实也是上面描述的原理 。

 那么正确的拷贝的方式一定是停机后,整个数据目录进行拷贝,而不是仅仅拷贝需要的库的目录,否则innodb数据字典是不能正常加载的。

***附带space 0的部分块解释

  1. /*--------------------------------------*/
  2. #defineFSP_XDES_OFFSET0/*!<extentdescriptor*/
  3. #defineFSP_IBUF_BITMAP_OFFSET1/*!<insertbufferbitmap*/
  4. /*Theibufbitmappagesaretheoneswhose
  5. pagenumberisthenumberaboveplusa
  6. multipleofXDES_DESCRIBED_PER_PAGE*/
  7. #defineFSP_FIRST_INODE_PAGE_NO2/*!<ineverytablespace*/
  8. /*Thefollowingpagesexist
  9. inthesystemtablespace(space0).*/
  10. #defineFSP_IBUF_HEADER_PAGE_NO3/*!<insertbuffer
  11. headerpage,in
  12. tablespace0*/
  13. #defineFSP_IBUF_TREE_ROOT_PAGE_NO4/*!<insertbuffer
  14. B-treerootpagein
  15. tablespace0*/
  16. /*Theibuftreerootpagenumberin
  17. tablespace0;itsfseginodeisonthepage
  18. numberFSP_FIRST_INODE_PAGE_NO*/
  19. #defineFSP_TRX_SYS_PAGE_NO5/*!<transaction
  20. systemheader,in
  21. tablespace0*/
  22. #defineFSP_FIRST_RSEG_PAGE_NO6/*!<firstrollbacksegment
  23. page,intablespace0*/
  24. #defineFSP_DICT_HDR_PAGE_NO7/*!<datadictionaryheader
  25. page,intablespace0*/
  26. ****/*--------------------------------------*/****

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月6日 09:55
下一篇 2023年5月6日 09:55

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信