一、后台线程
MasterThread
- 主线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性
- 脏页的刷新、合并插入缓冲、undo页的回收等
IO Thread
- AIO, 读、写、插入、日志线程
Purge Thread
- 回收分配Undo页线程
Page Cleaner Thread
- 页清理线程,InnoDB1.2.X版本中引入的,将原来版本中脏页刷新操作都放到单独线程完成
二、内存
缓冲池
通过检查点checkpoint的机制刷新回磁盘,以一定的频率,从而提升数据库的整体性能
缓冲池中缓存的数据页类型
- 索引页
- 数据页
- undo页
- 插入缓冲
- 自适应哈希索引
- InnoDB存储的锁信息
- 数据字典的信息
从InnoDB1.0.x版本开始,运行有多个缓冲池实列
LRU List、FreeList和Flush List
- 在InnoDB中缓冲池中的页大小默认为16KB,使用LRU List缓冲池进行管理
- LRU List中加入了midpoint位置,引入了innodb_old_blocks_time这个参数,也即页读取到mid后需要等待多久才能加入到LRU列表的热端
- InnoDB存储引擎从1.0.x开始支持压缩页的功能,也即原本的16KB页压缩为1KB、2KB、4KB、8KB。对于非16KB的页,采用unzip_LRU列表进行管理。通过伙伴算法进行内存分配
- 在LRU列表中的页被修改后,称该页为脏页,也即缓冲池中的页和磁盘中的页数据产生了不一致。此时数据库会通过checkpoint机制将脏页刷新回磁盘中。Flush列表中的页即为脏页的列表
重做日志缓冲
- redo log buffer,一般不会设置很大,因为一般情况下每1秒会将重做日志缓冲刷新到日志文件。在通常情况下,8M的重做日志缓冲池足以满足绝大部分应用。
- 触发场景
- Master Thread 每1秒将重做日志缓冲到重做日志文件
- 每个事务提交时会将重做日志缓冲刷新到重做日志文件
- 当重做日志缓冲池剩余小于1/2s时,重做日志缓冲刷新到重做日志文件
额外的内存池
三、checkpoint
缓冲池设计的目的是为了协调CPU速度和磁盘速度的鸿沟。
当前事务数据库普遍使用write aheead log策略
checkpoint解决以下问题
- 缩短数据库的恢复时间
- 缓冲池不够用时,将脏页刷新到磁盘
- 重做日志不可用时,刷新脏页
分为 Sharp Checkpoint、FuzzyCheckpoint,其中sharp Checkpoint发生在数据库关闭时将所有的脏页都刷回到磁盘,而Fuzzy Checkpoint发生在数据库运行时。
引入概念LSN,日志序列号,标记版本,8个字节
Fuzzy Checkpoint使用的场景
- Master Thread Checkpoint 主线程检查点,每秒或每10秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘,这个过程是异步的
- FLUSH_LRU_LIST Checkpoint 刷新LRU列表检查点,保证LRU列表需要100个空闲页,目前这个检查已经放在Page Cleaner线程中进行
- Aysnc/Sync Flush Checkpoint 异步/同步刷新检查点,checkpoint_age = redo_lsn -checkpoint_lsn
通过checkpoint_age和同步/异步刷盘的water_mark进行比较,出现下面情况: - 1)检查点age小于异步watermark,此时不需要进行刷盘
- 2)检查点age在同步异步检查点之间,触发异步刷新 Async Flush,从Flush列表刷新足够的脏页回磁盘
- 3)检查点age大于同步watermark,一般这种情况很少,除非设置的重做日志文件太小,并且进行类似加载数据的bulk insert操作。此时触发 Sync Flush
- 1.2.x版本开始,这部分已经放到了Page Cleaner线程中
- Dirty Page too much Checkpoint 脏页太多检查点
- innodb会强制刷新
四、MasterThread工作方式
之前InnoDB存储引擎最大只会刷新100个脏页到磁盘,合并20个插入缓冲。如果大于此情况时,master Thread将会忙不过来。这个问题由google工程师mark callaghan提出。
之后InnoDB对其进行了修改,提供了InnoDB Plugin参数:innodb_io_capacity参数,默认200,同时将刷盘脏页占缓冲的90%改成了75%
五、InnoDB关键特性
插入缓冲
- insert buffer ,当满足索引是辅助索引,同时索引不是唯一的时,InnoDB存储引擎会使用insert buffer
- 参数:IBUF_POOL_SIZE_PRE_MAX_SIZE
- change buffer,从1.0.x开始引入,innodb存储引擎可以对DML操作,insert、delete、update都进行缓冲
- 比如update操作分为两个过程:标记过程、操作过程
- Merge Insert Buffer
- 发生的场景
- 辅助索引页被读取到缓冲池时
- Insert Buffer Bitmap页追踪到该辅助页已无可用空间时
- Master Thread
两次写
- 在 应用重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是doublewrite
- 由两部分组成:内存中的doublewrite buffer,2MB,物理磁盘上共享表空间中连续的128页,即2个区,大小同样为2MB
自适应哈希索引
异步I/O
- Read Ahead方式的读取都是通过AIO实现的,脏页刷新
刷新邻接页
- 当刷新一个脏页时,InnoDB会检测该页所在区域是否存在相关的脏页,如果存在,则一并刷新到磁盘
整理的xmind如下:
参考:《MySQL技术内幕InnoDB存储引擎》 第二版 姜承尧