zoukankan      html  css  js  c++  java
  • MySQL open table

    MySQL open table

     

    背景:
        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++;

    要点:

    1. MySQL server层维护了一个全局的table definition cache即table_def_cache,所以一个table_share只会创建一次,后续进行共享。
    2. 初始化table_share的过程中,调用文件系统打开frm文件,初始化完成后,关闭frm文件。
    3. 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

     
  • 相关阅读:
    BZOJ 3506 机械排序臂 splay
    BZOJ 2843 LCT
    BZOJ 3669 魔法森林
    BZOJ 2049 LCT
    BZOJ 3223 文艺平衡树 splay
    BZOJ 1433 假期的宿舍 二分图匹配
    BZOJ 1051 受欢迎的牛 强连通块
    BZOJ 1503 郁闷的出纳员 treap
    BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp
    BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
  • 原文地址:https://www.cnblogs.com/FlyAway2013/p/5485139.html
Copyright © 2011-2022 走看看