背景:

MySQL经常会遇到Too many open files,MySQL上的open_files_limit和OS层面上设置的open file limit有什么关系?

源码中也会看到不同的数据结构,TABLE, TABLE_SHARE,跟表是什么关系?

MySQL flush tables又做了些什么,这几个东西放在一起,就会比较迷惑,下面进行梳理一下:

1 数据结构

table:   MySQL为每一个查询sql中的表建一个TABLE对象

table_share:  MySQL为每一张表建立一个table_share对象,与frm文件对应

handler:  对应于每个TABLE对象,innodb引擎创建一个handler

dict_table_t:  innodb为每一个ibd表load一个数据字典对象

简略图如下:

1. open table的过程

测试sql:select * from xpchild.pp

函数调用栈:

open_and_lock_tables

open_tables

open_and_process_table

open_table:打开一个table,并赋值给table_list->table

下面进入核心的逻辑:

开始锁lock_open:

1.1 table_share:

首先根据db&&table_name创建一个table_share.

函数调用栈:

get_table_share_with_discover: 创建或者查找table_share对象。

get_table_share:如果全局cache:table_def_cache中存在,就直接使用,如果不存在,就创建一个table_share

alloc_table_share: 如果不存在,先分配一个share的对象。

open_table_def: 打开frm文件。

mysql_file_open: my_open打开

inline_mysql_file_close: my_close关闭

share->ref_count++;

要点:

MySQL server层维护了一个全局的table definition cache即table_def_cache,所以一个table_share只会创建一次,后续进行共享。

初始化table_share的过程中,调用文件系统打开frm文件,初始化完成后,关闭frm文件。

share结构中ref_count来表示有多少个table关联

1.2 打开table:

open_table_from_share

step1: 初始化table中的变量,包括file handler (get_new_handler(share->db_type()))

step2: 添加各种索引,字段结构

step3: file->ha_open:ha_innobase::open 为innodb的table创建一个handler。

要点:

1. 在open table的过程中,innodb会创建一个handler,并打开ibd文件,初始化dict_table结构。

释放锁lock_open

1.3 close table:

sql执行结束之前,会调用close table

close_open_tables(thd)

table_def_unuse_table:

要点:

1.table_share维护了两个双向链表used_tables,free_tables,当close table的时候,

1.1 table->in_use=NULL,

1.2 把table从used_tables移除

1.3 加入到free_tables

2.全局参数table_cache_size,已经当前table_cache_count计数控制cache的置换策略

2. 再次执行sql

因为第一步已经完成了table_share的创建,并且cache了table,再次执行sql时,open table的过程就比较简单:

2.1: get_table_share:从cache中直接获取table_share对象

2.2:open_table_from_share:从s->free_tables中获取缓存的可以使用的table,然后增加ref计数。

if (!share->free_tables.is_empty())

table= share->free_tables.front();

++share->ref_count;

3 系统计数:

opened_tables:系统在open_table_from_share中,对新建的table,进行thd->status_var.opened_tables++计数。

opened_shares: 系统在 open_table_def的函数中,对于首次进行open的table_share进行thd->status_var.opened_shares++计数

注: 所以当系统的status:open_tables增长比较多的时候,可以适当的增加table_cache_size,用于缓存更多的table,毕竟open table的开销还是不小的。

4 status统计

使用show status命令,跟open有关的几个:

