MySQL技术内幕InnoDB存储引擎(二)——InnoDB存储引擎
1.概述
是一个高性能、高可用、高扩展的存储引擎。
2.InnoDB体系架构

InnoDB存储引擎主要由内存池和后台线程构成。
其中,内存池由许多个内存块组成,作用如下:
- 维护所有进程和线程需要访问的内部数据结构。
- 缓存磁盘上的数据,提高处理器读取速度,当数据被修改的时候也是先修改这里的数据,再被后台线程写到内存上去。
- 重做日志(redo log)缓冲。
后台线程的主要作用:
- 负责刷新内存池中的数据,以保证缓冲池中数据是最近的数据。
- 将缓冲中的数据刷新到磁盘上。
- 保证数据库发生异常的时候 ,数据库恢复到原先正常的状态。
后台线程
后台线程由很多类型,主要包括:
- Master Thread
最核心的后台线程,主要负责将缓冲池的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲、undo页的回收。 - IO Thread
InnoDB中大量使用了AIO来处理些的IO请求,提高数据库性能,这个线程的作用就是负责这些IO的回调。 - Purge Thread
用来已经使用并分配的undo 页。 - Page Cleaner Thread
减轻master线程的工作,将脏页的刷新操作放到了这个线程里单独完成。
内存
缓冲池
用于弥补CPU和磁盘速度差距太大的问题,CPU直接操作缓冲,然后由其他线程将在缓冲和磁盘之间做衔接。
缓冲池中的数据类型有索引页、数据页、undo页、插入缓冲、自适应哈希索引、锁信息和数据字典信息等。

