三大特性
双写机制
MySQL写数据页时,会写两遍到磁盘上,第一遍是写到doublewrite buffer,第二遍是写到真正的数据文件中。如果发生了极端情况(断电),InnoDB再次启动后,发现了一个页数据已经损坏,那么此时就可以从doublewrite buffer中进行数据恢复
Buffer Pool
自适应Hash索引
InnoDB存储引擎内部自己去监控索引表,如果监控到某个索引值经常用,那么就认为是热数据,然后内部自己创建一个hash索引。效率优于B+树索引的3到4次的IO
表空间
概念
表空间是一个<b><font color="#e74f4c">抽象的概念,系统表空间对应一个或多个实际文件</font></b>;独立表空间对应一个名为表名.ibd的实际文件表空间中的每一个页都对应着一个页号(FIL_PAGE_OFFSET),这个页号由4个字节组成,也就是32个比特位,所以<b><font color="#e74f4c">一个表空间最多可以拥有2³²个页</font></b>,如果按照页的默认大小16KB来算,<b><font color="#e74f4c">一个表空间最多支持64TB的数据</font></b>
分类
独立表空间
既可以在数据目录,也可以独立于数据目录之外,存储单张表的索引和数据文件,以ibd形式,不可以跨库
系统表空间
在数据目录中,存储多张表的索引和数据文件,以ibdata1,2,3的形式,可以跨多个数据库使用
整个MySQL进程只有一个系统表空间,记录系统信息的页面,所以会比独立表空间多出一些记录这些信息的页面,相当于是表空间之首,所以它的表空间 ID(Space ID)是0
双写缓冲区
在InnoDB将页写到InnoDB数据文件的正确位置之前,InnoDB将页从缓冲池写到该区域(双写缓冲区)类似于做个数据备份
系统表空间的<font color="#a66a30"><b>extent 1和extent 2</b></font>这两个区,也就是页号从<b><font color="#a66a30">64~191这128个页面</font></b>被称为Doublewrite buffer,也就是<b><font color="#e74f4c">双写缓冲区</font></b>
InnoDB的页大小一般是16KB,而操作系统写文件是以4KB作为单位的,系统写磁盘无法保证页的原子性
与redolog的比较
<b><font color="#e74f4c">redolog</font></b>:恢复数据<b><font color="#f1ac6a">需要原数据页是完整</font></b>的,redolog不包含数据页丢失的原数据<br><b><font color="#e74f4c">双写缓冲区</font></b>:在数据页被破坏时,用整个双写缓冲区的数据页替换被损坏的数据页<br>
InnoDB数据字典
元数据,记录表空间信息。例如某个表属于哪个表空间,有多少列,多少字段,文件路径等
Buffer Pool
概念 | 结构<br>
InnoDB为了缓存磁盘中的页,在MySQL启动时就向操作系统申请了一片连续的内存,叫做Buffer Pool,<b><font color="#e74f4c">默认只有8M</font></b>大小,<b><font color="#e74f4c">bp大于1G可设置多个独立pool</font></b>,支持多线程并发
InnoDB为<b><font color="#e74f4c">每一个缓存页创建一控制块</font></b>,包括该页所属的表空间编号、页号、缓存页在Buffer Pool中的地址、链表节点信息、一些锁信息以及LSN信息等。控制块和缓存页是一一对应的,它们都被存放到 Buffer Pool 中,其中控制块被存放到 Buffer Pool 的前边,缓存页被存放到 Buffer Pool 后边
主要作用
数据都是以页的形式存放在表空间中,即存储在磁盘上的。但磁盘速度慢,当需要访问某个页的数据时,会把完整的页的数据全部加载到内存中,读写访问后并不把该页对应的内存空间释放掉,而是将其缓存起来,这样将来有请求再次访问该页面时,就可以省去磁盘IO的开销了
缓存页的哈希处理
用<b><font color="#7985ec">表空间号</font></b> + <b><font color="#7985ec">页号</font></b>作为key,缓存页控制块作为value创建一个哈希表,用于判断该页在不在Buffer Pool中
free链表
空闲的缓存页对应的控制块作为一个节点放到一个链表中,这个链表也可以被称作free链表(或者说空闲链表)
每当需要从磁盘中加载一个页到Buffer Pool中时,就从free链表中取一个空闲的缓存页,并且把该缓存页对应的控制块的信息填上(就是该页所在的表空间、页号之类的信息),然后把该缓存页对应的free链表节点从链表中移除,表示该缓存页已经被使用了
flush链表
存储脏页的链表,修改了Buffer Pool中某个缓存页的数据,那它就和磁盘上的页不一致了,这样的缓存页也被称为脏页
LRU(Least Recently Used)链表
当Buffer Pool中不再有空闲的缓存页时,此链表是按照最近最少使用的原则去淘汰缓存页的。只要使用到某个缓存页,就把该缓存页调整到LRU链表的头部,这样LRU链表尾部就是最近最少使用的缓存页
预读
预先加载后续页数据到bufferpool
线性预读
顺序访问当前区56(默认)页,自动异步加载下一个区全部数据页
随机预读
缓存了某个区的13个连续的页面(不限顺序读取),都会异步读取本区中所有其他的页面到Buffer Pool
change buffer
作用:在进行DML(写)操作(insert/update/delete)时,如果请求的是 辅助索引(非唯一键索引)没有在缓冲池 中时,并不会立刻将磁盘页加载到缓冲池,而是在Change Buffer记录缓冲变更,等未来数据被读取时,再将数据合并恢复到Buffer Pool中