美文网首页数据库
InnoDB存储引擎

InnoDB存储引擎

作者: 简书徐小耳 | 来源:发表于2018-11-26 23:23 被阅读71次

    innoDB的各个版本对比

    image.png

    innoDB的整体架构

    image.png
    后台线程
    • master thread

    1.赋值将缓冲池中的数据异步刷到磁盘,保证数据的一致性。

    1. 刷新脏页,合并插入缓冲,UNDO页的回收等
    • IO tread

    1.innodb采用AIO来处理写IO,而IO thread就是处理这些IO请求的回调

    2.Io thread有:write,read,insert bufeer和log

    3.可以通过innodb_read_io_threads和innodb_write_io_threads来设置read和write的线程数,insert bufeer和log固定为1个

    image.png
    • purge thread

    1.undo log用于存放事务提交前原始的数据,如果事务已经提交了,则undo可以通过purge thread回收

    2.可以设置多个purge thread 回收undo 页

    • page cleaner thread

    1.将脏页的刷新操作都放入到page cleaner thread

    内存
    • 缓冲池

    1.innodb中的记录按照页的方式进行管理。

    2.将磁盘读到的页放在缓冲池,这个过程称为将页FIX在缓冲区

    3.对页修改是先修改缓冲池的页,然后再以一定的频率刷新到磁盘上

    4.页从缓存池刷新会磁盘的操作并不是每次页发生变更的时候,而是通过checkpoint机制

    5.通过innodb_buffer_pool_size来设置和这个缓冲池大小

    6.内存数据对象包含以下,其中缓冲池包含:数据页,插入缓冲,锁信息,索引页,自适应哈希索引,数据字典信息

    image.png

    7.可以有多个缓冲池实例,每个页根据hash值平均分配到不同的缓冲池实例,这样就减少数据库内部资源竞争

    8.innodb_buffer_pool_instances来设置多少个缓冲值实例。

    • LRU List,Free List 和Flush List

    1.LRU List,Free List 和Flush List这三个是用来管理缓冲池内容的方式

    2.LRU最近最少使用方式,前端存放使用最频繁,最少使用存放尾部。最新读到的页面,将首先存放在尾部。(innodb做了优化,把最新的页存放在midpoint位置,默认是在LRU列表长度的5/8)

    3.在innodb中把midpoint之后的称为old,之前的称为new。即new是最活跃的热点数据

    4.设置innodb_old_blocks_time,来标识页读取到mid位置后需要等待多久才会被加入到LRU列表的热端

    5.数据库刚启动LRU是空的,页都存放在Free列表中,我们获取页,优先从free中获取

    1. LRU列表淘汰的末尾页,将该内存空间分配给新的页

    7.当支持压缩页后,页变为 1KB,2KB,4KB和8KB,对于非16KB的页管理,通过unzip_LRU进行管理

    8.我们正常得到的LRU页包含unzip_LRU

    9.unzip_LRU分配页方法(比如想获取4KB),首先检查4KB的unzip_LRU列表是否有可用的空闲页,没有的话检查8KB的列表,如果有则将8KB分成2个4KB,放入到4KB列表,若还是得不到则从16KB申请一个页,拆分成1个8KB的页,2个4KB的页,分别存放对应的unzip_LRU

    10.在LRU列表中被修改的页,我们称之为脏页,通过checkPoint机制将脏页刷新会磁盘,flush列表就是脏页列表

    11.脏页即存在于LRU也存在Flush列表(因为还需要使用)

    • redo log buffer
    1. innodb会将重做日志信息放入到这个缓冲区,然后以一定的频率将其刷新到重做日志文件(redo log file)

    2.通过设置innodb_log_buffer_size设置这个redo log buffer

    3.以下三种情况会将redo log buffer刷新到redo log file:master thread每秒钟会刷新,当事务提交时候,当重做buffer剩余空间大小小于一半

    • 额外的内存池

    checkpoint

    • 1.为了避免在内存中脏页还未刷到磁盘,系统宕机导致数据都是,采用了write ahead log
    • 2.write ahead log:即事务提交的时候,先写redo log file(即把redo log buffer 转化为文件)
    • 3.如果redo log file 太大了会导致,数据库启动时候恢复需要很长时间,且成本太高
    • 4.checkPoint:缩短数据库的恢复时间,缓冲池不够用时候将脏页刷新到磁盘,重做日志不可用的时候刷新脏页。
    • 5.宕机之后,checkpont之前的页都已经刷新到磁盘,只需要对checkpoint后的重做日志进行恢复。
    • 6.单缓冲池不够用,LRU会溢出最近最少使用的页溢出,若是脏页则会执行checkpoint,即将脏页刷新到磁盘
    • 7.因为对重做日志都是循环使用的,当我们重做日志快用满了,这个时候如果还想使用重做日志,那么需要把内存中国对应的页给刷到磁盘,才可以覆盖那部分被刷到磁盘页对应的重做日志
      1. checkpoint的类型:sharpCheckPoint
        ,Fuzzy CheckPoint.
    • 9.sharpCheckPoint:发生在数据库关闭时候,将所有的脏页刷新回磁盘,这是默认的工作方式,通过参数innodb_fast_shutdown=1
    • 10.Fuzzy CheckPoint.:master thread checkPoint,FLUSH_LRU_LIST checkPoint,Async/Sync flush check point,Dirty Page too much check point
      1. master thread checkPoint:每个一段时间刷新一定比例,是异步操作。
    • 12.FLUSH_LRU_LIST checkPoint:被移除LRU列表的脏页会被回收.通过page cleaner thread 去操作
    • 13.Async/Sync flush check point:只重做日志不可用,这时候强制将一些页刷新回到磁盘,放入到page cleaner thread 中操作
      1. Dirty Page too much check point:强制刷新一部分脏页到磁盘

    masterThread的工作方式

    • 最初该线程内部又多个loop组成,loop,background loop,flush loop,suspend loop

    • loop 分为 每秒操作和每十秒操作,

    • loop 每秒操作:日志缓冲刷新到磁盘,即时事务还没提交(总是),合并插入缓冲(可能),至多刷新100个脏页到磁盘(可能),如果当前没有事务提交,则契合到backgroup loop

    • loop 每十秒操作:刷新100个脏页(可能),合并至多5个插入缓冲(总是),将日志缓冲刷新到磁盘(总是),删除无用的undo(总是),刷新100个或者10个脏页到磁盘

    • background loop:数据库空闲,或者关闭,就会切换到这个循环。

    • background loop:删除无用的undo(总是),合并20个插入缓冲(总是),调到主循环(总是),不断刷新100个页直到符合条件(可能,跳转到flush loop中完成)

    • 如果flsuh loop 没有脏页要刷新,则会切换到suspend_loop,将master thread 挂起

    • 之后的改革就是 合并插入缓冲时候,合并插入缓冲的数量是 innodb_io_capacity的5%,从缓冲区刷新脏页的数量就是innodb_io_capacity

    • 剔除了innodb_adaptive_flushing ,用来判断每次刷新多少脏页

    • 把 刷新脏页的操作转移给page cleaner thread

    innodb关键特性

    • 插入缓冲:其是物理页的一部分,不是缓冲区的一个部分,对于插入或者更新的时候,先判断对应的非聚集索引页是否在缓冲池,若是在直接插入,不在的话则先放入到一个insert buffer中,然后在以一定的频率和情况进行insert buffer和辅助索引的叶子结点的merge。需要索引不是唯一且是辅助索引。以后的change buffer 作用与insert buffer一样只是还可以作用于delete等
    • 我们每次删除记录都是现将记录标识位已删除,然后再真正删除

    • 两次写:如果数据写到页,写了一半发生宕机,那么这个页就是被损坏,如果通过redo log无法对其redo 因为redo log 是对页进行物理操作,,写入发生失效,我们先通过页的副本替换页,然后在进行重做。这就是double write

    • double write包含double write buffer 为2M,还有磁盘上128个连续页,大小同样为2M。在对缓冲池的脏页进行刷新时候,并不直接写盘,而是先将脏页数据复制到内存中double write buffer ,然后double write 分为2次 1m的去写,直接同步到磁盘。因为double write的页是连续的所以开销不大,然后我们在将double write buffer 写入各个表空间

    • 我们在恢复空间只需要将double write 页中的数据直接复制到表空间文件,在应用重做日志


      image.png
    • redo 是物理和逻辑日志的结合,每次记录哪个页,发生了什么操作,当我们页被污染了,这个时候再去写,很有可能造成数据不一致。所以需要换一个新的页

    • 为啥redo 不需要 doubble write

    • 这个博客记录了 为啥我们同时需要double write和redo :https://www.cnblogs.com/geaozhang/p/7241744.html

    • 自适应哈希索引:innodb观察到如果给表加上hash索引可以提高速度,即对热点查询建立自适应hash,

    • 异步io:read ahead和脏页的刷新都是依靠AIO

    • 刷新邻接页:刷新一个脏页,发现这个页所在去的所有页,如果是脏页,那么久一起进行刷新,这样的好处是通过AIO将多个IO写入合并为一个

    • 对于不怎么脏的脏页 也刷新了,或者固态硬盘不需要。所以可以关闭

    启动,关闭与恢复

    相关文章

      网友评论

        本文标题:InnoDB存储引擎

        本文链接:https://www.haomeiwen.com/subject/ybjiqqtx.html