LRUList 、Free List 和 Flush List
- LRU列表是用来管理已经被读取的数据页。
- Free列表是用来存储没有被使用的空闲页。
- Flush列表用来存储被修改过的脏页,脏页既存在于LRU列表,也存在于Flush列表。LRU列表管理缓冲池中页的可用性,二Flush列表管理将页刷新回磁盘,二者不影响。
重做日志缓冲
线程先将重做日志放到这个缓冲区,然后将按一定频率将其刷新到重做日志文件。额外的内存池
数据结构本身的内存进行分配的时候,先从额外的内存池中进行申请,这里不够,才从缓冲池里申请。
InnoDB缓冲池的LRU机制
朴素的LRU就是利用一个先进先出的队列,将最近用的使用的页放在队列的前端,最久远使用的页就会被排挤到后面,当缓冲池满了的时候,就将后面的页出队。
LRU的作用
提高缓冲区的利用率和降低CPU读取数据的总时间。每次CPU读取数据,会先去缓冲池里找,如果命中了,就直接提交;如果没有,就会去磁盘里提取,然后存储在缓冲区。因为缓冲池的大小是有限的,只能让部分数据存在里面,LRU算法就是确定哪些数据该留在缓冲区,哪些数据该被丢掉。
InnoDB的LRU优化
InnoDB对传统的LRU算法做了一些优化。在LRU队列中加入了midpoint位置,对于新加入的页,不会被直接放大列表头部,而是插入到midpoint的位置,一般默认位置是5/8长度处。midpoint前面的队列称为热点数据,而后面的就是old数据。
InnoDB通过一个时间参数,规定将读取到页等待多久的时间就会被加入到LRU队列的热点部分。
为什么需要加入midpoint?
如果采用朴素的LRU算法,将新添加的页直接放到头部,这样,可能会将热点的数据挤出去,从而降低了效率。通过加入midpoint,可以将热点的数据一直维持在midpoint之前的位置,将不常用的数据放在之后,这样,不常用的数据更有可能被先丢出去啊。
而新添加的数据还不知道是不是一个热点的数据,所以先放在midpoint位置上,然后通过midpoint和时间参数的配合,就能判断它是不是热点的。这样热点的数据就尽量不会被刷出。
undo log 和 redo log
在上面出现了undo log 和redo log 两个内容,在这里解释区分一下。
数据库通常借助日志来实现事务,常见的有undo log、redo log,undo/redo log都能保证事务特性,undolog实现事务原子性,redolog实现事务的持久性。
undo log
记录中存储的是老版本数据,当一个旧的事务需要读取数据时,为了能读取到老版本的数据,需要顺着undo链找到满足其可见性的记录。redo log
就是保存执行的SQL语句到一个指定的Log文件,当mysql执行数据恢复时,重新执行redo log记录的SQL操作即可。
作用:
- 数据持久化
redo log占满的时候,就会将相应的脏页写到内存,然后释放log。 - 数据恢复
如果出现宕机,就能重新执行redo log中的语句,恢复缓存中的数据。
3.Checkpoint 技术
数据库线程需要将脏页从缓存池中刷新到磁盘,如何控制刷新的时间和频率对数据库的性能和防止数据丢失就很重要。
作用
- 缩短数据库的恢复时间。
- 缓冲池不够用的时候,将脏页刷新到磁盘。
- 重做日志不可用的时候,刷新脏页。
具体的就是每次刷新多少脏页到磁盘,每次读取哪些脏页,什么时候出发刷新。
具体实现
InnoDB将CheckPoint分为两种:
- Sharp CheckPoint
用于在数据库关闭的时候将所有脏页都刷新回磁盘。也可以设置运行的时候使用 Sharp CheckPoint,但是这样回降低数据库的可用性。 - Fuzzy CheckPoint
只刷新部分脏页。
Fuzzy CheckPoint的发生条件
- Master Thread CheckPoint
这个检查点由Master线程发起,频率一般是每秒或者每十秒。是异步的,不会阻塞用户查询线程。 - Flush_LRU_List CheckPoint
需要保证LRUList中一直有100个空闲页,如果没有,就要将尾部的页移除,如果这些页中有脏页,这个检查点起作用了。 - Async/Sync Flush CheckPoint
指重做日志文件不够的情况下,需要将一些页刷新回磁盘,这样就能释放一部分重做日志的空间。此时的脏页是从脏页列表中获取的。 - Dirty Page too much Checkpoint
脏页数量太多,就强制执行检查点。
4.Master Thread 工作方式
由多个循环组成,包括主循环、后台循环、刷新循环和暂停循环。
主循环
主循环包括两个部分:每秒一次的操作和每十秒一次的操作。
每秒一次的操作包括:
- 日志缓冲刷新到磁盘(总是)。
- 合并插入缓冲(可能)。
- 最多刷新100个InnoDB的缓冲池中的脏页到磁盘(可能)。
- 日过没有用户活动,则切换到background loop(可能)。
所谓可能,就是不会每次都发生的操作。
每十秒一次的操作包括:
- 刷新100个脏页到磁盘(可能)。
- 至多合并5个插入缓冲(总是)。
- 将日志缓冲刷新到磁盘(总是)。
- 删除无用的undo页(总是)。
- 刷新100个或者是10个脏页的磁盘(总是)。会根据脏页比例控制刷新数量。
后台循环
如果没有用户活动或者数据被关闭了,就会切换到这个循环。
执行的操作包括:
- 删除无用的undo页(总是);
- 合并20个插入缓冲(总是;
- 跳回到主循环(总是);
- 不断刷新100个页直到符合条件(可能,跳转到刷新循环中完成)。
线程挂起
如果刷新循环都没有事情可以做,就会被切换到暂停循环,将master thread挂起。
版本改进
之前的刷新数量都是硬编码,是写死的。就会出现刷新数量低,线程忙不过来的问题。
后来改进这个问题,将刷新的数量与合并插入缓冲的数量设置为百分比,根据系统性能做出更改。还有就是自适应刷新,根据脏页的比例,控制刷新频率。
对于脏页的刷新操作,被从master线程中分离到了单独的page cleaner线程中了。
5.InnoDB关键特性
插入缓冲
Insert Buffer
解决问题:对于使用非聚集索引,插入操作不再是顺序的,需要离散地访问非聚集索引页,由于随机读取导致插入操作的性能下降。
目的:提高非聚集索引插入的性能。
实现原理:对于非聚集索引的插入和更新操作,先判断插入的非聚集索引页是不是在缓冲池中,如果在,就直接插入;如果不在,就先放到一个插入缓冲对象,标记为已插入,然后就等待到以后以一定频率和情况进行真正的插入缓冲和辅助索引页子节点的合并操作。这样可以将多个插入合并到一个操作中,大大提高了非聚集索引的性能。
使用插入缓冲需要两个条件:
- 索引是辅助索引。
- 索引不是唯一的。
Change Buffer
插入缓冲的升级版。
包括Insert Buffer、Delete Buffer、Purge Buffer,分别对应INSERT DELETE UPDATE操作的缓冲。
对记录进行UPDATE操作可能分为两个过程:标记已删除,真正删除记录。
Insert Buffer 内部实现
数据结构就是一棵B+树。
当辅助索引需要插入到页的时候,如果这个页不在缓冲池中,那么引擎就先构造一个search key,接下来查村Insert Buffer这棵B+树,然后将这个记录插入到树的叶子节点中去。
叶子节点的信息包括记录的表空间ID,页所在的偏移量,记录的插入顺序等。
缓冲中的记录如何合并到真正的辅助索引中呢?
三种情况回进行合并操作:
- 辅助索引页被读取到了缓冲池当中;
- 辅助索引页已经无可用空间;
- 主循环中的合并。
两次写
目的:提高数据的页的可靠性。
工作原理:对缓冲池中的脏页进行刷新的时候不会直接写到磁盘,而是先将脏页复制到内存的doublewrite buffer中,然后通过这个buffer分两次写到共享表空间的物理磁盘上,然后再同步磁盘。

自适应哈希索引
目的:一般通过B+树来查询定位页,查询次数取决于树的高度,一般为三到四层,也就是要查三到四次,而通过哈希索引就只需要查一次就能定位到数据。但是不能为所有数据都建立哈希索引,开销上可能划不来。
作用:引擎对表上各项索引进行查询,如果观察到的建立哈希索引可以带来速度提升,就建立哈希索引,这就是自适应哈希索引。
InnoDB存储引擎会根据访问的频率和模式来自动为某些热点页建立哈希索引。
异步IO
提高磁盘的操作性能,当前的数据库都是采用异步IO来操作磁盘。
刷新邻接页
工作原理:当刷新到一个脏页的时候,存储引擎就会顺便检测该页所在区的所有页,如果存在脏页,就一起刷新了,这样可以将多个IO合并为一个IO进行操作,大大提高对机械磁盘的操作性能。
总结
通过这一节内容,很好地理解和总结了InnoDB的相关知识,尤其是LRU、插入缓冲部分,如果学习过操作系统,那么将会对内存管理相关等知识得到一个更全面和深刻的理解。
MySQL技术内幕InnoDB存储引擎(二)——InnoDB存储引擎的更多相关文章
- MySQL技术内幕读书笔记(二)——InnoDB存储引擎
目录 InnoDB存储引擎 InnoDB存储架构 Checkpoint技术 Master Thread 工作方式 InnoDB关键特性(放一下,感觉看后面,再看总结吧) InnoDB存储引擎 Inno ...
- 《MySQL技术内幕:InnoDB存储引擎(第2版)》书摘
MySQL技术内幕:InnoDB存储引擎(第2版) 姜承尧 第1章 MySQL体系结构和存储引擎 >> 在上述例子中使用了mysqld_safe命令来启动数据库,当然启动MySQL实例的方 ...
- 《mysql技术内幕 InnoDB存储引擎(第二版)》阅读笔记
一.mysql架构 mysql是一个单进程多线程架构的数据库. 二.存储引擎 InnoDB: 支持事务 行锁 读操作无锁 4种隔离级别,默认为repeatable 自适应hash索引 每张表的存储都是 ...
- Mysql技术内幕——InnoDB存储引擎
Mysql技术内幕——InnoDB存储引擎 http://jingyan.baidu.com/article/fedf07377c493f35ac89770c.html 一.mysql体系结构和存储引 ...
- mysql技术内幕InnoDB存储引擎-阅读笔记
mysql技术内幕InnoDB存储引擎这本书断断续续看了近10天左右,应该说作者有比较丰富的开发水平,在源码级别上分析的比较透彻.如果结合高可用mysql和高性能mysql来看或许效果会更好,可惜书太 ...
- Mysql技术内幕之InnoDB锁探究
自7月份换工作以来,期间一直在学习MySQL的相关知识,听了一些视频课,但是一直好奇那些讲师的知识是从哪里学习的.于是想着从书籍中找答案.毕竟一直 看视频也不是办法,不能形成自己的知识.于是想着看书汲 ...
- 《[MySQL技术内幕:SQL编程》读书笔记
<[MySQL技术内幕:SQL编程>读书笔记 2019年3月31日23:12:11 严禁转载!!! <MySQL技术内幕:SQL编程>这本书是我比较喜欢的一位国内作者姜承尧, ...
- 读书笔记-《Mysql技术内幕》
MYSQL 技术内幕 Mysql体系 连接池组件 管理服务和工具 SQL接口 查询分析器 优化器 缓冲 插件式存储引擎 物理文件 存储引擎 InnoDB(默认引擎) 支持事务 行锁设计 多版本并发控制 ...
- MySQL技术内幕(一)
MySQL技术内幕 2. InnoDB存储引擎 2.1 InnoDB存储引擎概述 特点:行锁设计.支持MVCC.支持外键.提供一致性非锁定读 2.2 InnoDB体系架构 2.2.1 后台线程 Inn ...
- 好书推荐之Mysql三剑客 :《高性能Mysql》、《Mysql技术内幕》、《数据库索引设计与优化》
Mysql三剑客系列书籍: 大佬推荐 首先推荐<高性能 MySQL>,这本书是 MySQL 领域的经典之作,拥有广泛的影响力.不但适合数据库管理员(DBA)阅读,也适合开发人员参考学习.不 ...
随机推荐
- Scrum转型(一) 为什么敏捷和Scrum
1.1 为什么敏捷 由于传统的瀑布模型管理方法无法满足现代某些软件产品开发过程的特点,我们需要使用敏捷的方法(例如,Scrum是一个让我们关注于在短时间里交付高质量商业价值的敏捷框架). 需求频繁变动 ...
- 12.java设计模式之代理模式
基本介绍: 代理模式(Proxy)为一个对象提供一个替身,以控制对这个对象的访问.即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能,想在 ...
- 无所不能的Embedding4 - Doc2vec第二弹[skip-thought & tf-Seq2Seq源码解析]
前一章Doc2Vec里提到,其实Doc2Vec只是通过加入Doc_id捕捉了文本的主题信息,并没有真正考虑语序以及上下文语义,n-gram只能在局部解决这一问题,那么还有别的解决方案么?依旧是通用文本 ...
- SQL Server 常用近百条SQL语句(收藏版)
1. sqlserver查看实例级别的信息,使用SERVERPROPERTY函数 select SERVERPROPERTY ('propertyname') 2. 查看实例级别的某个参数XX的配置 ...
- SMBv3远程代码执行漏洞复现(CVE-2020-0796)
漏洞基本信息 服务器消息块(SMB),是一个网络通信协议,用于提供共享访问到文件,打印机和串行端口的节点之间的网络上.它还提供了经过身份验证的进程间通信机制.SMB的大多数用法涉及运行Microsof ...
- Windows SMBv3 CVE-2020-0796 漏洞分析和l漏洞复现
0x00 漏洞描述 漏洞公告显示,SMB 3.1.1协议中处理压缩消息时,对其中数据没有经过安全检查,直接使用会引发内存破坏漏洞,可能被攻击者利用远程执行任意代码.攻击者利用该漏洞无须权限即可实现远 ...
- python-网络安全编程第六天(threading多线程模块&Queue模块&subprocess模块)
前言 昨天晚上9点多就睡了 2点起来没睡意... 那就学习吧emmmm ,拿起闲置几天的python课程学习.学习到现在5.58了 总结下 继续开始学习新的内容 多多线程? 线程(英语:thread) ...
- Vue3.0 响应式数据原理:ES6 Proxy
Vue3.0 开始用 Proxy 代替 Object.defineProperty了,这篇文章结合实例教你如何使用Proxy 本篇文章同时收录[前端知识点]中,链接直达 阅读本文您将收获 JavaSc ...
- 如何使用系统清理缓存软件优化MacBook
在我们使用我们的Mac一定的时间后,总是不可避免的出现Mac内存不足的情况,所以清理垃圾软件也就成为了我们电脑里必不可少的软件.苹果软件商店中有很多各有不同的清理垃圾软件,但我们往往很难从这一大堆软件 ...
- jsp自定义错误页
1.在可能出错页面的Page标签上errorPage="/Error.jsp"指定错误页 2.Error,jsp的page标签中isErrorPage="true&quo ...