原标题:show tables能看到表却无法读写?

作者:高鹏(八怪)

来源:http://www.jianshu.com/p/8af0b92e4fc8

MySQL版本 5.7.14(社区版源码基础上增加一些debug代码)

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

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 deor */#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 show tables报错_show tables能看到表却无法读写?相关推荐

  1. mysql 中文字段报错_mysql 中 王数据表中插入中文字段报错:mysql insert into a values(202,王一); ERROR 1366 (HY000): Incorr...

    报错信息: mysql> insert into a values(202,"王一"); ERROR 1366 (HY000): Incorrect string value ...

  2. MySQL与oracle报错显示_Oracle中判断表是否存在再删除表避免报错与MySql和SqlServer的不同...

    不同数据库中drop a table if it exists的不同: In MySQL it is pretty easy to drop a table if it exists already. ...

  3. kettle使用mysql作为资源库报错 创建资源库时只有25张表,原本应该46张表。

    kettle使用mysql作为资源库报错 创建资源库时只有25张表,原本应该46张表. 连用户表都没有 ,导致连 默认的 admin和guest都无法登陆自己的资源库!!!! 问题是 SQL语句里边使 ...

  4. mysql安装教程博音网_RTSP视频平台EasyNVR使用mysql数据源启动报错unknow drivermysql优化...

    原标题:RTSP视频平台EasyNVR使用mysql数据源启动报错unknow driver"mysql"优化 我们上一篇讲了TSINGSEE青犀视频开发的视频平台默认都是使用的s ...

  5. mysql source导入报错ERROR 1366的解决方法

    mysql source导入报错ERROR 1366的解决方法 参考文章: (1)mysql source导入报错ERROR 1366的解决方法 (2)https://www.cnblogs.com/ ...

  6. mysql group by 报错 ,only_full_group_by 三种解决方案

    mysql group by 报错 ,only_full_group_by 三种解决方案 参考文章: (1)mysql group by 报错 ,only_full_group_by 三种解决方案 ( ...

  7. Linux下MySql插入汉字报错解决(/etc/my.cnf不存在)

    2019独角兽企业重金招聘Python工程师标准>>> Linux下MySql插入汉字报错解决(/etc/my.cnf不存在) 看了很多帖子,大多数是说修改my.cnf,如 http ...

  8. mysql创建用户报错ERROR 1290

    使用navicat 给mysql创建用户报错ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv op ...

  9. mysql分页查询报错,及解决

    mysql分页查询报错: 前提: 1.每页1000条数据 2.查到57页的时候,就报错了 以下是错误信息: org.springframework.jdbc.UncategorizedSQLExcep ...

最新文章

  1. iOS Masonry的使用详解
  2. c++ class struct同名_第二课C到C++的关系
  3. eclipese web前端开发教学_Web前端零基础好学吗?新手该怎么学?
  4. mysql jdbc 5.1.6_mysql5.0+Mysqljdbc5.1.6.jar的整合 | 學步園
  5. python学习-Pillow图像处理
  6. js时间对象:获取当前时间(格式化)- 代码篇
  7. 易于使用的人工智能_通过AI使网络更易于访问
  8. 共迎海量数据库管理挑战 中韩数据库专家对话北京
  9. 20170114 - Mac 向上一级文件夹快捷键
  10. 23_Open_Loop
  11. 合作博弈(coalitional game)——核仁(Nucleolus)初解
  12. 批量重命名文件夹和文件名bat脚本
  13. Wireshark 用户使用手册 ———— 自定义 Wireshark
  14. idea 2019.2顶部菜单栏隐藏的恢复办法
  15. 新概念二册 Lesson 6 Percy Buttons泊西·巴顿斯 (冠词)
  16. Google Earth Engine——MERRA-2 M2T1NXAER:1980-2022年气溶胶逐日数据集
  17. COM组件开发(四)——VC++调用COM组件的方法
  18. 图灵奖得主Jack Dongarra:高性能计算与AI大融合,如何颠覆科学计算
  19. KIngcms 5.1版本增加站内链接功能自动给指定关键词加上链接
  20. 使用PLSql连接Oracle时报错ORA-12541: TNS: 无监听程序

热门文章

  1. 关于 Content-Type:application/x-www-form-urlencoded 和 Content-Type:multipart/relat
  2. 掌财社:将鳄鱼的特性完全运用到期货战场中
  3. 基于云开发的二手书交易微信小程序
  4. python io
  5. 2.发那科工业机器人操作规范及坐标系介绍
  6. 计算机专业大创要求,计算机学院举行2018年度“大创项目”研究工作推进会
  7. 使用ThreeJs从零开始构建3D智能仓库——第二章(创建地面与门窗)
  8. 如何使用hbuilder快速生成一个直接打开网站的app
  9. January 04th, 2018 Week 01st Thursday
  10. JAVA -生日礼物