InnoDB架构图
可以看到主要由3部分组成,分别为后台线程、InnoDB存储引擎内存池及文件。
后台线程一个作用是负责刷新内存池中的数据,因为内存池相当于CPU与磁盘文件中间的缓冲,加速CPU对磁盘文件的访问,因此内存池中会存有磁盘文件的一部分缓存数据,而该部分数据会通过LRU算法进行更新,后台线程则正是执行这个操作。另一个作用是将已修改的数据文件刷新到磁盘文件,因为在InnoDB中,会将数据先写入内存池中,之后再通过后台线程将该部分数据(也称为脏页,即内存池中与磁盘文件中不一致的那部分数据)刷到磁盘文件中。
缓冲池工作原理
缓冲池简单来说就是一块内存区域,用于弥补磁盘速度与CPU之间的数据差异,从而减弱对数据库性能的影响。
InnoDB是以数据页来管理磁盘文件的。在数据库中进行读取操作时,会先判断该页是否已在缓冲池中,如果已经在了,则缓存命中,直接读取该页。否则,读取磁盘上的页,此外,根据LRU算法,会对缓冲池的数据进行刷新。对数据库中的页进行修改时,会先修改在缓冲池中的页,之后通过Checkpoint机制刷新到磁盘。
对修改页操作的进一步分析
正如我们知道缓冲池可以用来缓存数据,因此我们可以很容易理解,为什么在修改时,先对缓冲池的中页进行修改,而不是直接对磁盘文件进行操作。可是InnoDB在修改完缓冲池中的页数据后没有将其写回到磁盘文件,这样如果在数据页写回到磁盘文件前发生了宕机,就会造成数据修改的丢失。为了避免该问题,当前的事务数据库系统,普遍都采用了Write Ahead Log策略,即当事务提交时,先写redo log,再修改缓冲池中的页。采用这种策略后,当由于在数据页写回磁盘文件前发生宕机而导致数据修改的丢失,就可以通过redo log来完成数据的恢复。这也是InnoDB对ACID中D(持久性) 的实现。
redo log中记录了 对数据页的修改
Checkpoint机制
一般来说缓冲池大小和redo log日志的大小都是有限的,Checkpoint就是在这个前提下,对脏页进行刷新的方式。
- 当缓冲池不够用时,将脏页刷新到磁盘
- 当redo log不够用时,将脏页刷新到磁盘
至于为什么采用这样的方式,这两者其实理解起来差不多。假如缓冲池不够用了,后续写操作要对不在缓冲池中的页进行修改,这时候如果不将脏页刷新到磁盘,就会因为数据页的置换导致被置换出去的数据页丢失,因此必须在不够用时,将脏页刷新到磁盘。假如redo log不够用了,后续修改操作产生的redo log记录会将原本redo log中的记录覆盖,如果此时发生了宕机,就会造成被覆盖部分数据页修改的丢失,所以在redo log不够用时,也必须将脏页刷新到磁盘。
补充:写入redo log记录时,会先写入redo log缓冲池中,并根据一定的策略刷新到redo log磁盘文件中。具体有以下三种情况。
- Master Thread每一秒将redo log缓冲爱护刷新到redo log磁盘文件中
- 事务提交时会将redo log缓冲爱护刷新到redo log磁盘文件中
- 当redo log缓冲池剩余空间小于1/2时,将redo log缓冲爱护刷新到redo log磁盘文件中