看了姜老师的技术内幕,做了如下笔记


Innodb线程:

innodb是多线程模型,有多个后台线程负责处理不同任务

1、主线程

负责将缓冲池中的数据异步刷新到磁盘,脏页刷新,合并插入缓冲,undo页回收等


2、IO线程

innodb存储引擎中使用了大量AIO(异步io)来处理IO请求,IO线程主要负责这些IO请求的回调。


3、purge线程

事务提交后,其所使用的undolog可能不再需要,因此需要purge thread来回收。


4、page cleaner 线程

负责刷新脏页


Innodb的内存:

1、缓冲池(innodb_buffer_pool)

    Innodb存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。由于CPU与磁盘速度之间的鸿沟,基于磁盘的数据库系统,通常使用缓冲池技术提高数据库的整体性能。

    缓冲池可以理解为一块内存区域,在数据库中读取页的操作,首先将磁盘中读到的页放在缓冲池中,下次再读相同的页时,判断是否在缓冲池中,在就直接读取,即命中。不在就到磁盘中去读取。

    对于数据库中页的修改,首先修改缓冲池中的页,然后再以一定频率刷回磁盘。注意:页从缓冲池刷回磁盘并不是每次页变更了都会触发,而是通过检查点机制刷新回磁盘。

    缓冲池中缓存的数据页类型有:索引页,数据页,undo页,插入缓冲,自适应哈希,innodb锁信息,数据字典信息等。

2、LRU list、Free list、Flush list

    LRU列表

    数据库中的缓冲池是通过LRU(最近最少使用)算法来进行管理的,innodb对LRU算法进行了一些优化,在LRU列表中加入了midpoint位置,默认情况下,该位置位于LRU列表长度的5/8处。

    在midpoint之前的列表称为new,之后的称为old,可以简单理解为new列表中的页都是活跃的热点页。

    mid位置页升为热点数据需要等待参数innodb_old_blocks_time,已保证尽量不将LRU列表的将热点数据刷出。


    Free列表

    数据库刚启动时,LRU列表为空,所有页都存在Free列表中,要从缓冲池分页时,先从Free列表查看有没有空闲页,有,将该页从Free列表删除,放到LRU列表中。没有,根据LRU算法,淘汰LRU列表末尾的页,将内存空间分配给新的页。

    LRU list包含unzip_LRU list,LRU list页大小为16K,unzip_LRU list的页大小可能为1k、2k、4k、8k。

    unzip_LRU列表对不同压缩页大小的页进行分别管理,其次通过伙伴算法进行内存的分配。

    例如需要从缓冲池申请一个4k的页,检查4k的unzip_LRU列表是否有空闲页,有,直接使用,没有,查找8k的unzip_LRU列表,若有空闲页,将其分为2个4K的页,存到4k的unzip_LRU列表,若没有空闲页,则将LRU列表一个16k的页,拆成一个8k和2个4k的页,存入对应的unzip_LRU列表。


    Flush列表

    LRU列表中的页被修改后,称为脏页,即缓冲池中的页和磁盘上的页不一致。这时,数据库会通过checkpoint机制将脏页刷回磁盘。

    Flush列表中的页即为脏页,脏页既存在于LRU列表,也存在于Flush列表。

    LRU列表用来管理缓冲池中页的可用性,Flush列表用来管理将页刷新回磁盘,两者互不影响。


3、重做日志缓冲(redo log buffer)

    innodb存储引擎先将重做日志信息放入这个缓冲区,再按照一定频率将其刷新到重做日志文件,用户只需要保证每秒的事务不超过这个缓冲大小即可。默认8M

    在下面三种情况下,会将重做日志缓冲中的内容刷新到重做日志:

    1)、主线程,每一秒将重做日志缓冲刷新到重做日志文件。

    2)、每个事务提交时,会将重做日志缓冲刷新到重做日志文件。

    3)、当重做日志缓冲大小小于1/2时,会将重做日志缓冲刷新到重做日志文件。


checkpoint技术

检查点技术主要解决以下几个问题:

1)、缩短数据库恢复时间

    当数据库宕机时,数据库不需要重做所有的日志,checkpoint之前的已经刷回磁盘,只需要重做checkpoint之后的日志,大大减少了恢复时间。

2)、缓冲池不够时,将脏页刷新到磁盘

    当缓冲池不够用时,会溢出最近最少使用的页,如果这个页是脏页,那么强制checkpoint,将脏页刷新回磁盘。

