mysql innodb架构分析
文章目录
- 前言
- 一、缓冲池(Buffer Pool)
-
- 1、Buffer Pool 基本概念
- 2、Buffer Pool 预读机制
- 3、Buffer Pool free链
-
- 3.1、 结构与组成
- 3.2、工作流程
- 4、LRU
-
- 4.1、传统LRU
- 4.2、InnoDB中的LRU
- 5、Buffer Pool Flush链
- 6、数据持久化
- 二、Doublewrite Buffer
-
- 1、Doublewrite Buffer结构:
- 2、Doublewrite Buffer的写入过程
- 3、数据恢复
- 三、Redo Log
-
- 1、Redo Log
- 2、Redo Log Buffer
-
- 2.1、Redo Log Buffer触发同步条件
- 2.2 、Redo Log Buffer 刷盘机制
- 四、Undo Log
- 五、Binlog
- 六、Change Buffer
- 总结
前言
数据库的持久化数据,是通过磁盘存储的。那么每次sql检索假如都去磁盘获取,明显性能会比较慢,期间是不是做了很多优化,既能高效的完成sql的检索更新,也能实现数据的持久化,接下来将探讨这样一个过程。
一、缓冲池(Buffer Pool)
1、Buffer Pool 基本概念
缓冲池是主内存中的一个区域,在 InnoDB 访问时缓存表和索引数据。缓冲池允许直接从内存访问频繁使用的数据,从而加快处理速度。
无缓冲池的时候
有缓冲池的时候
一条sql的数据交互如下
假设我们进行数据查询,
1、select * from user where id in (1,2,3);
2、去bufferpool中查看1、2、3 所在的page页是否存在
3、存在,直接返回
4、不存在,根据1、2、3的数据所在的page页,去磁盘加载,加载完后保存到内存,返回
5、select * from user where id in (1);
6、在buffer pool中查询,发现存在,直接返回
磁盘I/O相对内存来说是非常慢的,特别是磁盘的随机读操作,产生的I/O次数更多,引入buffer pool减少了磁盘的I/O,提升了很大一部分性能。
如果是修改数据,修改 Buffer Pool 中对应的数据后,会放入一块特定区域中,由 MySQl 后台线程将这特定区域的数据写入磁盘,完成持久化,这一块特定的区域叫脏链,后面会详细介绍。
对于操作系统来说,当磁盘上的一块数据被读取的时候,很有可能它附近的位置也会马上被读取到,这个就叫做局部性原理。那么这样,我们干脆每次多读取一点,而不是用多少读多少,这样能提升很大一部分性能,同时它也叫做预读取。
buffer pool也参照了这个模式,每次读取的时候,会多加载一些数据到buffer pool中,以空间换取时间,达到快速响应的机制。
2、Buffer Pool 预读机制
学习预读机制,需要先了解数据在mysql中的存储结构
- 表空间(Tablespace):表空间又分为很多的类型,比如系统表空间、通用表空间、独立表空间、临时表空间
- 系统表空间:系统表空间可以有1个或者多个数据文件,默认情况下,在data目录中创建一个名为ibdata1的系统表空间数据文件。系统表空间数据文件的大小和数量由innodb_data_file_path启动选项定义
- 独立文件表空间:独立文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统中的单个数据文件中。
- 临时表空间:在我们的sql中,可能会用到临时表的逻辑,就是在会话中创建一个表供会话使用,会话关闭后,表失效
- 通用表空间:通用表空间是能够为多个表存储数据的共享表空间。但是这个空间可以自己进行维护管理。
每个表空间都是由相同大小的page页来组成的,默认page页的大小为16KB;也可以根据innodb_page_size来设定页的大小。page又不是直接放在表空间的,而是会用其他的一些数据结构来封装,目的是为了提高数据磁盘的扩展性,管理空间分配与性能以及利于磁盘的分配,于是诞生了segement、extent。
- 段(Segment):Segment 由一个或多个 Extent 组成,在 Segment 中不要求区与区之间是相邻的。段是数据库中的分配单位,不同类型的数据库对象以不同的段形式存在。当创建数据表、索引的时候,就会相应创建对应的段,比如创建一张表时会创建一个表段,创建一个索引时会创建一个索引段。
- 区(Extent):64个相邻的 Page 称为一个 Extent。默认情况下 Extent 大小为 16kb * 64 = 1024kb = 1MB。
- 页(Page):为 InnoDB 存储引擎磁盘管理的最小单元,每页大小默认为 16kb。
- 行(Row):数据行,存储一条数据的基本单位
由此可以得出存储结构图
InnoDB 使用两种预读算法来减少磁盘I/O,提高系统性能,默认采用线性预读:
- 线性预读 linear read-ahead:线性预读是MySQL InnoDB存储引擎的一种优化技术,当顺序访问一个区里的多个数据页时,如果访问的数据页数量超过了配置参数innodb_read_ahead_threshold的阈值(默认值为56),则触发线性预读机制
SELECT @@innodb_read_ahead_threshold; -- 默认为56 可以配置0-64,因为一个extent为64个页
- 随机预读 random read-ahead:如果在缓冲池中发现来自同一区段的13个连续页面,则InnoDB会异步预取这些页面。随机预读能够尽可能地预先加载下一个可能需要的数据块,即使这些数据块不是顺序存储的