概述
InnoDB存储引擎是以页为单位来管理存储空间的,我们进行增删查改操作本质上就是在访问页(读页、写页、创建新页等),而页在磁盘上,每次磁盘I/O都需要消耗很多时间,为了提高效率,DBMS会申请占用内存来作为数据缓冲池:在InnoDB处理请求(尽管只有页中的一条数据)时,会将磁盘上完整的页数据缓存到内存中的Buffer Pool(后面有介绍)中再去进行读写访问,而后将其缓存起来给后续请求使用。
作用:减少与磁盘进行I/O的时间,提高效率。
Buffer Pool
Buffe Pool 本质是InnoDB向操作系统申请的一块连续的内存空间;
多线程、高并发下的Buffer Pool
多线程情况下,访问Buffer Pool的数据都需要加锁;
在Buffer Pool 特别大且线程并发访问量特别高的情况下,需要把其拆分成若干个小的Buffer Pool,每个Buffer Pool都称为一个实例,他们都是独立的,并且会独立的去申请内存空间、独立的管理各种链表,固在多线程并发访问时不会互相影响,从而提高并发处理能力。
Buffer Pool也是需要性能开销的,innodb规定:当 innodb_buffer_pool_size 小于1G时,设置多个实例是无效的,InnoDB会默认innodb_buffer_pool_instances 的值为1;
innodb_buffer_pool_size 大于1G时建议设置多个Buffer Pool实例。
指令
在服务器启动时可以通过设置 innodb_buffer_pool_instances 的值来修改Buffer Pool 的实例个数
eg:
表示创建2个Buffer Pool 实例
查看缓冲池的个数: show variables like`innodb_buffer_pool_instances`;
缓存原则
根据 “位置 * 频次” 原则对I/O访问进行优化;
位置:决定效率,提供缓冲池就是为了在内存可以直接访问数据;
频次:决定优先顺序,缓冲池大小有限(eg:磁盘有200G,内存只有16G,缓冲池就只有1G),无法将所有数据加载到缓冲池,会根据使用频次加载频次高的热数据;
预读特性
我们进行读取数据时存在一个“局部性原理”:我们使用了一些数据,大概率还会使用它周围的一些数据,因此采用“预读”机制提前加载,可减少未来可能的磁盘I/O操作。
数据同步
当我们对数据库中的记录进行修改时,首先会对缓冲池中的信息进行修改,然后以一定的频率刷新到磁盘上,这里并不是每次更新操作都会立刻写回磁盘,而会采用一种 checkpoint 的机制,触发时才回写到磁盘上,更好的提升整体性能;
eg:当缓冲池不够时,此时将不常用的脏页(缓冲池中修改过的页)回写到磁盘上,然后从缓冲池中释放掉。
黑盒下的数据更新流程
当我们查询数据时,会先去Buffer Pool 中查询,若是不存在,存储引擎会先将数据从磁盘加载到Buffer Pool中,然后将数据返回给客户端;
同理,当我们更新某个数据时,若是在Buffer Pool中找不到,同样会先加载进去再修改在内存中的数据,后续会统一刷入磁盘。