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已经发生了变化,就关闭,并重新打开。

  • 相关阅读:
    Leetcode 349. Intersection of Two Arrays
    hdu 1016 Prime Ring Problem
    map 树木品种
    油田合并
    函数学习
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 101. Symmetric Tree
    poj 2524 Ubiquitous Religions(宗教信仰)
    pat 1009. 说反话 (20)
  • 原文地址:https://www.cnblogs.com/xpchild/p/3818497.html
Copyright © 2011-2022 走看看