InnoDB 是事务安全的 MySQL 存储引擎,设计上采用了类似于 Oracle 数据库的架构。通常来说,InnoDB 存储引擎是 OLTP(在线事务处理) 应用中核心表的首选存储引擎。同时,也正是因为 InnoDB 的存在,才使 MySQL 数据库变得更有魅力




2.1 InnoDB 存储引擎概述

InnoDB 存储引擎最早由 Innobase Oy(现在已经被 Oracle 公司收购)公司开发,从 MySQL 5.5 版本后开始是默认的表存储引擎

该存储引擎是第一个完整支持 ACID 事务的 MySQL 存储引擎,其特点是行锁设计、支持 MVCC、支持外键、提供一致性非锁定读,同时被设计用来最有效地利用以及使用内存和 CPU

被许多大型网站使用,如 Google、Facebook、YouTube 等,这些都足以证明了 InnoDB 是一个高性能、高可用、高扩展的存储引擎




2.2 InnoDB 存储引擎的版本




2.3 InnoDB 体系架构

innodb存储引擎 java innodb的存储引擎_java


2.3.1 后台线程

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

1.Master Thread

Master Thread 是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲、UNDO 页的回收等

2.IO Thread

在 InnoDB 存储引擎中大量使用了 AIO(Async IO)来处理写 IO 的请求,这样可以极大提高数据库的性能,而 IO Thread 主要负责这些 IO 请求的回调(call back)处理

3.Purge Thread

事务被提交后,其所使用的 undolog 可能不再需要,因此需要 Purge Thread 来回收已经使用并分配的 undo

4.Page Cleaner Thread

Page Cleaner Thread 是在 InnoDB 1.2.下版本中引入的。其作用是将之前版本中脏页的刷新操作都放入到单独的线程中来完成。而其目的是为了减轻原 Master Thread 的工作及对于用户查询线程的阻塞,进一步提高 InnoDB 存储引擎的性能




2.3.2 内存

1、缓冲池

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

缓冲池简单来说就是一块内存区域,通过内存的速度来弥补磁盘速度相对较慢对数据库性能的影响

过程:在数据库进行读取页的操作,首先将从磁盘读取到的页存放在缓冲池中,这个过程称为将页 ”FIX“ 在缓冲池中。下一次再读取相同的页时,首先判断该页是否在缓冲池中。若在缓冲池中,称该页在缓冲池中被命中,直接读取该页。否则读取磁盘上的页

对于数据库中页的修改操作,则首先修改在缓冲池中的页,然后再以一定的频率刷新到磁盘上。这里需要注意的是,页从缓冲池刷新回磁盘的操作并不是在每次页发生要更新时触发,而是通过一种称为 Checkpoint 的机制刷新回磁盘。同样,这也是为了提高数据库的整体性能

具体来看,缓冲池中存放的数据页类型有:索引页、数据页、undo 页、插入缓冲、自适应哈希索引、InnoDB 存储的锁信息、数据字典信息等

InnoDB 中存储引擎中内存的结构情况:


innodb存储引擎 java innodb的存储引擎_java_02


从 InnoDB 1.0.x 版本开始,允许有多个缓冲池实例。每个页根据哈希值平均分配到不同缓冲池实例中。这样做的好处是减少数据库内部资源的竞争,增加数据库的并发处理能力。


2、LRU List、Free List 和 Flush List

通常来说,数据库中的缓冲池是通过 LRU(Latest Recent Used,最近最少使用)算法来进行管理的。即最频繁使用的页在 LRU 列表的前端,而最少使用的页在 LRU 列表的尾端。当缓冲池中不能存放新读取到的页时,将首先释放 LRU 列表中尾端的页

在 InnoDB 存储引擎中,缓冲池页的大小默认为 16KB,同样使用 LRU 算法对缓冲池进行管理。稍有不同的是 InnoDB 存储引擎对传统的 LRU 算法做了一些优化。

LRU 列表中的页被修改后,称该页为脏页,即缓冲池中的页和磁盘上的页的数据产生了不一致,这时数据库会通过 CheckPoint 机制将脏页刷新回磁盘,而 Flush 列表中的页即为脏页列表。需要注意的是,脏页即存在于 LRU 列表中,也存在于 Flush 列表中。LRU 列表用来管理缓冲池中页的可用性,Flush 列表用来管理将页刷新回磁盘,二者互不影响




2.4 Checkpoint 技术




2.5 Master Thread 工作方式




2.6 InnoDB 关键特性

InnoDB 存储引擎的关键特性包括

  • 插入缓冲
  • 两次写
  • 自适应哈希索引
  • 异步 IO
  • 刷新邻接页

上述这些特性为 InnoDB 存储引擎带来更好的性能以及更高的可靠性。


2.6.1 插入缓冲


2.6.2 两次写

如果说插入缓冲带给 InnoDB 存储引擎是性能上的提升,那么两次写带给 InnoDB 存储引擎的是数据页的可靠性。

有经验的 DBA 也许会想,如果发生写失效,可以通过重做日志进行恢复。这是一个办法。但是必须清楚的认识到,重做日志中记录的是对页的物理操作,如偏移量 800,写 ’aaa‘ 记录。如果这个页本身已经发生了损坏,再对其进行重做是没有意义的。这就是说,在应用重做日志之前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是两次写


doublewrite 由两部分组成,一部分是内存中的 doublewrite buffer ,大小为 2MB,另一部分是物理磁盘共享表空间中连续的 128 个页,即 2 个区,大小同样是 2MB。在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是会通过 memcpy 函数将脏页先复制到内存中的 doublewrite buffer,之后通过 doublewrite buffer 再分两次,每次 1MB 顺序地写入共享表空间的物理磁盘上,然后马上调用 fsync 函数,同步磁盘,避免缓冲写带来的问题。在这个过程中,因为 doublewrite 页是连续的,因此这个过程是顺序写的,开销不是很大。


innodb存储引擎 java innodb的存储引擎_存储引擎_03



2.6.3 自适应哈希索引

哈希是一种非常快的查找方法,在一般情况下这种查找的时间复杂度为 O(1) ,即一般仅需要一次查找就能定位数据。而 B+ 树的查找次数,取决于 B+ 树的高度,在生产环境中,B+ 树的高度一般为 3~4 层,故需要 3~4 次的查询。


InnoDB 存储引擎会监控对表上各索引页的查询。如果观察到建立哈希表可以带来速度提升,则建立哈希索引,称之为自适应哈希索引(Adaptive Hash Index,AHI)。AHI 是通过缓冲池的 B+ 树页构造而来,因此建立的速度很快,而且不需要对整张表建哈希索引,InnoDB 存储引擎会自动根据访问的频率和模式来自动为某些热点页建立哈希索引


AHI 有一个要求,即对这个页的连续访问模式必须是一样的



2.6.4 异步 IO

为了提高磁盘操作性能,当前的数据库系统都采用异步 IO(Asynchronous IO,AIO)的方式来处理磁盘操作。InnoDB 存储引擎亦是如此。

AIO 对应的是 Sync IO,即每进行一次 IO 操作,需要等待此次操作结束才能继续接下来的操作



2.6.5 刷新邻接页

其工作原理为:当刷新一个脏页时,InnoDB 存储引擎会检测该页所在区的所有页,如果是脏页,那么一起进行刷新。这样做的好处显而易见,通过 AIO 可以将多个 IO 写入操作合并为一个 IO 操作,故该工作机制在传统机械硬盘下有着显著的优势。
等待此次操作结束才能继续接下来的操作**。