{"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}

注释:【全局变量】MySQL和innodb通过文件系统打开的文件的计数,这里包括了所有的文件,binlog,relay,alert,slow log等。

{"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC},

注释:【全局变量】server当前打开的table_share数量,等于table_def_cache.records的数量

{"Open_tables", (char*) &show_open_tables, SHOW_FUNC}

注释:【全局变量】 server当前打开的table数量,server维护了一个全局变量table_cache_count

{"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH}

注释:【全局变量】 启动以来打开过的文件的总数

{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}

注释: 【线程变量】 在真正open_table_from_share的过程中,累计计数

{"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS}

注释: 【线程变量】 在真正打开share的时候,累计计数

注: use test的过程:

在use test的过程中,会轮询把test db下的所有表的table_share都创建一遍,即open所有的frm文件,并创建table_share对象,最后close 所有的frm文件。

为了方便调试,写了一个进程监控的程序:pidmon.py

在gdb的时候,可以看到mysqld进程打开的所有文件:

Too many open files:

这里包括了server层的open frm,和innodb层open ibd的时候,当打开的文件超过limit限制,就会报这个错误。

但这个限制牵涉到两个参数:

一个是MySQL配置的open_files_limit

一个是OS层配置的进程的open file limit

下一篇:

flush tables究竟做了什么:close了server层创建的所有的table_share和table。

mysql open table_MySQL open table相关推荐

  1. mysql rename table_Mysql: RENAME TABLE IF EXISTS

    可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试): 问题: This DROP TABLE IF EXISTS works, too bad that R ...

  2. mysql alter table_mysql alter table 修改表命令详细介绍

    MySQL ALTER语法如下: ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...] alter_specification: AD ...

  3. mysql alter table_mysql ALTER TABLE 的用法

    在表格被建立在资料库中后,我们常常会发现,这个表格的结构需要有所改变.常见的改变如下: 加一个栏位 删去一个栏位 改变栏位名称 改变栏位的资料种类 以上列出的改变并不是所有可能的改变.ALTER TA ...

  4. mysql check table_mysql check table

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  5. mysql 清空row_MySQL_TRUNCATE_清空table里的记录

    MySQL_TRUNCATE_清空table里的记录 MySQL TRUNCATE 语法 TRUNCATE [TABLE] tbl_name TRUNCATE TABLE empties a tabl ...

  6. DBD::mysql::db do failed: Table cl_access was locked with a READ lock and can't be updated

    DBD::mysql::db do failed: Table 'acl_access' was locked with a READ lock and can't be updated at /us ...

  7. 运行mysql时,提示Table ‘performance_schema.session_variables’ doesn’t exist

    运行mysql时,提示Table 'performance_schema.session_variables' doesn't exist 解决的方法是: 第一步:在管理员命令中输入: mysql_u ...

  8. mysql返回#1114 – The table ‘xxxx’is full解决方法

    发现执行mysql的 REPLACE INTO 的时候mysql返回 #1114 – The table 'xxxx' is full 这个错误. 以前没有遇到过,于是查找资料解决这个问题.得知是由于 ...

  9. MySQL出现Waiting for table metadata lock的原因以及解决方法

    MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Wa ...

最新文章

  1. string转int 等(转)
  2. c语言计算器实现简单的四则运算.(加,减,乘,除)实验报告,C语言数据结构“简单计算器。”1、简单计算器。请按照四则运算加、减、乘、除、幂(^)和括号的优先关系和惯例,编写计算器程...
  3. 计算机应用基础操作题教学考试,电大教学全国计算机应用基础考试网考内容全部操作题.doc...
  4. Mysql中怎样使用update更新某列的数据减去指定值
  5. tomcat问题记录-线程池引发的问题
  6. SQLServer书写规范梳理
  7. [Java基础]Stream流的收集操作
  8. 斗地主(矩阵快速幂)
  9. idea菜单栏消失如何调整回来
  10. 怎么多次调用c语言dll,c-如何从注入到同一程序的另一个.dll中调用...
  11. java int和String类型之间的相互转换
  12. (45)System Verilog数组乘积运算
  13. 【kibana】kibana node 监控指标 详解
  14. 解决CocosCreator 在微信小游戏中使用Socket.io 报错的问题
  15. 关于同网段内主机之间通信细节
  16. 这道小学六年级的数学题,恕我直言没几个人会做
  17. 浙江学生头戴“金箍”,上课走神自动通知家长
  18. 连接mysql失败怎么办_数据库连接失败有什么原因?怎么解决?
  19. 终于有人把 Docker 讲清楚了,万字长文详解!
  20. 如何使用Xcode的Targets来管理开发和生产版本的构建

热门文章

  1. git 怎么查看合并过来哪些代码_git整理纷乱的历史合并记录
  2. java正则表达式 ppt_Java正则表达式演示
  3. avr uart打印_AVR | 在16x2 LCD上打印HELLO WORLD
  4. 优先级调度算法动态优先级_与优先级调度有关的问题及其解决方案
  5. 漫画:什么是布隆算法?
  6. Java调优:Mybaitis的缓存优化
  7. 【逆强化学习-0】Introduction
  8. Windows系统端口转发
  9. ORACLE中使用递归查询
  10. Nginx-ingress部署及使用