目录
- 一、序言
- 二、InnoDB架构
- 三、InnoDB内存结构
- 1、Buffer Pool (缓冲池)
- 2、Change Buffer
- 3、Log Buffer
- 四、InnoDB磁盘结构
- 1、表空间
- 2、Doublewrite Buffer(双写缓冲区)
- 3、Redo Log
- 4、Undo Log
- 五、结语
一、序言
本节内容为博主根据MySQL 8.0版本官方文档手动翻译过后的最新内容,并加上自己的经验对InnoDB的理解。
二、InnoDB架构
下面这张图是从官方文档上捞过来的架构图,可以看到InnoDB的架构主要分为两部分,一部分是内存结构,还有一部分是磁盘结构。
三、InnoDB内存结构
从上面的架构图中可以看出,InnoDB内存结构主要分为Buffer Pool、Change Buffer和Log Buffer三部分,下面我们具体聊聊这3个部分的作用。
1、Buffer Pool (缓冲池)
Buffer Pool从名字其实就可以看出是一片内存区域,该区域会缓存表和索引数据。通过Buffer Pool可以直接在内存里频繁处理使用到的数据。在专用服务器上,80%的物理内存会被分配到Buffer Pool中。
为了提高大容量读操作的效率,Buffer Pool会被划分为多页(page)来保存行数据。Buffer Pool的实现其实是一个链表,链表上为访问的页数据。
备注:page是一个数据单位,代表InnoDB每次从磁盘读取到内存中的的数据量,每个page可以包含一行或者多行数据。
Buffer Pool会用LRU算法(变体)
去管理链表上的数据,当往Buffer Pool中插入新的page时,最近最少使用的page会被添加到链表的中间。
这种中点插入策略会把链表拆分为两个子链表,如下:
可以看到,链表主要分为两部分:
- 头部是最近被访问的子链表,我们称之为新页(young pages)。
- 尾部是最近很少被访问的子链表,我们称之为旧页(old pages)。
这种LRU
变体算法会将受大量查询影响的page放在new sublist,而old sublist则包含更少使用的page。
当InnoDB从磁盘中读取数据到Buffer Pool中时,首先会将读取到的page插入到两个链表的中间位置(old sublist的头部),访问old sublist的page时,page会被标记为young,该page将会被移到Buffer Pool中的头部(new sublist的头部)。
当有数据库操作时,Buffer Pool中没有被访问到的page会被移到链表的尾部,如果该page依然没有被用到就会被清除掉。
2、Change Buffer
Change Buffer是一种特殊的数据结构,它会缓存对二级索引页的修改,这些修改主要来自于DML语句,比如INSERT
、UPDATE
、DELETE
。
对于不在Buffer Pool中的二级索引页的修改将被缓存到change buffer中,当二级索引页被读取到Buffer Pool中时,这些修改将会被周期性地合并到Buffer Pool中。
3、Log Buffer
Log Buffer是一片内存区域,这片区域会保存写到日志文件的数据。Log Buffer的大小默认为16MB
,里面的数据会周期性的刷新到磁盘中。
Log Buffer越大,支持运行的事务也就越大,大的log buffer可以减少redo log数据频繁刷新到磁盘。如果事务中包含了大量数据行的DML操作,增加Log Buffer的大小可以减少磁盘I/O。
四、InnoDB磁盘结构
InnoDB磁盘结构主要包含表、索引、表空间、Doublwrite Buffer、Redo Log和Undo Logs,下面我们具体讲讲后面几项的作用。
1、表空间
表空间主要分为系统表空间
、File-Per-Table表空间
、General表空间
、Undo表空间
和临时表空间
。
- 系统表空间:针对Double write buffer和Change buffer的一块存储区域。如果表建立在系统表空间内,那么也会包含表和索引的数据。
- File-Per-Table表空间:过去InnoDB都是把表数据存储在系统表空间内,这种方式适用于专门用于数据库处理的机器,而File-Per-Table允许每个表数据都可以存储在自己的表空间数据文件里(.ibd文件)。默认都是用这种方式存储表数据。
- General表空间:共享表空间,可以通过
CREATE TABLESPACE
语法创建共享表空间。 - Undo表空间:该表空间包含undo日志,通过该日志可以撤销事务对聚簇索引数据的最新修改,即我们常说的数据回滚。
- 临时表空间: 除了用于存放临时表数据,还会保存对临时表修改的回滚段。
2、Doublewrite Buffer(双写缓冲区)
双写缓冲区是位于系统表空间内的一块存储区域,InnoDB会在该存储区域完成Buffer Pool中已刷新的page写入。
为什么说叫做双写缓冲区呢?因为数据页在落地数据文件前,首先会往双写缓冲区写入数据,用来保证数据的完整性。
3、Redo Log
Redo log是一种基于磁盘的数据结构,主要用于未完成事务的数据恢复。Redo Log会编码更新表数据的请求,未完成更新数据文件的修改在数据库初始化期间自动重放。
默认情况下,Redo Log在磁盘上分为两个文件:ib_logfile0
和ib_logfile1
,MySQL将会循环写入数据到redo log文件中。
4、Undo Log
Undo log是与单个读写事务相关联的Undo log日志记录的集合,该日志会包含如何撤销事务最新修改的一些信息。
一个事务最多分配4个undo日志文件,每个日志文件对应的操作类型如下:
- 对表的INSERT操作。
- 对表的UPADATE和DELETE操作。
- 对临时表的INSERT操作。
- 对临时表的UPADATE和DELETE操作。
五、结语
本篇文章比较偏概念性,好让大家对InnoDB的内存结构和磁盘结构有个大概的了解,更加详细的内容以及相关MySQL参数设置参考MySQL 8.0官方文档。
下一节我们将具体聊聊MySQL中InnoDB和MyISAM存储引擎的区别。