InnoDB体系架构
这些内存块负责如下工作:
- 维护所有进程/线程需要访问的多个内存数据结构
- 缓存磁盘上的数据,方便快速读取,同时在对磁盘文件的数据修改之前在这里缓存。
- 重做日志缓冲(redo log)
后台线程的主要作用是负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据。此外将修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下InnoDB能恢复到正常运行状态。
后台线程
-
Master Thread:核心后台线程,负责将缓冲池中的数据异步刷新到磁盘上,保证数据的一致性,包括脏页刷新、合并插入缓冲、UNDO页回收等。
-
IO Thread:InnoDB使用AIO处理IO请求,提高了数据库性能。这些线程的作用是负责这些请求的回调。
-
Purge Thread:事务提交后,其使用的undolog可能不在需要,因此需要PurgeThread来回收已经使用并分配的undo页。1.2后,InnoDB支持多个Purge Thread,目的是为了加快undo页的回收。
- Page Cleaner Thread:1.2版本后引入,作用是将之前版本中的脏页的刷新操作都放入到单独的线程中来完成。目的是为了减轻Master Thread的工作。
内存
缓冲池
InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。磁盘数据库系统通常通过缓冲池技术提高数据库整体性能。
缓冲池就是一块内存区域,通过内存的速度来弥补磁盘速度较慢的数据库影响。缓冲池的大小直接影响了数据库的整体性能。
- 读页操作的时候,首先将从磁盘读取,拿到页后放入缓冲池中,下次在读取相同的页时候判断是否在缓冲池中,如果在缓冲池命中,直接读取该页,否则重复上面的操作。
- 对数据库修改的操作,先修改缓冲池中的页,然后以一定的频率将缓冲池的页刷新回磁盘上。(通过checkpoint机制刷新回磁盘,并不是每次更新都刷新回磁盘,也是为了提高数据库的整体性能)
缓冲池中缓存的数据页类型:索引页、数据页、undo页、插入缓冲、自适应哈希索引、InnoDB存储的锁信息、数据字典等。InnoDB在1.0之后,允许多个缓冲池实例,每个页根据哈希值平均分配到不同缓冲池实例中,减少了数据库内部的资源竞争,增加了并发能力。
LRU List、Free List和Flush List
数据库缓冲池通过LRU(Last Recent Used最近最少使用)算法进行管理,最频繁的数据在LRU列表最前端,最少使用的数据在最末端。当缓冲池不能存放新读取的页时,将首先释放LRU最末端的页。
InnoDB对LRU的优化,加入了midPoint位置(列表5/8处),读取到新页的时候,将新页放到midPoint位置,然后把midPoint之前的页叫new列表,之后的叫old列表。这样做的好处是放置防止每次新请求都会把缓冲池中的尾部的页刷出,从而影响效率。
加载过程:数据库启动LRU列表为空,页都存放到Free列表中。需要从缓冲池分页的时候,从Free列表中查询是否有空闲页,有则从Free列表删除,放入到LRU中,没有的话根据LRU算法淘汰最末端的页,将该内存分配给新的页。
缓冲池中的自适应哈希索引,Lock信息,插入缓冲等页,不需要LRU算法,所以不在LRU列表中。
LRU列表中的页被修改后,被称为脏页,即缓冲池中的页和磁盘中的页不一致,数据库回通过checkPoint机制将脏页刷新回磁盘,而Flush列表中的页即为脏页。
脏页既存在与LRU列表,也存在于Flush列表中。
重做日志缓冲
InnoDB存储引擎的内存区域除了有缓冲池外,还有重做日志缓冲。InnoDB存储引擎将重做日志信息放入缓冲区,然后按照一定频率将其刷新回重做日志文件。
以下情况会将重做日志缓冲刷新回磁盘的重做日志中:
- Master Thread每一秒将重做日志缓冲刷新到重做日志文件中;
- 每个事务提交时会将重做日志缓冲刷新到重做日志文件;
- 每当重做日志缓冲池剩余空间小于1/2时,重做日志缓冲刷新到重做日志文件。
额外内存池
在对一些数据结构本身的内存分配的时候,需要从额外内存池进行申请,当区域内存不足的时候,会从缓冲池中申请。