3)、重做日志不可用时,刷新脏页


在innodb中checkpoint分为两种:

Sharp checkpoint:在数据库关闭时,将所有脏页刷新回磁盘,默认的。

Fuzzy checkpoint:只刷新一部分脏页到磁盘。


可能发生Fuzzy checkpoint的几种情况:

1)、master thread checkpoint

    差不多每10秒,从脏页列表刷新一部分脏页到磁盘。

2)、flush_LRU_list checkpoint

    innodb需要保证LRU列表有innodb_lru_scan_depth个空闲页可以使用,如果没有,就会从lru列表末尾移除,如果移除的有脏页,就进行checkpoint。

3)、异步/同步 Flush checkpoint

4)、dirty page too much checkpoint

    当缓冲池中脏页数量大于innodb_max_dirty_pages_pct,强制checkpoint。


Master thread

    master thread具有最高的线程优先级,由多个循环组成:主循环loop、后台循环backgroup loop、刷新循环flush loop、暂停循环suspend loop。master thread会根据数据库运行状态,在这些循环中切换。

    loop循环,分为每1秒操作和每10秒操作:

    每1秒:

    1)、日志刷新缓冲刷新到磁盘,即使这个事务没有提交(总是)

    2)、合并插入缓冲(可能)(innodb判断前1秒发生的IO次数是否小于innodb_io_capacity的5%次,则合并缓冲innodb_io_capacity的5%)

    3)、至多刷新innodb_io_capacity个缓冲池中的脏页到磁盘(可能)(判断当前缓冲池中脏页的比例是否超过了innodb_max_dirty_pages_pct)

    4)、当前没有用户活动,则切换到backgroup loop(可能)

    

    每10秒:

    1)、刷新innodb_io_capacity个脏页到磁盘(可能)(innodb判断过去10s内io是否小于innodb_io_capacity次)

    2)、合并innodb_io_capacity的5%个插入缓冲(总是)

    3)、将日志缓冲刷到磁盘(总是)

    4)、删除无用的undo页(总是)

    5)、刷新innodb_io_capacity个或innodb_io_capacity的10%个脏页到磁盘(总是)(判断缓冲池中的脏页比例,如果大于70%刷新innodb_io_capacity个,小于70%刷新innodb_io_capacity的10%个)


   backgroup loop:

    1)、删除无用的undo页(总是)

    2)、合并innodb_io_capacity个插入缓冲(总是)

    3)、跳回到主循环(总是)

    4)、不断刷新innodb_io_capacity个页直到符合条件(可能跳到flush loop中完成)


Innodb关键特性

    1)、插入缓冲

        并不是所有的主键插入都是顺序的,例如UUID这样的主键值或者主键为自增,但插入为指定值而不是null值,同样可能会出现非连续插入的现象。

        对于非聚集索引的插入或更新操作,并不是每次都直接插入到索引页。先判断插入的非聚集索引页是否在缓冲池中,在,直接插入,不在,先放到insert buffer中。然后再以一定频率进行Insert buffer和索引页子节点的合并操作。

        insert buffer使用要满足两个条件:

        a、索引是辅助索引

        b、索引不唯一

    2)、两次写

        刷新脏页时,先将脏页刷到double write buffer中(2M),再从double write buffer中分两次(1次1M)顺序写入磁盘上共享表空间的连续128个页(2M),然后再从double write buffer离散的写入磁盘,如果写入失败了再去共享表空间里拿副本来恢复。

    3)、自适应哈希

        AHI是通过缓冲池B+树页来够造的。innodb会根据访问频率和模式,自动为热点页添加hash索引。

        添加hash索引的条件:

        a、连续以同一模式访问100次

        b、页以同一模式访问N次,N=页中记录*1/16

    4)、异步IO

        用户可以发出一个io请求后,跟着再发出一个io请求,当全部IO请求发送完毕后,等待所有IO操作完成,这就是AIO。即不用等一个IO完成才能再发出一个IO。

        AIO会判断多个页是否是连续的,如果是,会进行merge操作,合并为一个IO,这就提升了IOPS。

    5)、刷新邻接页

        当刷新一个脏页时,innodb会检查该页所在的区的所有页,如果是脏页,那么就一起刷新。固态硬盘可以考虑关闭,机械硬盘建议开启。参数为0关闭、1开启。