最近一个和file_system有关的问题,因此将这部分数据结构和重要的函数简单看了一下,好在数据结构不多,成员变量也不多。但是这部分的知识和IO子系统联系太紧密了,因为IO子系统不熟,所以难免有错误。但是也为学习IO子系统做了一层铺垫。并且不管错误与否必须要记录一下否则很容易忘记,现记录如下(包含代码,文章稍显混乱),代码来自8.0.23。
仅供参考。
一、前言
在我们数据库启动的时候,实际上很多表都是没有打开的,当然除了一些redo/undo等系统空间会常驻打开,其他的用户的innodb表示没有打开,当遇到真正的IO操作后才会打开文件,这些文件会存在于file_system中,主要包含的就是fil_space_t结构,一个fil_space_t对于单表或者分区表的一个分区来讲就对应一个fil_node_t,但是对于redo或者undo这些来讲一个fil_space_t对应了多个file_node_t,因为有多个相关文件,真正的iohandler存储在fil_node_t上。在5.7中打开的文件都整体存在于一个file_system下,但是最近遇到了一个问题,稍微看了下8.0发现做了拆分,将一个file_system查分为69个(8.0.19是65个)这个是个硬编码。这样如果我们需要打开文件或者关闭文件那么拆分后锁的代价就更小了,其中每一个拆分出来的结构叫做shard(内部结构叫做Fil_shard)。
二、总体示意图
注意这里我们只讨论一个fil_space_t对应一个fil_node_t的情况,也就是普通表(分区表的分区),这往往也是和用户关系较大的。
三、file_system(Fil_system)的重点变量
图中包含另一些重点的数据结构,其中file_system中包含:
m_shards:这是一个vecoter数组,包含了69个shard。m_max_n_open:这个是我们的参数Innodb_open_files设置的值。m_max_assigned_id:是我们当前分配的最大的space_id。
四、shard的重点变量
m_id:当前shard的序号,从0开始m_spaces:一个stdmap结构,在数据库初始化的时候就建立好了,其主要是space_id和fil_space_t做的一个map结构m_names:一个stdmap结构,在数据库初始化的时候就建立好了,其主要是space_name和fil_space_t做的一个map结构
m_spaces和m_names变量的初始化可以查看函数Fil_shard::space_add,如下:
voidFil_shard::space_add(fil_space_t*space){ut_ad(mutex_owned());{autoit=m_spaces.insert(Spaces::value_type(space-id,space));ut_a(it.second);}{autoname=space-name;autoit=m_names.insert(Names::value_type(name,space));ut_a(it.second);}}
我们通常在进行物理IO的时候需要打开文件,这个时候拿到的一般为page的space_id,这样通过Fil_shard:
et_space_by_id就快速拿了fil_space_t的结构,而不用去遍历链表。
但是需要注意的一点是,我们首先还需要判定是的这个space_id到底到哪个shard上建立或者到哪个shard上查找,是需要定位到相关的shard上的,这个是通过space_id取余来做到的,函数Fil_system::shard_by_id(FIL_system就是我们的file_system的数据结构)函数完成这个功能,计算取余如下:
Fil_shard*shard_by_id(space_id_tspace_id)constMY_ATTRIBUTE((warn_unused_result)){#ifndefUNIV_HOTBACKUPif(space_id==dict_sys_t::s_log_space_first_id){returnm_shards[REDO_SHARD];}elseif(fsp_is_undo_tablespace(space_id)){constsize_tlimit=space_id%UNDO_SHARDS;returnm_shards[UNDO_SHARDS_START+limit];}ut_ad(m_shards.size()==MAX_SHARDS);returnm_shards[space_id%UNDO_SHARDS_START];//取余,将各个space分布到不同的shard上#else/*!UNIV_HOTBACKUP*/ut_ad(m_shards.size()==1);returnm_shards[0];#endif/*!UNIV_HOTBACKUP*/}
因为我们的undo,redo会独占末尾的几个shard,因此这里用了宏来减去了这部分然后取余,相关宏定义如下。
/**Maximumnumberofshardssupported.*/staticconstsize_tMAX_SHARDS=69;//69个shard/**Theredologisinitsownshard.*/staticconstsize_tREDO_SHARD=MAX_SHARDS-1;//末尾第1个为redo的shard/**Numberofundoshardstoreserve.*/staticconstsize_tUNDO_SHARDS=4;//倒数第2到第5为undo的shard/**TheUNDOlogshavetheirownshards(4).*/staticconstsize_tUNDO_SHARDS_START=REDO_SHARD-UNDO_SHARDS;#else/*!UNIV_HOTBACKUP*/
m_LRU:这个玩意是一个最重要的数据结构了,如果一个文件刚刚打开或者io