缓冲池Buffer Pool:
缓冲池是innodb内存结构缓冲区中的核心部分,在服务启动的时候服务器会向操作系统申请一块大小为128MB的内存空间,所有对数据库中数据的增删查改操作均在缓冲池bufferPool中完成,并且缓冲区中其他组件的描述信息也都存储在缓冲池中
Buffer Pool结构
缓冲池管理的最小单位是页,多个页通过一个chunk块管理,多个chunk块通过一个instance管理,呈现层级结构,如图所示
内存中对页的组织:
页从磁盘被加载到内存中,也需要对页进行管理,此时不能再使用页中的next_record管理内存页了,因为next_record是磁盘地址并且被加载到内存的页可能是不连续的
在不修改页的前提下innodb引入了控制块的概念用来管理内存页,简单得说就是每一个控制块有唯一对应得内存页,并且所有控制块被一个带头双向链表关联,通过遍历控制块链表就能遍历所有内存页 如图所示
chunk块作用
chunk 是一块连续的大内存区域,InnoDB 可以更灵活地管理不同大小的内存块,避免内存碎片。而直接管理 page 的地址,可能会导致更多的内存碎片
chunk类似于一个内存池的机制,以固定大块的空间为单位分配与释放内存空间,可以有效的降低空间申请和释放的次数,如果instance直接管理page,那么就需要page大小的堆空间频繁申请与释放,时间成本就上去了,不妨一次申请一个chunk块大小的空间(一般大小为页空间的整数倍),一段时间内就不需要申请释放了,一定程度上提高了性能
通过 chunk 管理内存,减少了对大量 page 的直接操作,简化了整体的内存管理流程。内存管理模块可以专注于管理少量的 chunk,而不是成千上万个 page
缓冲池中对页的申请和释放都是以chunk块为单位的
chunk块初始化
当缓冲区完成初始化后会把每个数据页所占用的内存空间和对应的控制块提前分配到,只不过此时控制块和数据页都是空的(未使用)
chunk块中左半部分为控制块信息,右半部分为页信息
控制块信息从左至右初始化
页信息从右至左初始化
第一个控制块管理第一个页,第二个控制块管理第二个页,依次类推
页管理
缓冲池中采用三个链表管理不同状态的页,三个链表分别是Free List,LRU List,Flush List
页状态分为空闲页Free,干净页Clean,脏页Dirty
顾名思义,空闲页是还没有被使用的页空间,干净页是已经有真实数据但数据未发生修改的页空间,脏页即已经发生数据修改的页空间
当读取指定页的数据时,会从Free List中取出一个空闲页,将目标页的数据拷贝到所获得的空闲页中,并把该页标记为干净页挂入LRU List,如果之后该页的数据发生了修改操作,会把该页标记为脏页挂入Flush List中,但不一定会从LRU中马上删除
LRU List采用了LRU算法对干净页和脏页进行统一管理,当达到阈值大小时,会率先淘汰掉长时间未使用的页
对于Flush List,服务器会在合适的时机对链表中的页进行统一的刷盘操作,刷盘结束后将对应的页空间归置,放入Free List中
变更缓冲区Change Buffer:
普通情况下对一个文件中的数据修改分为3步:
1、从磁盘中找到目标位置
2、将文件加载到内存中进行修改
3、将最新数据刷新到磁盘
作为一个数据库,修改操作肯定是比较频繁的,如果每一次修改都进行一次上述操作,那么势必会严重降低性能,因为IO的次数太多了,有效的解决办法就是将修改操作先保存到一个缓冲区中,等达到阈值时再IO,一次性批量修改,大幅度降低IO次数,这就是Change Buffer的作用
触发刷新的时机:
读取对应的数据页
系统空闲时
系统正常关闭
change buffer写满
redo log写满
修改操作存入变更缓冲区是由条件的
必须是针对二级索引数据的修改,否则不会进入变更缓冲区,因此建议为每一张表建立二级索引,并且修改时筛选条件为二级索引行
不能是主键索引的原因:主键是不可重复的,如果同一时刻新增2条主键值都为1的数据,在真正修改的时候就会发生主键冲突
自适应哈希Adaptive Hash:
根据InnoDB内部的监控机制,如果监控到某些查询通过建⽴哈希索引可以提⾼性能,则⾃动对这个⻚创建哈希索引,这个过程称为⾃适应,所以叫⾃适应哈希索引。
如果表完全放在内存中,则哈希索引可以通过直接查找任何元素来加快查询速度,为频繁使⽤的查询条件和对应的数据⻚建⽴映射关系,从⽽提升内存级别的查询效率
InnoDB存储引擎的数据存储于B+树中,B+树通常只有3到5层,但从根节点到叶节点的寻路涉及到
多层⻚⾯内记录的⽐较,即使所有路径上的⻚⾯都在内存中,也⾮常消耗CPU的资源
InnoDB对寻路的开销进⾏了优化,⽐如寻路结束后将cursor缓存起来⽅便下次查询复⽤;尽可能
的避免单词寻路开销,Adaptive hash index(AHI)便是为此⽽设计
日志缓冲区Log Buffer:
MySQL在运行过程中会产生大量需要落盘的日志,产生一条写一条肯定是不合理的,通过日志缓冲区将批量的日志统一落盘减少IO次数提高性能