缓冲池
InnoDB存储引擎的记录是按页存储。
将磁盘中的页存放在缓冲池中,称之为“FIX”在缓冲池中。
下次读时先判断缓冲池是否命中,若命中,直接读取改页;否则读取磁盘的页。
写时首先修改缓冲池中的页,然后以一定频率刷新到磁盘上(CheckPoint机制)。
数据页类型
索引页,数据页,undo页,插入缓冲,自适应哈希索引,InnoDB存储的锁信息,数据字典信息。
缓冲池页大小16 KB。
从InnoDB 1.0.x版本开始,允许有多个缓冲池实例,每个页根据哈希值平均分配到不同缓冲池实例中。
LRU List、Free List和Flush List
LRU List
数据库缓冲池管理算法是添加midpoint优化的LRU算法。
新读取到的页插入到LRU列表尾端37%的位置。
位于midpoint之后的列表称为old列表,midpoint之前的列表称为new列表(热点数据)。
为什么不用朴素LRU? 某些SQL操作可能是索引或数据的扫描操作,需要访问很多页,但这些页只有本次查询工作需要,不作为热点数据。
Free List
数据库刚启动时,LRU列表时空的,页全部存放在Free列表中。
需要从缓冲池分页时,首先从Free列表中查找是否有可用的空闲页,若有则将该页从Free列表中删除,放入到LRU列表中。
否则根据LRU算法,淘汰LRU列表末尾的页,将内存空间分配给新的页。
一个重要的变量:Buffer pool hit rate,表示缓冲池命中率,通常不应该小于95%。(小于95%考虑是否由于全表扫描引起LRU列表被污染的情况)
压缩页
InnoDB存储引擎从1.0.x版本开始支持压缩页功能,可以将原本16KB的页压缩为1KB、2KB、4KB和8KB。
对于非16KB的页,通过unzip_LRU列表进行管理。
unzip_LRU分配的方式采取大页拆分的方式,当申请不到正常大小的空闲页检查二倍大小的压缩页,并分成两个同样大小的空闲页,放到对应的unzip_LRU列表;如果压缩页取不到就从LRU列表中申请一个16KB的页。
脏页写回
当LRU中的页被修改后,称该页为脏页,即缓冲池的页和磁盘的页数据不一致。使用checkpoint机制将脏页刷新回磁盘,Flush列表中的页即为脏页列表。
脏页既存在于LRU列表,也存在于Flush列表,二者互不影响(一个管理缓冲池页可用性,另一个管理将页面写回磁盘)。
重做日志缓冲
InnoDB存储引擎首先将重做日志信息放入此缓冲区,然后按一定频率将其刷新到重做日志文件。
刷新时的情况:
- Master Thread每一秒将重做日志缓冲刷新到重做日志文件。
- 每个事务提交的时候回将重做日志缓冲刷新到重做日志文件。
- 当重做日志缓冲池剩余空间小于1/2时,重做日志刷新到重做日志文件。