|||-> file->table_share=share file->ht=db_type //innobase_create_handler创建handler对象|||->file->init() //handler::init()||->//copy share中的key、column信息赋值到TABLE中||->outparam->file->ha_open(TABLE,table_name,mode)|||-> file->table=outparam //handler::ha_open||->ha_innobase::open(table_name)||->ib_table=open_dict_table(table_name,...,)//根据name加载innodb的系统表中的表的元数据||->m_prebuilt=row_create_prebuilt(ib_table,TABLE->S->reclength)//创建prebuit对象在查询数据时的元组结构|->Table_cache::add_used_table //将TABLE对象加入Table_cache中||->el=table->s->cache_element[this->idx] // 获取该表名在该table_cache中的el||->if(!el) // 如果不存在|||->el= new Table_cache_element(table->s) // 创建el对象|||->my_hash_insert(&m_cache, (uchar*)el) // 加入当前table_cache的el的hash链表|||->table->s->cache_element[this->idx]=el // 存到TABLE_SHARE对应的el位置 其他线程访问当前table_cache使用||->el->used_tables.push_front(table) // TABLE对象加入el的used链表||->m_table_count++ |->table_found:|->thd->set_open_tables(table)|->table->init(thd, table_list)流程解释:
1)首先根据thd的thread_id找到对应的tc,然后根据key定位找到tc中缓存的el,如果el的share和TABLE都存在,则直接使用TABLE对象.
2)如果el的share存在,无缓存的TABLE对象,则调用open_table_from_share,根据share构造TABLE对象,并加入used_tables链表.
3)如果el的share不存在,则先调用get_table_share_with_discover根据frm文件构造share对象,然后再构造TABLE对象.
close_table:
我们看下当一个thd一条语句执行完毕之后,对于打开的TABLE对象如何处理
mysql_execute_command|->close_thread_tables||->while (thd->open_tables)||->close_open_tables(thd, &thd->open_tables)||->close_thread_table||->if(!table->needs_reopen())ha_innobase::reset()//reset某些成员变量||->tc->lock();||->if(table->s->has_old_version()||table->needs_reopen())|||->tc->remove_table(table) //TABLE* 从tc缓存中删除|||->intern_close_table(table) //close TABLE->file 释放file对应的内存对象同时free_table_share释放share内存对象||->else|||->tc->release_table(thd, table)//不close TABLE->file|||->table->in_use = nullptr|||->//将TABLE* 指针对象从el->used_tables移除加入el->free_tables链表同时加入tc->m_unused_tables||->tc->unlock()|->MDL_context::release_transactional_locks //释放所有的MDL锁intern_close_table(TABLE *table)|->closefrm(table, free_share=1)|->table->file->ha_close()|->release_table_share(table->s)|->if(!--share->ref_count)//使用share open TABLE才会+1|->if(share->has_old_version())|->my_hash_delete(&table_def_cache, (uchar*) share)|->table_def_free_entry(share)|->free_table_share(share)|->while(ticket=share->m_flush_tickets) |->ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED) // 唤醒其他等待old_version的thread 注:
TABLE_SHARE::m_version在alloc_table_share初始化为refresh_version 在DDL过程中会调用TABLE_SHARE::clear_version()将m_version重置为0
从上面的过程我们可以知道:
TABLE对象已经不仅仅是MySQL Server层的对象了,它是可以具体操作某一个存储引擎的对象,所以TABLE对象作为MySQL层和存储引擎之间的桥梁,可以直接使用TABLE对象的存储引擎的句柄执行各个公共C++ API来操作具体执行动作. 总结:
通过对源码的浅析,我们已经基本了解了MySQL Server层怎样通过一步步获得不同存储引擎表结构的信息,希望对大家理解MySQL Server层对象的缓存有一定的帮助.
推荐阅读
- 转转MySQL机房迁移半小时结束战斗?
- 【科学的温度】ChatGPT被指没“人性”,可能产生哪些危害?
- 欧姆龙是哪个国家的品牌?Laneige兰芝是什么品牌?
- 平山白鹿温泉度假酒店.最近想去平山白鹿温泉,在哪里住一晚。玩个两天。帮忙推荐好点的住宿。
- 火爆的单机游戏排名--全球最火的十大单机游戏?
- 手机充电功率大小有什么区别—华为p30可以用多少w的充电器,别人说的只能接受22.5w的
- 央视网|内娱将被整顿!央视删除Z姓女星的全部内容,疑似与“文盲”有关
- 丁太升|李荣浩的新歌《乌梅子酱》出圈大火,丁太升犀利点评俗不可耐
- 银币|为何大清银币的价值会比一般银元的价值高很多
- 【科学的温度】体育中考调整耐力项目,青少年“阳康”后如何锻炼?
