Innodb加载数据字典 && flush tables

测试了两个case,属于之前blog的遗留问题:

  1.   innodb如何加载数据字典
  2.   flush tables都做了什么操作

 

先来看下innodb加载数据字典:

  首次使用:select * from tt;

 

1. 创建handler对象

函数调用栈:
  open_binary_frm
    get_new_handler
      innobase_create_handler
        ha_innobase::ha_innobase

  根据单实例 handlerton + table_share两个参数,创建了handler对象,赋值table->file。server层对innodb的操作,都通过这个接口完成。

 

2. open innobase_share

  innobase_share是innodb层对某张表的定义,全局共享结构, 受 innobase_share_mutex保护。

  innobase_open_tables hash表保存着所有的INNOBASE_SHARE。

  这里完成初始化一个innobase_share结构。


3. 加载数据字典:

  初始化innodb_share中的dict_table_t

步骤:
  mutex_enter(&(dict_sys->mutex));
    dict_sys_t:整个系统的数据字典, 全局的 dict_sys_t* dict_sys;
      包括:hash_table_t* table_hash; /*!< hash table of the tables, based
      包括:UT_LIST_BASE_NODE_T(dict_table_t) table_LRU; /*!< LRU list of tables */

  dict_table_get
  dict_table_get_low
    存在: dict_table_check_if_in_cache_low: 从hash表中取出,并更新lru链表。
    不存在:dict_load_table

1. load 表定义
2. load columns
3. load index
4. load foreign key

注:数组字典使用了两个结构存储,一个hash方便查询, 一个是lru链表,用于缓存的置换。

 

flush tables

reload_acl_and_cache:
  1. 清空query_cache:使用structure_guard_mutex锁。
  2. close_cached_tables:关闭没有使用的。使用LOCK_open锁进行保护。  
  3. 递增:refresh_version

   free_cache_entry: free掉 table_cache中的table
    inter_close_table: 清空 io_cache
    closefrm:

  1. 关闭handler
  2. free innobase_share
  3. 释放table_share: 从table_def_cache上删除。

记录binlog:

  flush talbes记录了statement的binlog。

 

flush tables with read lock 

如果使用了flush tables with read lock:会flush table并获取全局锁, 类似于set read_only=1;

    global read lock:使用mdl锁的架构实现。一共获取了两个锁:

    1. m_mdl_global_shared_lock: 全局范围的共享锁

      mdl_request.init(MDL_key::GLOBAL, "", "", MDL_SHARED, MDL_EXPLICIT);

      所有的ddl/dml都会被阻塞。

    2. m_mdl_blocks_commits_lock:阻塞commit的排它锁

      mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT);

      所有有更新事务的commit都会阻塞,因为commit会写数据到binlog中。

mdl锁的不兼容情况,都是使用排队的阻塞模式,所以,flush tables with read lock经常会被大事务所阻塞,线上慎用。 

 

结论:
  对于一个表, flush_tables一共关闭了 table, table_share, handler, innobase_share. 只保留了dict_table_t数据字典。
  flush tables不关闭正在使用的,当table再次使用的时候,发现version已经发生了变化,就关闭,并重新打开。

posted @ 2014-07-01 15:48  xpchild  阅读(612)  评论(0编辑  收藏  举报