原创转载请注明出处

源码版本 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的数据字典,主要的包含:

INNODB_SYS_columns

INNODB_SYS_FIELDS

INNODB_SYS_TABLES

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 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: | | | | | | | | | | | | |

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: | | | | | | | | | | | | | |

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: | | | | | | | | | | | | | | |

518 T@2: | | | | | | | | | | | | | | | >btr_cur_search_to_nth_level

519 T@2: | | | | | | | | | | | | | | |

520 T@2: | | | | | | | | | | | | | |

521 T@2: | | | | | | | | | | | | |

522 T@2: | | | | | | | | | | | |

523 T@2: | | | | | | | | | | | <:open_dict_table>

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: | | | | | | | | | | | | |

529 T@2: | | | | | | | | | | | |

530 T@2: | | | | | | | | | | |

其实大概步骤就是

Checks if a table is in the dictionary cache

根据dict_sys->table_hash寻找

Loads a table definition and also all its index definitions.

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

如果不能找到则报错

这样也就解释了为什么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 */

****/*--------------------------------------*/****

doesnt exist table_MYSQL ERROR 1146 Table doesnt exist 解析相关推荐

  1. mysqld_exporter报错Error 1146: Table 'my2.status' doesn't exist

    grafana安装mysql simple dashboard后提示Templating init failed Error 1146: Table 'my2.status' doesn't exis ...

  2. mysql 提示表不存在的解决方法error 1146 Table doesn't exist

    直接拷贝数据库导致提示表不存在的解决方法 电脑重装系统后把原来的mysql data复制进去后大部分表是可以访问的,但是有几个表提示表不存在: error: 1146: Table 'your_tab ...

  3. Mysql 5.7 表名大写遇到的坑 error: 1146: Table 'your_table' doesn't exist

    环境 数据库从Mysql5.6导出后导入到Mysql5.7,操作系统是 Centos7 问题 在导入脚本中表名都是大写,导入后无论是命令行.navicat.还是Java代码,均提示表不存在. Tabl ...

  4. golang使用grom连接mysql,Error 1146: Table ‘xxx.xxxs‘ doesn‘t exist

    解决办法: DB.SingularTable(true) 原因: 因为不设定的话,默认会在表后面加s

  5. centos mysql 1146_MySQL查询报错:ERROR 1146 (42S02): Table 'craw.sitePageConfig' doesn't exist

    今天一同事咨询mysql的问题,在mysql主库访问某个表报错, 但是备库上可以,感觉有点奇怪.即使不同步, 也不能说主库不能访问啊. 既然是主备,就从主备同步开始查.各种show master st ...

  6. ERROR 1146 (42S02): Table ‘xxxxxxx‘ doesn‘t exist模拟删表删库恢复

    ERROR 1146 42S02: Table doesn't exist模拟删表删库恢复 0. 事件概要 1.准备工作 1.1 确保binlog配置文件 1.2 建立binlog目录 1.3 重启M ...

  7. ERROR 1146 (HY000): Table ‘itcast.tb_log‘ doesn‘t exist;使用 Mycat 连接到mysql8 建表,发现表名,字段名全为大写解决方案!

    使用 MyCat连接 MySql8后,新建的表.字段都是大写的,并且在执行 insert 语句时报错: ERROR 1146 (HY000): Table 'itcast.tb_log' doesn' ...

  8. MySql Error 1146 Tabel doen't exist

    最近在导入数据库的时候出现问题:MySql Error 1146 Tabel doen't exist 解决办法: 1. mysql -uroot -proot登录到数据库 2. use databa ...

  9. Ubuntu 使用phpmyadmin,报错#1146 - Table ‘phpmyadmin.pma_table_uiprefs' doesn't exist

    cd /etc/phpmyadminsudo vim config.inc.php 修改phpmyadmin的配置文件config.inc.php $cfg['Servers'][$i]['table ...

最新文章

  1. sklearn 归一化 和 标准化
  2. 批处理,%~d0 cd %~dp0 代表什么意思
  3. java 的类型转换方式
  4. 动圈耳机振膜_耳机中的动圈、动铁、圈铁都是什么意思 买哪种最好?
  5. npm与Yarn命令对比
  6. 网易云信合作伙伴招募计划全面开启!
  7. 如何高效学习前端新知识,拓展视野,我推荐
  8. css英文左右对齐,中文英文左右padding一致两端对齐实现_js
  9. java8 lambda map排序_Android兼容Java 8语法特性的原理分析
  10. gulp-sass的有关问题
  11. mysql 处理一条语句卡死_一条MySQL查询语句,卡死机器,不知道为什么,求高手指点!...
  12. Wireshark 文件分割和合并
  13. Bootstrap 使用教程 与jQuery的Ajax方法
  14. Docker 5分钟搭建web服务器
  15. 扑克牌练习 【数据结构】
  16. 关于火车采集文章发布到wordpress后台待审核模块的设置
  17. HTTP 503 Service Temporarily Unavailable
  18. PowerApps教程07-记录的详细信息显示
  19. gitlab安装及配置
  20. 查看centos 的版本

热门文章

  1. 用74LS161构建多位计数器Multisim仿真实验
  2. 在 aws emr 上,将 hbase table A 的数据,对 key 做 hash,写到另外一张 table B
  3. Median of Two Sorted Arrays
  4. python 读帧和绘图的区别
  5. 关于图片按比例自适应缩放
  6. hashCode与equals的区别与联系
  7. UA MATH567 高维统计专题1 稀疏信号及其恢复3 Coherence与RIP简介
  8. Bochs调试Linux内核 - 定位内核中的变量或数据结构
  9. Windows下32位汇编语言读取键盘输入单字符
  10. C++ boost 实例学习