InnoDB引擎
此文章是 《MySQL技术内幕:InnoDB存储引擎(第2版)》 一书的学习笔记,感兴趣的小伙伴可以自己买书学习。
InnoDB 中数据库和数据库实例的区别
在 mysql 中,数据库和数据库实例是有区别的,数据库指的是数据库文件,数据库实例是运行起来的数据库软件,用户通过数据库实例操作数据库,而非直接操作数据库。也就是说虽然数据库是文件,但是对数据库的一些操作并不一定就是很慢的磁盘IO。
InnoDB 是一个单进程多线程的数据库
InnoDB 是多线程的模型,通过下面的这些后台线程,对数据库进行操作。
- Master Thread 主要负责将缓存池中的数据异步刷新到磁盘。这个线程下有多种循环,InnoDB 根据不同的情况切换不同的循环
- 主循环 loop
- 后台循环 background loop
- 刷新循环 flush loop
- 暂停循环 suspendloop
- Io Thread ,InnoDB 通过 AIO 进行异步IO操作, Io Thread 负责处理这个异步 IO 的回调
- Purge Thread, InnoDB 1.1 版本后增加的, 负责在事务处理后,回收事务产生的 undolog
- Page Cleaner Thread, InnoDB 1.2 版本后增加的,负责刷新脏页。
InnoDB 内存分配
主要由下面几个部分组成
- 缓冲池
- LRU List、Free List和Flush List
- 重做日志缓存
- 额外的内存池,主要用来内存管理,内存管理也需要内存进行操作。
InnoDB 缓存池
InnoDB对数据的操作首先都是在缓冲池完成的,在查询的时候首先判断该页是否在缓冲池中。修改的时候先更新缓冲池中的页,然后通过 ckeckpoint 机制将数据页刷新回磁盘。缓存池中主要包含下面这些部分:
- 索引页
- 数据页
- undo 页
- 插入缓冲 insert buffer
- 自适应哈希索引 adaptive hash index
- 存储的锁信息 lock info
- 数据字典信息 data dictionary
InnoDB 的checkpoint 机制
正常数据发生修改时,数据库实例会先写入重做日志缓存,然后再写入磁盘。但是如果每一个缓存页发生更新时都马上写入磁盘,那么开销是特别大的,某些情况下会影响数据库实例的性能。所以只有当缓存池不够用的时候,再将缓存池中的脏页(与磁盘不一致的页)写入磁盘。这里 checkpoint 解决的问题主要是以下几点。
- 缩短数据库的恢复时间。 当服务器宕机时,服务器不需要重做所有的日志,只重做 checkpoint 之后的就可以
- 缓冲池不够用时,将脏页刷新到磁盘
- 重做日志不可用时,刷新脏页。比如重做日志很大了, 需要清理重做日志,在清理重做日志之前,需要将缓存池中的脏页刷新到当前重做日志的位置, 避免数据无法恢复。
InnoDB 的 AIO
前面提到了 InnoDB 是通过 AIO (Asyncchronous IO) 的方式进行磁盘操作, 和同步IO (Sync IO) 的区别在于,异步IO不用等上一次的操作结果返回就能立即进行下一个操作,比如同时发出10个IO请求然后再等待10个请求完成。AIO 还有一个好处是 InnoDB可以有选择性的合并IO, 比如AIO判断有多次IO请求操作的页是连续的,那么AIO就会合并到一个IO里。使用AIO据说可以使查询速度提高 75% 。
本作品采用《CC 协议》,转载必须注明作者和本文链接