MySQL技术内幕学习笔记
第二章 InnoDB存储引擎(一)
InnoDB是事务安全的MySQL存储引擎,是OLTP应用中核心表的首选存储引擎。Heikki Tuuri(1964年,芬兰赫尔辛基)是InnoDB存储引擎的创始人。
文章目录
1. InnoDB存储引擎概述
- InnoDB存储引擎最早由Innobase Oy公司开发,从MySQL 5.5版本开始是默认的表存储引擎
- 该存储引擎是第一个完整支持ACID事务的MySQL存储引擎
- 特点是 行锁设计、支持MVCC、支持外键、提供一致性非锁定读、同时被设计用来最有效地利用以及使用内存和CPU
2. InnoDB存储引擎的版本
版本 | 功能 |
---|---|
老版本InnoDB | 支持ACID、行锁设计、MVCC |
InnoDB 1.0x | 继承了上述版本所有功能,增加了compress和dynamic页格式(动态加载) |
InnoDB 1.1x | 继承了上述版本所有功能,增加了Linux AIO、多回滚段 |
InnoDB 1.2x | 继承了上述版本所有功能,增加了全文索引支持、在线索引添加 |
3. InnoDB体系结构
-
InnoDB存储引擎有多个内存块,负责如下工作:
- 维护所有进程/线程需要访问的多个内部数据结构
- 缓存磁盘上的数据,方便快速地读取,同时在对磁盘文件的数据修改之前在这里缓存
- 重做日志(read log)缓冲
-
后台线程的主要作用:
- 负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据
- 将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下InnoDB能恢复到正常运行状态
3.1 后台线程
InnoDB存储引擎是多线程的模型,因此其后台有多个不同的后台线程,负责处理不同的任务
后台线程 | 功能 |
---|---|
Master Thread | 一个核心的后台线程,**主要负责 ** 将缓冲池中的数据异步刷新到磁盘,保证数据的一致性(包括脏页的刷新、合并插入缓冲页的回收等) |
IO Thread | 在InnoDB存储引擎中大量使用了AIO(Async IO)来处理写IO请求,极大提高数据库的性能。IO Thread主要负责 将这些IO请求的回调(call back)处理 1.0x版本后使用 innodb_read_io_threads 和 innodb_write_io_threads 参数设置读写线程,读线程的ID总是小于写线程 |
Purge Thread | 事务被提交后,其所使用的undolog可能不在需要,Purge Thread来回收已经使用并分配的undo页 InnoDB1.2版本开始,InnoDB支持多个Purge Thread,目的是进一步加快undo页的回收(同时由于purge Thread需要离散地读取undo页,这样做能更进一步利用磁盘的随机读取性能) |
Page Cleaner Thread | 其 作用 是将之前版本中脏页的刷新操作都放入到单独的线程中来完成 目的 是减轻元Master Thread的工作及对于用户查询线程的阻塞,进一步提高InnoDB存储引擎的性能 |
mysql>SHOW ENGINE INNODB STATUS\G //观察InnoDB中的IO Thread
inoodb_purge_threads=4 //在MySQL配置文件中添加来启动独立的Purge Thread
3.2 内存
1. 缓冲池
由于InnoDB存储引擎时基于磁盘存储的,并将其中的记录按照页的方式进行管理,可以视为基于磁盘的数据库系统。通常可以使用 缓冲池技术 来提高数据库的整体性能,解决CPU速度与磁盘速度之间的鸿沟。
- 缓冲池就是一块内存区域,通过内存的速度来弥补磁盘速度较慢对数据库性能的影响。缓冲池的大小直接影响着数据库的整体性能。
- 读取页操作:首先将从磁盘读到的页存放在缓冲池中(将页“FIX"在缓冲池中),下次读到相应页时,首先判断该页是否在缓冲池中,若在称该页在缓冲池中被命中,直接读取。否则读取磁盘上的页
- 修改操作:首先修改在缓冲池中的页,然后以一定的频率刷新到磁盘上。(页从缓冲池刷新回磁盘的操作并不是每次页发生更新时触发,而是通过一种称为Checkpoint的机制刷新回磁盘),提高数据库整体性能
innodb_buffer_pool_size //缓冲池的配置设置
InnoDB内存数据对象如图所示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JQtf71E7-1625647581830)(D:\zhaojiahui20\Documents\md\InnoDB内存数据对象.jpg)]
- InnoDB1.0.x开始,允许多个缓冲池实例,每个页根据哈希值平均分配到不同缓冲池实例中。好处:减少数据库内部的资源竞争,增加数据库的并发处理能力。
innodb_buffer_pool_instances //配置缓冲池实例,默认为1
2. LRU List、Free List 和Flush List
-
数据库中的缓冲池是通过LRU(Lastest Recent Userd,最近最少使用)算法来进行管理的。
-
InnoDB存储引擎中,缓冲池中页的大小默认为16KB(对于非16KB的页,是通过unzip_LRU列表进行管理的)
-
InnoDB存储引擎对LRU做了优化,在LRU列表中加入了midpoint位置,midpoint之后的列表成为old列表,之前为new 列表,存储最为活跃的数据
innodb_old_blocks_pct //设置midpoint位置,默认为37 % innodb_old_bllocks_time //表示页读取到mid位置后需要等待多久才会被加入到LRU列表的热端
-
LRU列表用来管理已经读取的页。数据库刚启动该列表为空,这是页都存放在Free列表中。需要从缓冲池中分页时:首先在Free列表找是否有空闲页,有则将该页删除并放入到LRU列表中,否则根据LRU算法,淘汰LRU列表末尾的页,将该内存空间分配给新的页。
- 当页从LRU列表的old部分加入到new部分时,称为page made young
- 因为innodb_old_bloack_time设置而导致没有移动,称为page not made young
- Buffer pool hit rate变量表示缓冲池的命中率,通常不小于95%
-
InnoDB存储引擎从1.0x版本开始支持压缩页的功能,对于非16K的页通过unzip_LRU列表进行管理
-
unzip_LRU是怎样从缓冲池中分配内存的?
- 首先,在unzip_LRU列表中对不同压缩页大小的页进行分别管理
- 其次,通过伙伴算法进行内存的分配
-
需要从缓冲池中申请页为4KB的大小,其过程如下:
- 检查4KB的unzip_LRU列表,检查是否有可用的空闲页
- 如有,直接使用
- 否则,检查8KB的unzip_LRU列表
- 若得到空闲页,将页分成2个4KB页,存放到4KB的unzip_LRU列表
- 若得不到空闲页,从LRU列表中申请一个16KB的页,将页分为1个8KB的页,2个4KB的页,分别存放到对应的umzip_LRU列表中。
- LRU列表被修改后,称该页为脏页,即缓冲池中的页和磁盘上的页的数据产生了不一致。这是数据会通过CKECKPOINT机制将脏页刷新回磁盘,而Flush列表中的页即为脏页列表。
- 脏页即存在于LRU列表中,也存在与Flush列表中。LRU列表用来管理缓冲池中页的可用性,Flush列表用来管理将页刷新回磁盘。
- Modified db pages表示脏页的数量
3. 重做日志缓冲
- InnoDB存储引擎首先将重做日志信息先放到缓冲区,然后按一定频率将其刷新到重做日志文件
- 可由配置innodb_log_buffer_size控制,默认为8MB
- 重做日志文件在下列三种情况下会将日志缓冲中的内容刷新到外部磁盘的重做日志文件中、
- Master Thread每一秒将重做日志缓冲刷新到重做日志文件
- 每个事物提交时
- 当重做日志文件缓冲池剩余空间小于1/2时
4. 额外的内存池
- 在InnoDB存储引擎中,对内存的管理是通过一种称为内存堆(heap)的方式进行的。在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。
4. Checkpoint技术
-
为了避免数据丢失的问题,采用Write Ahead Log策略,即当事务提交时,先做重做日志,再修改页。(满足持久性的要求)
-
满足缓冲池可以缓存数据库中所有的数据并且重做日志可以无限增大,则不需要将缓冲池中页的新版本刷新回磁盘(很难实现)
-
Checkpoint(检查点)技术的目的解决以下问题:
- 缩短数据库的恢复时间
- 缓冲池不够用时,将脏页刷新到磁盘
- 重做日志不可用时,刷新脏页
-
当数据库宕机时,只需对checkpoint后的重做日志进行恢复,之前的已经刷新到磁盘中,缩短了恢复时间
-
InnoDB存储引擎内部有两种checkpoint
- Sharp Checkpoint:发生在数据库关闭时将所有的脏页都刷新回磁盘,默认方式,即参数innodb_fast_shutdown=1
- Fuzzy Checkpoint:只刷新一部分脏页
-
在InnoDB存储引擎中可能发生如下几种情况的Fuzzy CheckPoint:
- Master Thread Checkpoint:差不多以每秒或每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘
- FLUSH_LRU_LIST Checkpoint
- Async/Sync Flush Checkpoint:为了保证重做日志的循环使用的可用性
- Dirty Page too much Checkpoint:脏页的数量太多,导致InnoDB存储引擎强制进行Checkpoint
_LRU_LIST Checkpoint
- Async/Sync Flush Checkpoint:为了保证重做日志的循环使用的可用性
- Dirty Page too much Checkpoint:脏页的数量太多,导致InnoDB存储引擎强制进行Checkpoint