class Table_cache
{// 缓存TABLE对象 一个Table_cache包含N个不同表名的TABLE对象
HASH m_cache; // The hash of Table_cache_element objects,Table_cache_element::share::table_cache_ke作为hash的key
TABLE *m_unused_tables; // 所有unused的TABLE对象
};
class Table_cache_manager
{
Table_cache m_table_cache[MAX_TABLE_CACHES]; // table_cache对象数组
}
extern Table_cache_manager table_cache_manager; // table_cache全局管理对象
HASH table_def_cache // 缓存TABLE_SHARE的hash表
table_cache的精简架构图如下:
文章插图
一个thread怎样获得缓存的TABLE* 对象:
【浅析MySQL的Table_cache实现】1)根据thread_id%table_cache_instances 获得tc对象,假设为tc1
2)根据key找到对应的el对象,假设为el1
3)获得el1中free_tables的TABLE* 对象
如果已经创建了一个TABLE*对象,那怎样快速知道一个TABLE* 是属于哪个el的呢而加入到对应的used_tables链表中呢?
TABLE_SHARE存在一个el*的s数组,数组的大小为table_cache_instances个数,如下图:
文章插图
假设thread获得的为tc1和el1,那么cache_element[1]存储的为tc1->el1对象.
el= table->s->cache_element[table_cache_manager.cache_index(thd->id)];
- open_table和close_table
接下来看MySQLServer层在open表的过程中,加载表结构.frm文件,转换TABLE对象的主要步骤.
open_table
|->get_table_def_key //库名.表名得到对应的key
|->retry_share:
|->Table_cache *tc = table_cache_manager::get_cache(thd)
|//首先根据thd的m_thread_id%table_cache_instances 获取table_cache_manager.m_table_cache[i]
|->table = tc->get_table(thd, key, key_length, &share)
||->el_it = tc->m_cache.find(key_str) //一个key对应一个el 一个el对应一个TABLE_SHARE* N个TABLE*
||->if(el_it == m_cache.end()) return NULL
||->*share = el->share
||->if((table = el->free_tables.front()))//从el的free_tables链表获取TABLE*对象
|||->el->free_tables.remove(table)
|||->el->used_tables.push_front(table) //close_thread时候会将table从el的used_tables移除,加入free_tables
||->return table
|->get_table_share_with_discover
||->get_table_share
||->my_hash_search_using_hash_value从table_def_cache中HASH查找TABLE_SHARE
||->alloc_table_share 新建share变量赋值share的frm路径信息
||->my_hash_insert //share插入hash表table_def_cache中
||->open_table_def
| | |->open_binary_frm //读取.frm文件赋值engine类型、KEY、FIELD信息
| | |->legacy_db_type= (enum legacy_db_type) (uint) *(head+3);//获得engine类型
| | |->share->db_plugin= ha_lock_engine //根据engine类型获得plugin对象 初始化在innobase_init中完成
| |->// 若table_def_cache记录超过table_def_size 则从hash删除oldest_unused_share
|->share_found:
|->if (!(flags & MYSQL_OPEN_IGNORE_FLUSH))
| |->if (share->has_old_version())
| |->release_table_share(share) // 如果TABLE_SHARE没有引用 则从table_def_cache中删除
| |->tdc_wait_for_old_version(lock_wait_timeout)
| | |->TABLE_SHARE::wait_for_old_version
| | |->m_flush_tickets.push_front(&ticket)// 增加ticket到SHARE的m_flush_tickets链表中
| | |->thd->mdl_context->m_wait.timed_wait(thd,wait) // MDL_wait::timed_wait等待其他线程唤醒
| |->goto retry_share // 唤醒之后再次获取TABLE_SHARE
|->open_table_from_share
||->outparam->file=get_new_handler(share->db_type())
|||->file= db_type->create(db_type, share, alloc)
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 转转MySQL机房迁移半小时结束战斗?
- 【科学的温度】ChatGPT被指没“人性”,可能产生哪些危害?
- 欧姆龙是哪个国家的品牌?Laneige兰芝是什么品牌?
- 平山白鹿温泉度假酒店.最近想去平山白鹿温泉,在哪里住一晚。玩个两天。帮忙推荐好点的住宿。
- 火爆的单机游戏排名--全球最火的十大单机游戏?
- 手机充电功率大小有什么区别—华为p30可以用多少w的充电器,别人说的只能接受22.5w的
- 央视网|内娱将被整顿!央视删除Z姓女星的全部内容,疑似与“文盲”有关
- 丁太升|李荣浩的新歌《乌梅子酱》出圈大火,丁太升犀利点评俗不可耐
- 银币|为何大清银币的价值会比一般银元的价值高很多
- 【科学的温度】体育中考调整耐力项目,青少年“阳康”后如何锻炼?