InnoDB存储引擎(一)概述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kukubao207/article/details/88544122

1、概述

InnoDB是事务安全的MySQL存储引擎,支持ACID,他的特点是:

  • 行锁设计
  • 支持外键
  • 提供一致性非锁定读
  • 支持MVCC

2、InnoDB体系架构

InnoDB存储引擎主要由后台线程和内存块构成,可以认为这些内存块组成了一个大的内存池,负责如下工作:

  • 维护所有进程/线程需要访问的多个数据结构
  • 维护磁盘上的数据,方便快速读取
  • 在数据刷到磁盘前缓存数据
  • 重做日志(redo log)缓冲

2.1 后台线程

2.1.1 Master Thread

这是核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性

  • 脏页的刷新
  • 合并插入缓冲
  • undo页的回收
2.1.2 IO Thread

InnoDB中用了大量AIO来处理写IO请求,而IO Thread用来处理这些IO请求的回调。InnoDB1.0版本之前有4个IO Thread,分别是write,read,insert buffer,log

2.1.3 Purge Thread

事务Commit后undolog可能不再需要,该线程主要用来回收undo页

2.1.4 Page Cleaner Thread

将之前版本中脏页的刷新操作都放入这个线程中去处理,减轻Master Thread的负担

2.2 内存

2.1.1 缓冲池

InnoDB存储引擎是基于磁盘存储的,其中记录以页的方式管理。
缓冲池简单来说就是一块内存区域,协调CPU速度与磁盘速度的鸿沟。
缓冲池的作用、特点:

  • 读操作,从磁盘上读页载入缓冲池,下次再读相同页,直接从内存中取。
  • 写操作,先写入缓冲池,以一定的频率(CheckPoint机制)刷新到磁盘。
  • 缓冲池的具体数据页类型:数据页、索引页、undo页、插入缓冲、自适应哈希索引等。
2.1.2 LRU List、Free List和Flush List

缓冲池通过改进的LRU算法管理数据页。
Free List:数据库刚启动时,页都在这个List中。

LRU List:用来管理已经读取的页,当数据库刚启动时,LRU列表是空的,当需要从缓冲池中新增页时

  • 首先从Free List中查找是否有可用的空闲页
  • 若有则将该页从Free List中删除,放到 LRU List中。
  • 否则根据LRU算法,淘汰LRU List末尾的页,将该内存空间分配给新的页。

Flush List:在LRU列表中的页被修改后,称该页为脏页,即缓冲池中的页和磁盘上的页数据不一致。这时候数据库会通过CHECKPOINT机制将脏页刷新回磁盘,Flush List中就是脏页列表。当然,LRU List中也有脏页。

2.1.3 重做日志缓存

InnoDB存储引擎首先将重做日志信息放到这个缓冲区,然后以一定频率刷新到redo log文件。
刷新的时机:

  • Master Thread每秒刷新
  • 事务Commit时刷新
  • 重做日志缓存剩余空间小于1/2时刷新
2.1.4 额外的内存池

InnoDB存储引擎中,对内存的管理是通过一种称为内存堆的方式进行的,在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。

2.3 CHECKPOINT 技术

为了避免数据丢失,大多数数据库采用了Write Ahead Log的策略,事物提交时,先写redo log,再修改页。
Checkpoint技术目的是为了解决:

  • 缩短数据库的恢复时间
  • 缓冲池不够用时,将脏页刷新到磁盘
  • 重做日志不可用(因为重做日志是循环使用的)时,将脏页刷新到磁盘

2.4 Master Thread 工作方式

内部由多个循环组成:

  • 主循环
    • 每秒一次的操作:
      • 刷新日志缓冲到磁盘(总是)
      • 合并插入缓冲(可能)
      • 刷新脏页(可能)
      • 切换到后台循环(可能)
    • 每十秒一次的操作:
      • 刷新脏页(总是)
      • 合并至多5个插入缓冲(总是)
      • 刷新日志缓冲(总是)
      • 删除无效Undo页(总是)
  • 后台循环
    • 删除无用的Undo页(总是)
    • 合并20个插入缓冲(总是)
    • 调回到主循环(总是)
    • 不断刷新100个页直到符合条件(可能)
  • 刷新循环
  • 暂停循环

2.5 InnoDB关键特性

2.5.1 插入缓冲

对于非聚集索引的插入或更新操作,不是每次都直接插入索引页,而是先去判断要插入到的非聚集索引页是否在缓冲池中,若在,则直接插入,若不在,则先放到Insert Buffer对象中。然后再以一定频率进行Insert Buffer和辅助索引页子节点的merge操作。

  • 使用条件
    • 索引是辅助索引
    • 索引不是唯一的
  • 缺点
    • 如果发生宕机,可能有大量Insert Buffer未合并,恢复时间长。
    • 写密集的情况,插入缓冲会占用太多的缓冲池内存。
  • 内部实现
    • Insert Buffer内部是一颗B+树,全局只有一颗,维护所有表的辅助索引。
    • 非页节点存的是search key
    • 当一个辅助索引要插入到索引页,首先看看缓冲池有没有该页,有则直接插入,没有就构造一个search key 去查B+树。
    • Insert Buffer Bitmap记录索引页的可用空间。
  • 合并时机
    • 辅助索引页被读取到缓冲池时
    • Insert Buffer Bitmap页追踪到该辅助索引页已无可用空间时
    • Master Thread每10秒合并一次插入缓冲
2.5.2 两次写

在应用重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是double write。举个例子来说,如果操作系统将页写入磁盘的时候发生了崩溃,该页损坏,在恢复时,InnoDB存储引擎可以从共享表空间中的doublewrite中找到副本,将其复制到表空间文件,再应用redo log文件。

  • doublewrite的构成:
    • 2MB的 doublewrite buffer(内存中)
    • 2MB的 共享表空间中的连续128页(磁盘中)
  • doublewrite刷新脏页的原理:
    将脏页刷新到磁盘之前,会先写入doublewrite buffer,然后通过该buffer分两次写,一次写到共享表空间的物理磁盘,一次写到数据文件的物理磁盘。
2.5.3 自适应哈索引

如果建立哈希索引可以带来速度提升,则建立哈希索引,这就是自适应哈希索引。
他是通过缓冲池的B+树页构造而来的。

2.5.4 异步IO

用户可以在发出一个IO请求后立即发出下一个,不需要等待上一个完成。
这就是AIO,所有IO请求发送完毕,等待所有IO操作完成。
AIO可以进行IO Merge操作,磁盘的写入操作都是AIO完成的。

2.5.5 刷新邻接页

刷新脏页同一个区的邻接页。

猜你喜欢

转载自blog.csdn.net/kukubao207/article/details/88544122