缓存的重要性
即使只需要访问一个页的一条记录,也需要先把完整的页中的数据加载到内存中,将整个页的数据加载到内存中就可以进行读写访问了,而且在读写访问之后并不着急把该页的对应的内存空间释放掉,而是将其缓存起来,这样将来有请求再次访问该页面时,就可以省下磁盘I/O的开销了。
磁盘太慢,用内存作为缓存区很有必要。
Buffer Pool
本质上是InnoDB
向操作系统申请的一段连续的内存空间,可以通过innodb_buffer_pool_size
来调整它的大小。
Buffer Pool
向操作系统申请的连续内存空间由控制和缓存页组成,每个控制块和缓存页嗾使一一对应的。都填充了足够多的控制块和缓存页的组合后,Buffer Pool
中剩余的空间可能不足以填充一组控制块和缓存页,从而导致这部分空间无法使用。这部分空间也称为碎片。
InnoDB
使用了许多链表来管理Buffer Pool
。
在free
链表中,每一个节点都代表一个空闲的缓冲页,在将磁盘中的页加载到Buffer Pool
中时,会从free
链表中寻找空闲的缓冲页。
为了快速定位某个页是否被加载到Buffer Pool
中,可使用表空间号+页号作为key
,缓冲页控制块的地址作为value
的形式来建立哈希表。
在Buffer Pool
中,被修改的页称为脏页,脏页并不是立即刷新的,而是加入到flush
链表中,待之后某个时刻再刷新到磁盘中。
LUR
链表分为young
区和old
区,可以通过innodb_old_blocks_pct
来调节old
区域所占的比例。首次从磁盘加载到Buffer Pool
中的页会放到old
区域的头部,在innodb_old_blocks_pct
间隔时间内访问该页时,不会把它移动到young
区域头部,在Buffer Pool
中没用可用的空闲缓冲页时,会首先淘汰掉old
区域中的一些页。
可以通过指定innodb_buffer_pool_instances
来控制Buffer Pool
实例的个数,每个Buffer Pool
实例都有各自独立的链表,互不干扰。
自MySQL 5.7.5
版本之后,可以在服务器运行 过程中调整Buffer Pool
大小,每个Buffer Pool
实例由若干个chunk
组成,每个chunk
的大小可以在服务器启动时通过启动选项调整。