缓冲池 Buffer Pool
mysql它的数据也存储在磁盘上,为什么可以达到毫秒级的响应呢?或者为什么速度这么快呢?
1.Mysql 的底层是文件系统,查询数据是需要 IO 的,但是我们每次查询数据感觉没有那么慢,原因是数据库中有一层 Buffer Pool。
2.缓冲池,简单来说就是一块内存区域。它存在的原因之一是为了避免每次都去访问磁盘,把最常访问的数据放在缓存里,提高数据的访问速度。
还有就是得益于预读机制:
什么是预读机制?
作用就是尽可能减少磁盘的 IO,它是 Innodb 通过在缓冲池中提前读取多个数据页来优化 I/O 的一种方式。因为磁盘读写的时候,是按照页的方式来读取的(你可以理解为固定大小的数据,例如一页数据为 16K),每次至少读入一页的数据,如果下次读取的数据就在页中,就不用再去磁盘上读取了,从而减少了磁盘 I/O
比如: select * from user where id = 10;
这个时候用户只看到了一条数据,但是mysql其实读取了一页数据,这一页数据有多少条呢?取决于这一条数据多大,每次读取一页数据16KB。
虽然只展示了一条数据,但是 id = 11 id =12 id =9 等等这附近的数据都已经读取出来了。
将不展示的数据放入到缓冲池里面去(其实就是一块内存),当下一次再读取的时候先去缓冲池中查找是否有该数据。如果有就直接获取即可。减少IO操作。
缺点是:有可能会出现预读失效以及缓冲池污染的问题,这些问题都仅仅围绕 缓冲池。
什么是预读失效?
上面我们提到了缓冲池的预读机制可能会预先加载相邻的数据页。假如加载 了 20、21 相邻的两个数据页,如果只有页号为 20 的缓存页被访问了,而另 一个缓存页却没有被访问。此时两个缓存页都在链表的头部,但是为了加载这两 个缓存页却淘汰了末尾的缓存页,而被淘汰的缓存页却是经常被访问的。这种情 况就是预读失效,被预先加载进缓冲池的页,并没有被访问到,这种情况是不是 很不合理。
什么又是缓冲池污染呢?
还有一种情况是当执行一条 SQL 语句时,如果扫描了大量数据或是进行了全表扫描,此时缓冲池中就会加载大量的数据页,从而将缓冲池中已存在的所有页替换出去,这种情况同样是不合理的。这就是缓冲池污染,并且还会导致MySQL 性能急剧下降。
如何来解决这些问题呢?
-- 冷热数据分离
冷热数据分离:
也就是将 LRU 链表分为两部分,一部分为热数据区域,一部分为冷数据区域。当数据页第一次被加载到缓冲池中的时候,先将其放到冷数据区域的链表头部,1s(由 innodb_old_blocks_time 参数控制) 后该缓存页被访问了再将其移至热数据区域的链表头部。