持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 10 天,点击查看活动详情
哈喽,大家好,我是二毛。
在上篇文章 面试官:什么是 BufferPool ?,我大概介绍了 BufferPool 的概念和出现原因。
那么你知道一条 SQL 在 BufferPool 的执行流程是怎么样的吗?
先要弄懂这个问题,我们要先知道 BufferPool 内部的一个大概组成。
内部组成
不BB,先上图:
既然 BufferPool 是作为缓存加速 Mysql 的读写效率,那么最容易想到的就是它一定会有 数据的缓存和索引缓存,对应图的就是 data page 数据页和 index page 索引页。
除此之外,还有多种类型,如insert buffer插入缓存、lock info、自适应哈希索引、数据字典信息等。这些并不影响我们对本问题的理解,先不做深入探讨。
执行 SQL 的流程
读情况
执行一条 SQL: select * from user where id = 1,那么SQL执行与Buffer Pool的交互大体如下图:
即:
- 看查找的数据对应的数据页是否在内存中。
- 如果 BufferPool 中能够找到,那么直接返回。
- BufferPool 中未找到,则需要将磁盘id=1这一页数据加载到 BufferPool 内存中。最后返回。
题外话:MySQL是如何知道数据在哪个缓存页的呢?
其实对于每个缓存页,都会有一个描述信息,这个描述信息大体可以认为是用来描述这个缓存页的。 比如包含如下的一些东西:数据页所属的表空间、数据页的编号、缓存页在Buffer Pool中的地址等等。如下图:
写情况
执行一条 SQL: update user set name = lisi where id = 1 -----修改之前name = zhangsan,那么SQL执行与Buffer Pool的交互大体如下图:
如上图,对于写操作,如果要修改的行所在的数据页在内存中,则修改后返回对应的结果。如果不在的话,则会从磁盘里将该行所对应的数据页读到内存中再进行修改。【注意:此时修改的数据还未持久化到磁盘中,此时磁盘数据与内存中的数据可能不一致】
通过上面Buffer Pool与读操作、写操作交互的分析,我们应该能猜到为什么SQL执行不慢了吧,因为MySQL内部有一个缓冲池,很大程度减少了磁盘 I/O 带来的开销,将数据存放于内存中,我们读取数据,操作数据都是在内存中完成之后,不需要每次从磁盘去取,并且操作完数据直接返回,内存操作比磁盘快得多。
但是这其中也有一个问题:
因为修改的数据都是在内存中修改,并没有持久化到磁盘中,这样容易丢失数据,在Buffer Pool中已经修改但还没刷新到磁盘的数据,称为脏页。MySQL必然会有后台线程会去将Buffer Pool中的这些脏页刷新到磁盘中进行持久化,不然就很容易丢失数据了。
最后
本文主要跟大家介绍了 BufferPool 的内部结构、读操作的执行流程、写操作的执行流程,希望对大家有帮助。
我是二毛,我们下期再见~