简介
存储引擎是基于表的,不是基于数据库。这一点在开始学习之前,我们要有个概念。InnoDB存储引擎是支持事务,当初的世界目标即使为了在线事务处理,特点有支持行锁,外键,默认读取数据无锁,从mysql5.58版本之后 InnoDB存储引擎成为mysql数据库表的,默认存储引擎。InnoDB存储引擎使用MVC
C来实现多版本并发控制,并且支持4种隔离级别。默认是可重复读 也就是PR
。针对可重复读出现的幻读现象,InnoDB存储引擎提供了间隙锁来避免幻读。InnoDB存储引擎采取使用聚集的方式来存储,每张表的存储顺序都是按照主键的顺序来存储,如果没有主键,那么会使用ROWID
作为主键来存储。
InnoDB存储引擎架构
先撇开架构不谈,在现实社会,称得上引擎的比如雅马哈发动机。发动机的气缸数越多,曲轴转动越均匀,振动也就越小。加速也就越明显,多气缸就仿佛多线程
运行,喷油点火产生动力的过程,可以想象为从内存
中读取数据之后处理,直接从油管里取汽油,这个过程耗时,而且不安全不是,总要经过一个油管把汽油流经发动机让其燃烧之后产生动力。在计算机也是在cpu内存直接也需要有高速缓存来平衡两者,这个可以理解为是个缓存
。
上面就是InnoDB存储引擎的架构实现,现在我来细细分析其工作的后台线程,及内存的处理
后台线程
- Master线程
主要处理吧引擎内存缓存区域的数据持久化到磁盘,保证数据一致性,合并插入缓存,undo页进行回收。
- IO线程
主要处理读写的IO请求的
- Purge线程
用来回收事务提交之后,已经使用的undo页
- Page Cleaner 线程
用于处理脏页刷新功能
引擎内存
也就是图中那个绿色的框框,基于磁盘的存储,把数据记录按照页得到形式存放在磁盘。为了平衡访存速度,InnoDB存储引擎提供了内存缓存池来提高数据库的访问效率,对于读取来说,把文件系统的数据库记录读取之后存放到内存。针对写入的处理,首先修改放在缓存池之内,隔一段时间把数据刷到磁盘。肯定不是每次变更就会把数据刷到磁盘,和Lucene的索引段提交类似,也有一个提交点的概念,只不过InnoDB存储引擎中使用的是CheckPoint的机制,都是大同小异的东西。
InnoDB存储引擎提供如这么多的内存缓存,用于处理各种各样的数据,提到缓存就避免不了有缓存的淘汰策略,在这里使用也是LRU淘汰策略。不过InnoDB存储引擎在LRU列表增加了一个中点的概念。就是新进入的页不是直接晋升到头部,而是挡在中间的位置。默认放在LRU列表的5/8
的位置,使用midpoint inertion strategy
。在《MySQL技术内幕InnoDB存储引擎》一书中指出了LRU List
、Free List
、Flush List
看书上长篇大论讲了什么如何查看对应的区域大小,以及脏页数目,还有就是一系列的设置参数,对于DBA而言这部分配置是很关键的,对我我们开发而言是要理解为什么要有这3个数据结构,从磁盘加载数据之后,单独使用LRU用来管理缓存不也可以嘛,也是可以实现平衡访存的啊,我理解为这个3个数据结构就是个3级缓存,联想到了IOC的三级缓存,哈哈哈和这个可一毛钱关系没有。
MySQL实例启动之后首先会预先从磁盘加载一些数据文件或者索引文件放到free List,lru List的话由于刚启动所以没有数据,Flush List呢由于没有更新修改操作,所以开始时候也是空的,随着访问的增加,如果读取数据是freeList中有的,就会从freeList中添加到Lru的中点位置。如果在LRU的页被更新之后,同步到Flush List。最后达到checkPoint之后,把脏页刷新到磁盘;
缓存CheckPoint
可以理解为一个保存点。在ES的文案可以被检索的过程,就有保存点的概念,在这里也是类似的东西。每当发生更新修改操作之后,直接去持久化磁盘,在性能上这简直是噩梦,所以一些系统在设计上异步刷新磁盘是不错的方案;保存点的好处可以缩短数据恢复时间,当有限的缓存进行页置换,InnoDB存储引擎提供了俩种保存机制,
,在数据库退出的时候把内存中的数据刷新到磁盘,还有一类针对脏页,flush列表 之类的局部刷新到磁盘。
InnoDB存储引擎特性
Insert Buffer
主要是为了应对非聚簇索引的插入不是顺序二带来的插入性能下降,针对聚簇索引来说,安装自增的主键顺序插入即可。没有随机访问的性能消耗,在插入非聚簇索引的时候首先回去判断当前的索引页在内存中存在与否,在的话直接插入,不在的话先放在 Insert Buffer之内,会在 Insert Buffer满了之后的条件下去把 Insert Buffer和内存中的索引页关联。所有 Insert Buffer存放的都是非聚簇索引,也不是唯一索引;
自适应hash索引
知道hash用于访问,速度是非常快的,时间复杂度可以达到(O1),然而B+树的检索 则会取决于树的高度,在实际环境一般一颗B+树的高度3~4层,所以会访问3-4次才可以拿到叶子节点。InnoDB存储引擎使用缓存池来实现这个自适应的hash索引。InnoDB存储引擎会根据对访问非聚簇索引的频率和连续访问模式超过100次来为热点索引添加缓存。你可以把这个理解为了hashMap。
总结
主要赘述了一番InnoDB存储引擎的架构,以及所支持的一些特性,已经针对cpu访问和磁盘之间的提效的工作,还有就是简单叙说了下InnoDB存储引擎的内存缓存模块,比较新颖的点在于在InnoDB存储引擎的LRU策略中引入了中点的位置,这是InnoDB存储引擎考虑数据库访问。就算是第一次加入其中的记录,也可以是使用的很少,在InnoDB存储引擎总是把频繁访问的放在LRU缓存的头部,这样会避免热点数据的过度淘汰。