1. 内存池
由多个内存块组成,负责的工作如下:
- 维护所有进程 / 线程需要访问的多个内部数据结构
- 缓存磁盘上的数据,方便快速读取,同时在对磁盘文件的数据修改之前在这里缓存
- 重做日志(redo log)缓冲
- ....
2. 后台线程
- 作用
- 负责刷新内存池中的数据,保证缓冲池中的内存缓存是最近的数据。
- 将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下InnoDB 能恢复到正常运行状态
- 分类
- Master Thread
- 是一个非常核心的后台线程
- 主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性
- 脏页的刷新
- 合并插入缓冲(INSERT BUFFER)
- undo 页的回收
- ...
- IO Thread
- InnoDB 存储引擎中大量使用了AIO(Async IO)来处理写请求,这样可以极大的提高数据的性能
- IO Thread 的工作主要负责这些IO 请求的回调处理
- 分类
- write IO thread
- read IO thread(读线程的ID 总是小于写线程)
- insert buffer IO thread
- log IO thread
- Purge Thread
- 主要负责回收已经使用并分配的undo页(事务提交后,其所使用的undo log 可能不再需要)
- InnoDB 1.1 版本之前,purge 操作通过Master Thread 完成,InnoDB 1.1 开始使用单独的线程进行purge操作,而减轻Master Thread 的负荷,从而提高CPU 使用率以及提升存储引擎的性能
- InnDB1.2 开始支持多个Purge Thread ,目的是为了进一步加快undo页的回收
- Page Cleaner Thread
- InnoDB 1.2.x 版本引入,作用是将之前版本中的脏页刷新操作都放入到单独的线程中来完成
- 目的是减轻原Master Thread的工作及对于用户查询线程的阻塞
- 进一步提高InnoDB 存储引擎的性能
- Master Thread
3. 内存(内存池的组成单元)
![](https://img-blog.csdnimg.cn/d166bf44b2524bf2b67503ad944822a5.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAUXVuS3J5cw==,size_20,color_FFFFFF,t_70,g_se,x_16)
- 缓冲池
- 平衡磁盘速度和CPU 速度(就是一般的缓存的特点),从而提高数据库的整体性能
- 将页“FIX”到缓冲池中
- InnoDB 将表中的记录按照页的方式进行管理
- FIX 到缓冲池是指,当一个页之前从未读取过时,首先从磁盘中读取出来并放入缓冲池的过程
- 页在缓冲池中命中
- 当需要读取一页时,判断该页是否在缓冲池中,在则称为页在缓冲池中命中,并直接返回该页
- 页在缓冲池中未命中
- 当需要读取一页时,判断该页是否在缓冲池中,不在则称为该页在缓冲池中未命中,需要将页“FIX”到缓冲池
- 数据库中页的修改操作
- 首先修改在缓冲池中的页,然后再以一定的频率刷新到磁盘上
- 页从缓冲池刷新回磁盘的操作不是在每次页更新时触发,而实通过一种checkpoint的机制刷新回磁盘
- 数据库缓冲池大小直接影响数据库的整体性能
- 缓冲池中缓存的数据页类型
- 索引页
- 数据页
- undo页
- 插入缓存(insert buffer)
- 自适应哈希索引(adaptive hash index)
- InnoDB 存储的锁信息(lock info)
- 数据字典信息(data dictionary)
- 多个缓冲池实例
- InnDB 1.0.x 版本开始,允许有多个缓冲池实例
- 每个页根据哈希值平均分配到不同的缓冲池实例中
- 目的是为了减少数据库内部的资源竞争,增加数据库并发处理能力
- LRU List、Free List 和 Flush List
- 缓冲池是通过LRU 算法管理的
- 最频繁使用的页放在LRU List 的前端,而最少使用的页在LRU List的末尾
- 当缓存池已经满时,首先释放LRU List 末尾的页
- InnoDB 对LRU 算法的优化
- 在LRU List 中加入midpoint 位置,新读取的页不直接放在List 的首部,而是先放入到List 的 midpoint 位置。这个算法称为——midpoint insertion strategy。目的是为了防止热点数据被挤出缓存,常见的操作为索引或数据的扫描操作。
- InnoDB 进一步引入innodb_old_blocks_time 参数来管理LRU List,用于表示页读取到mid 位置后需要等待多久才会被加入到LRU List 的热端
- LRU List 不对自适应哈希索引、Lock信息、Insert Buffer等页进行管理
- 压缩页的管理——unzip_LRU
- InnDB 1.0.x 开始支持压缩页的功能,对非16KB的页使用unzip_LRU进行管理
- unzip_LRU List 对不同压缩页大小的页进行分别管理
- 通过伙伴算法进行内存分配,以4KB 的页为例
- 检查4KB 的unzip_LRU List,检查是否有可用的空闲页
- 若有,则直接使用
- 否则,检查8KB 的 unzip_LRU List
- 若能得到空闲页,将页分成2 个4KB页,存放到4KB 的unzip_LRU列表
- 若不能得到空闲也,从LRU 列表中申请一个16KB 的页,将页分为一个8KB的页和2个4 KB的页,分别存放到对应的unzip_LRU列表中
- Free List 用于缓冲池的空闲空间管理
- Flush List 用于脏页
- 脏页既存在于LRU List 中,也存在于Flush List 中
- LRU List 用来管理缓冲池中也的可用性,Flush List 用来管理将页刷新回磁盘,二者互不影响
- 缓冲池是通过LRU 算法管理的
- redo 日志缓冲
- redo 日志信息先放入这个缓冲区,然后按一定频率将其刷新到redo 日志文件
- redo 日志缓冲的大小不用很大,只需保证每秒产生的事务量在这个缓冲大小之内即可
- redo 日志缓冲刷新到磁盘中的redo 日志文件的时机
- Master Thread 每一秒将redo 日志缓冲刷新到redo 日志文件
- 每个事务提交时会将redo 日志缓冲刷新到redo 日志文件
- 当redo 日志缓冲剩余空间小于1 / 2时,redo 日志缓冲刷新到redo 日志文件
- 额外的内存池