zoukankan      html  css  js  c++  java
  • 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已经发生了变化,就关闭,并重新打开。

  • 相关阅读:
    python获取前几天的时间
    协程
    python实现进制之间的转换
    爬虫学习博客
    python 将base64字符串还原为图片
    python进行md5加密
    初始Hibernate4
    Linux安装tomcat
    centOS7安装jdk
    centOS7安装mysql
  • 原文地址:https://www.cnblogs.com/xpchild/p/3818497.html
Copyright © 2011-2022 走看看