MySQL中InnoDB存储引擎是如何设计的

介绍

小编给大家分享一下MySQL中InnoDB存储引擎是如何设计的,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!

MySQL中的两个成员binlog和重做日志。然而,这只是MySQL家族里的两个小喽啰,MySQL可以做到高性能高可靠,靠的绝对不只有他们俩。

<强> MySQL里还有什么其他成员呢?

这其中,最底下的存储引擎层(存储引擎),它决定了MySQL会怎样存储数据,怎样读取和写入数据,也在很大程度上决定了MySQL的读写性能和数据可靠性。

对于这么重要的一层能力,MySQL提供了极强的扩展性,你可以定义自己要使用什么样的存储引擎:InnoDB, MyISAM,记忆,CSV,甚至可以自己开发一个存储引擎然后使用它。

通常我们说MySQL高性能高可靠,都是指基于InnoDB存储引擎的MySQL,所以,这一讲,先让我们来看看,除了重做日志,InnoDB里还有哪些成员,他们都有什么能力,承担了什么样的角色,他们之间又是怎么配合的吗?

<>强InnoDB内存架构

InnoDB主要分为两大块:内存和磁盘,让我们先从内存开始。

<强> 1,缓冲池

正如之前提到的,MySQL不会直接去修改磁盘的数据,因为这样做太慢了,MySQL会先改内存,然后记录重做日志,等有空了再刷磁盘,如果内存里没有数据,就去磁盘负载。

而这些数据存放的地方,就是缓冲池。

我们平时开发时,会用复述来做缓存,缓解数据库压力,其实MySQL自己也做了一层类似缓存的东西。

MySQL是以“页”(页)为单位从磁盘读取数据的,缓冲池里的数据也是如此,实际上,缓冲池的页面是一个链表,一个以页为元素的链表。

为什么是链表?因为和缓存一样,它也需要一套淘汰来管理数据。

缓冲池采用基于LRU(最近最少使用)的算法来管理内存。

<强> 2,改变缓冲

上面提到过,如果内存里没有对应“页”的数据,MySQL就会去把数据从磁盘里加载出来,如果每次需要的“页”都不同,或者不是相邻的“页”,那么每次MySQL都要去加载,这样就很慢了。

于是如果MySQL发现你要修改的页,不在内存里,就把你要对页的修改,先记到一个叫改变缓冲区的地方,同时记录重做日志,然后再慢慢把数据负载到内存,负载过来后,再把改变缓冲区里记录的修改,应用到内存(缓冲池)中,这个动作叫做合并,而把内存数据刷到磁盘的动作,叫清洗:

合并:改变缓冲→缓冲池

清洗:缓冲池→磁盘

上面是MySQL官网对改变缓冲区的定义,仔细看的话,你会发现里面提到:改变缓冲区只在操作“二级索引”(二级指标)时才使用,原因是“聚簇索引”(集群索引)必须是“唯一”的,也就意味着每次插入,更新,都需要检查是否已经有相同的字段存在,也就没有必要使用改变缓冲了;另外,“聚簇索引“操作的随机性比较小,通常在相邻的“页”进行操作,比如使用了自增主键的“聚簇索引”,那么插入时就是递增,有序的,不像“二级索引”,访问非常随机。

<强> 3,自适应哈希索引

MySQL索引,不管是在磁盘里,还是被加载到内存后,都是B +树,B +树的查找次数取决于树的深度。你看,数据都已经放到内存了,还不能“一下子”就找到它,还要”几下子”,这空间牺牲的是不是不太值得吗?

尤其是那些频繁被访问的数据,每次过来都要走B +树来查询,这时就会想的到,我用一个指针把数据的位置记录下来不就好了吗?

这就是“自适应哈希索引”(自适应哈希索引)。自适应,顾名思义,MySQL会自动评估使用自适应索引是否值得,如果观察到建立哈希索引可以提升速度,则建立。

<强> 4,日志缓冲区

日志缓冲区里的重做日志,会被刷到磁盘里。

操作系统缓存在内存和磁盘之间,你看到MySQL画了一层叫做操作系统缓存的东西,其实这个不属于InnoDB的能力,而是操作系统为了提升性能,在磁盘前面加的一层高速缓存,这里不展开细讲,感兴趣的同学可以参考下维基百科:页面缓存

<强> InnoDB磁盘架构

磁盘里有什么呢?除了表结构定义和索引,还有一些为了高性能和高可靠而设计的角色,比如重做日志,undo日志,改变缓冲区,以及Doublewrite缓冲区等等。

<强> 1,表空间(表空间)

可以看的到,表空间分为五种:系统表空间;File-Per-Table表空间,一般表空间;撤销表空间,临时表空间。

其中,我们平时创建的表的数据,可以存放到系统表空间,File-Per-Table表空间、表空间三将军者中的任意一个地方,具体取决于你的配置和创建表时的sql语句。

MySQL中InnoDB存储引擎是如何设计的