InnoDB系列:体系结构

MySQL体系结构

从上图可以看出,主要是这几个

  • 连接池组件
  • 管理服务和工具组件
  • SQL接口组件
  • 查询分析器组件
  • 优化器组件
  • 缓冲组件
  • 插件式存储引擎
  • 物理文件

其中比较重要的就是这个插件式的存储引擎,这个引擎完全是基于表的,而不是基于整个数据库。

InnoDB的优点

  • 插入缓冲:对于非聚集索引的插入或更新操作不是每次直接插入到索引页,先判断插入的非聚集索引页是否在缓冲池中,若在,直接插入,若不在,先放入插入缓冲对象中。再用一定的频率对插入缓冲和辅助索引页进行合并操作。
  • MVCC高并发:支持行锁,每次删除不直接删除数据,而是去标记这个数据无效。
  • next-key locking 避免幻读。
  • 支持事务,保证ACID。
  • 支持崩溃后的安全恢复。

InnoDB体系结构

一图胜千言,上面就是Innodb存储引擎的体系架构。

  • 后台线程

    • 刷新内存池中的数据,保证缓冲池中的内存缓冲是最近的数据。
  • 内存池

    • 存储所有进程/线程需要访问的多个内部数据结构
    • 缓存磁盘上的数据,方便快速读取
    • redo log的缓冲
  1. 后台线程
  • Master Thread
    主线程,用于将缓冲池中的数据异步刷新到磁盘,保证数据的一致性。

  • IO Thread

使用大量Async IO来提高数据库性能。这些线程的主要工作就是负责IO请求的回调。1.0.x版本之后,分别有4个write和read,1个insert buffer和1个log thread。

  • Purge Thread
    事务提交之后其undolog可能不在需要,因此需要PurgeThread来回收已经使用并分配的undo页。

  • Page Cleaner Thread
    1.2版本引入,目的是减轻主线程的工作量。

  1. 内存池
  • 缓冲池
    其实就是一块内存区域,按照页的方式进行管理。在数据库读取页的时候,首先判断此页是否在缓冲池中,若没有,则读取的时候顺便把它放到缓冲池中。而脏页的回写遵循checkpoint机制。
    缓冲池中不光是数据和索引,更有自适应哈希索引,所信息,数据字典信息等等。
  • LRU List/Free List/Flush List

需要注意的是在进行LRU的时候,每次新的页不是直接插在表头,而是5/8的位置,为什么?因为某些SQL操作例如数据的扫描和索引等,需要访问表中的甚至全部页,而这些都不是热点数据,如果插在头部会淘汰热点数据。
还有一个问题,什么时候会认为这些数据是热点数据?mysql设置了一个参数,只要超过这个时间,就会被移到热端。

还有一点是脏页可同时存在于LRU list和Flush list中。

  • redo log缓冲

  • 额外的内存池
    对一些数据和结构本身的存储,必要的时候需要设置大一点

  1. checkpoint技术

设置这个技术的目的就是为了协调cpu和磁盘的速度,刷新频率不能太快,太快导致性能变差,并且如果从缓冲刷到磁盘宕机了,数据就丢失了。为了避免这个情况,使用Write Ahead Log策略,事务提交时,先写重做日志,再修改页,这样可以通过redo log来恢复。这也是事务ACID中D的要求。
综合来看,checkpoint技术解决下面几个问题:

  • 缩短数据库恢复时间(只需redo 检查点之后的数据)。
  • 缓冲池不够时,将脏页刷新到磁盘。
  • redo log不可用时,刷新脏页(redo log满了)。

checkpoint分为sharp和fuzzy两种,第一种是把所有脏页刷回磁盘,第二种有下面好几种情况:

  • 主线程检查点:每秒或者没十秒从缓冲池刷一定比例的脏页回磁盘。
  • Flush/LRU 检查点:保证列表有一定比例的空闲项。
  • Async/Sync checkpoint:redo日志不可用时刷新。
  1. 主线程工作方式
    主线程内部由几个循环组成
  • 主循环
    • 每1s
      • 日志缓冲刷新到磁盘
      • 合并插入缓冲
      • 至多100个脏页回写(后面版本改成以磁盘IO吞吐量来定)
      • 如果没有活动,切换到后台循环
    • 每10s
      • 刷新100个脏页
      • 合并5个插入缓冲
      • 日志缓冲回写
      • 删除无用undo页
      • 刷新100个或10个脏页
  • 后台循环
    • 删除无用undo
    • 合并20个插入缓冲
    • 跳回主循环
    • 不断刷新100个页,跳转刷新循环
  • 刷新循环
  • 暂停循环
  1. 插入缓冲

对于非聚集索引的插入或者更新,不是直接插入到索引页, 而是先放入插入缓冲对象中。再按照一定的频率对插入缓冲和非聚集索引节点进行合并操作。

  1. 两次写(double write)


两次写由两个部分组成,一部分是内存中的doublewrite buffer(2MB)。另一部分是物理磁盘上共享表空间中连续的128页(2MB)。
对缓冲池脏页刷新时:

  • 不立马写磁盘,使用memcpy将脏页复制到buffer中
  • 分两次,每次先将buffer的1MB写入共享表空间,调用fsync函数同步磁盘
  1. 自适应哈希索引(AHI)
    InnoDB会监控对表上索引页的查询,如果观察到简历哈希索引可以带来速度提升,会建立哈希索引。
    建立哈希索引的条件是:
  • 通过某模式访问100次
  • 页通过该模式访问了(页中记录/16)次