对于innodb体系架构之后台线程、内存

来源:互联网 发布:女权癌 知乎 编辑:程序博客网 时间:2024/06/05 00:44

innodb体系架构

innodb存储引擎有多个内存块,可以认为这些内存块组成了一个大的内存池,负责:维护所有进程/线程需要访问的多个内部数据结构;缓存磁盘上的数据,方便快速读取,同时对磁盘文件的数据修改之前在这里缓存;redo log缓冲等等。

       后台线程主要作用是负责:刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据;将已经修改的数据文件刷新到磁盘文件;同时保证数据库发生异常情况下,innodb能恢复到正常运行状态。

       innodb存储引擎是多线程的模型,因此,后台有多个不同的后台线程,负责处理不同的任务。

一、后台线程

1.    master thread:主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新,合并插入缓冲,undo页回收等

2.    io thread:大量使用AIO来处理io请求,可以极大提高数据库性能。io thread主要负责io请求的回调处理。(如,读写线程、log thread、insert buffer thread)

3.    purge thread:事务被提交后,所使用的undo log可能不在需要,需要purge thread来回收已经使用并分配的undo页。从innodb 1.1版本开始,purge操作可以独立到单独的线程中进行,减轻了master thread的工作,提高了CPU使用率以及提升存储引擎的性能。从innodb 1.2开始,innodb支持多个purge thread,这样的目的是为了进一步加快undo页的回收。同时,由于purge thread需要离散的读取undo页,也能进一步利用磁盘的随机读取性能。

4.    page cleaner thread是在innodb 1.2版本引入的。作用是:将之前版本中脏页的刷新操作放入到单独的线程中来完成,目的是减轻master thread的工作及对于用户查询线程的阻塞。提高了innodb存储引擎的性能。

 

二、内存

1、缓冲池:innodb存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理,因此,可被视为基于磁盘的数据库系统。由于CPU和磁盘速度之间的鸿沟,这种数据库系统通常需要缓冲池技术来提高数据库的整体性能。

       缓冲池就是一块内存区域,通过内存的速度弥补磁盘速度较慢对数据库的影响。在数据库中进行读取页的操作,首先将从磁盘读到的页放在缓冲池中,这个过程成为将页fix在缓冲池下,下次在读相同的页时,首先判断是否在缓冲池中,如果在。就称该页在缓冲池被命中,直接读取该页,否则,读取磁盘上的页。

       数据库中对页的修改操作,先是修改缓冲池中的页,然后以一定频率刷新到磁盘上。刷盘的操作不是在每次页发生更新时触发,而是通过checkpoint机制刷新回磁盘。具体来看,缓冲池中缓存的数据页类型有:索引页、undo页、数据页、插入缓冲、自适应hash索引、innodb存储的锁信息、数据字典信息等。不能简单的任务缓冲池只是缓存索引页和数据页。他们只是占缓冲池很大的一部分而已。


从innodb1.0版本开始,允许有多个缓冲池实例。每个页根据hash值平均分配到不同缓冲池实例中。可以减少数据库内部资源竞争,增加数据库的并发处理能力。

注:额外内存池从5.7.4版本正式移除

2、LRU list、Free list和Flushlist

       数据库中的缓冲池通过LRU(latest recent used,最近最少使用)算法来进行管理。及最频繁使用的页在LRU列表的前端,最少使用的页在LRU列表的尾端。当缓冲池不能存放新读取的页时,先释放LRU尾端的页。页的大小默认是16KB,同样使用LRU算法对缓冲池进行管理。稍有不同的是innodb存储引擎对传统的lru算法做了一些优化,在innodb的存储引擎中,LRU列表还加入了midloint位置,新都区到的页,虽然是最新访问的页,但是不直接放到LRU列表的收不,而是放到midpoint位置。这个算法成为midpoint insertion strategy。在默认配置下,在LRU列表长度的5/8处。通过和innodb_old_blocks_time配合,尽可能的保护LRU列表中热数据不被刷出去。

       free列,当数据库刚启动时,lru列表是空的,这些页都在free列表中,当需要从缓冲池中分页时,首先从free列表中看是否有可用的空闲页,如果有就将该页从free列表中删除,放入到lru列表中。否则,根据lru算法,淘汰lru列表末尾的页,将该内存空间分配给新的页。当页从lru的old端加入到new端时,此时的操作为page made young;如果从new端加入到old端,操作成为page not made young。

       当show engineinnodb status查看到free buffer和databasepages的和并不等于buffer pool size,因为,缓冲池中的页可能还被分配给自适应hash索引、lock信息、insertbuffer等页。这部分页不需要lru算法维护,因此不存在lru列表中。

       从innodb 1.2版本开始,可以通过innodb_buffer_pool_stats来观察缓冲池的运行状态;通过innodb_buffer_page_lru来观察lru表中每个页的具体信息。

       innodb存储引擎从1.0版本开始支持压缩页的功能,即将原本16K的页压缩为1KB、2KB、4KB、8KB,由于页的大小发生了变化,lru列表也有了些许的改动。对于非16k的页,是通过unzip_lru列表进行管理的。假如要从缓冲池申请页为4KB,那么unzip_lru从缓冲池中分配内存的情况如下:

1) 检查4KB的unzip_lru列表,检查是否有可用空闲页

2) 若有直接使用;若没有检查8KB的unzip_lru列表

3) 若能得到空闲页,将页分成2个4KB页,存放到4KB的unzip_lru列表

4) 若不能得到空闲页,从lru列表申请一个16KB的页,将页分为1个8KB的页,2个4KB的页,分别存放到对应的unzip_lru列表。

注意,lru列表中的页被修改后,称该页为脏页,即缓冲池中的页和磁盘上的页的数据不一致。数据库会通过checkpoint机制将脏页刷新回磁盘,而flush列表中的页就是脏页。脏页既存在于lru列中,也在flush列。lru列表用来管理缓冲池中页的可用性,flush列表用来管理将页刷新回磁盘。

3、重做日志缓冲(redo)

       innodb首先将redo信息放入到redo log buffer,然后按一定频率将其刷新到redo logfile。redo log buffer不需要设置的很大,因为一般情况下每一秒都会将redo缓存刷新到redo logfile,因此用户只需要保证每秒产生的事务量在这个缓冲大小之内即可。由innodb_log_buffer_size控制。但是,通常情况下,8MB的redo log buffer足以满足绝大部分应用,因为redo在下列三种情况下会将redo log buffer中的内容刷新到logfile中。

1.    master thread每一秒将redo日志缓冲刷新到redo logfile中

2.    每个事务提交时会将redo日志缓冲刷新到redo logfile中

3.    当log buffer size剩余空间不足1/2时,刷新到redo logfile中。

4、额外的内存池

       额外的内存池同样重要,在innodb中,对内存的管理是通过一种成为内存堆的方式进行的。在对一些数据结构本身的内存进行分配的时候,需要从额外的内存池中进行申请,当该去局的内存不够时,会从缓冲池中进行申请。要注意,这个innodb_additional_mem_pool_size参数在5.6.3被启用,在5.7.4正式被移除。

 

三、innodb关键特性

1、插入缓冲

2、两次写

3、自适应hash索引

4、异步IO

5、刷新邻接页