MYSQL技术内幕-innoDB存储引擎 第二章 InnoDB存储引擎
后台线程
1 master thread
核心后台线程,将缓冲池数据异步刷新到磁盘,保证数据一致性,脏页的刷新,合并插入缓冲,不同版本功能略有不同
2 IO thread
大量使用AIO处理IO请求,分别是write、read、insert buffer、log IO thread四种,可以用参数配置
3 purge thread
1.1版本后引入,回收已经使用并分配的undo页
4 page cleaner thread
1.2.X版本后引入,脏页刷新操作
内存
1 缓冲池
内存区域
读取页时,先判断是否在缓冲池中,如果不在,将页从磁盘读取到缓冲池。
修改页时,先修改缓冲池中的页,再根据checkpoint机制刷新回磁盘
缓存的数据页类型:索引页,数据页,undo页,插入缓冲,自适应哈希索引,锁信息,数据字典信息
1.0.x版本后,可以配置多个缓冲池实例,每个页根据哈希值平均分配到不同的缓冲池实例中
2 LRU List、Free List和Flush List
缓冲池根据LRU(最近最少使用算法)来管理页,称做LRU list列表
页默认大小为16k
innnodb对LRU算法有优化,新页,不是放首部,而是放入midpoint(5/8)位置,midpoint之前是new列表,之后是old列表,new列表为活跃热点数据
有参数来控制,新页读取到mid位置后,多久会加入new列表
空闲页称作 free list列表
1.0.x后支持压缩页功能,16k的页可以压缩到1k、2k、4k和8k,通过unzip_LRU列表管理
LRU list包含unzip_LRU 列表
unzip_LRU对不同压缩页大小的页进行分别管理
如果需要4k大小的页,过程如下:
(1) 检查4k的unzip_LRU 列表,看是否有可用的空闲页
(2) 如果有,直接使用
(3) 没有,检查8k的unzip_LRU 列表
(4) 如果有,将页分成2个4k,放到4k的unzip_LRU 列表
(5) 没有,申请一个16k的页,分成一个8k,2个4k,放入对应的unzip_LRU 列表中
LRU列表中的页被修改后,称该页为脏页,即缓冲池中的页和磁盘中的页的数据不一致,Flush列表中的页为脏页列表,
脏页即存在LRU列表中,也存在Flush列表中
LRU列表用来管理页的可用性,Flush列表用来管理将页刷新回磁盘
3 重做日志缓冲
此区域在缓冲池之外,innodb先将重做日志信息放入这个缓冲区,然后按照一定频率将其刷新到重做日志文件,默认为8M,可由参数配置
下列三种情况会刷新重做日志缓冲:
(1) Master Thread 每一秒将重做日志缓冲刷新到重做日志文件
(2) 每个事务提交会刷新
(3) 重做日志缓冲池小于1/2时,会刷新
4 额外的内存池
在对一些数据结构本身的内存进行分配时,需要额外的内存池进行申请
checkpoint技术
缓冲池中页的版本比磁盘新,叫做脏页
事务数据库普遍采用write ahead log 策略,当事务提交时,先写重做日志,再修改页,出错时,通过重做日志来恢复数据
innoDB通过LSN来标记版本,LSN是8字节的数字,每个页有LSN,重做日志有LSN,Checkpoint也有LSN
有两种checkpoint:sharp Checkpoint和fuzzy Checkpoint
sharp Checkpoint发生在数据库关闭时,将所有脏页刷新回磁盘
fuzzy Checkpoint只刷新部分脏页
以下情况会发生fuzzy Checkpoint:
(1) Master Thread,差不多以每秒或每十秒的速度,异步从缓冲池的脏页列表刷新一定比例的页
(2) innoDB保证差不多有100个空闲页可用,如果没有将移除LRU列表尾端的页,如果其中有脏页,需要进行checkpoint。1.2.x之前由master thread执行,之后由page cleaner执行,可配置可用页数量
(3) 重做日志不可用时,从脏页列表中刷新部分回磁盘。为了保证重做日志可以循环使用,mysql5.6之后,由单独的page cleaner threa执行
(4) 脏页太多,强制checkpoint。1.0.x之前默认90%,之后默认75%
Master Thread 工作方式
1 1.0.x版本之前的master thread
最高优先级线程,由多个循环组成,主循环(loop),后台循环(background loop),刷新循环(flush loop),暂停循环(suspend loop),根据数据库运行状态在循环中切换
主循环有两个主要操作:
每秒操作:
(1) 重做日志缓冲刷新到重做日志文件,即使事务还没有提交
(2) 如果当前一秒IO次数小于5次,执行合并插入缓冲
(3) 脏页比例超过配置值,刷新脏页
(4) 如果当前没有用户活动,切换到background loop
每十秒操作:
(1) 如果过去十秒内磁盘IO操作小于200次,innoDB会认为当前有足够的磁盘io操作能力,因此将100个脏页刷新到磁盘
(2) 合并插入缓冲
(3) 将日志缓冲刷新到磁盘
(4) 删除无用的undo页
(5) 刷新100个脏页
后台循环操作:
(1)删除无用的undo页
(2)合并20个插入缓冲
(3)跳回到主循环
(4)不断刷新100个页直到符合条件,跳转到刷新循环
如果刷新循环也没什么事情,跳转到暂停循环
2 1.2.x版本之前的master thread
添加参数配置,优化性能
3 1.2.x版本的master thread
分离出page cleaner thread刷新脏页,减轻master thread工作,提高并发性
innoDB关键特性
1 插入缓冲
通常行记录的插入顺序是按照主键递增的顺序进行插入,一般是顺序的,不需要随机读取。
但是非聚集索引叶子节点的插入不是顺序的,innoDB设计了Insert buffer,对非聚集索引的插入或更新,先判断插入的非聚集索引页是否在缓冲池中,如果在,直接插入,如果不在,放入insert buffer,
然后按照一定的频率和情况进行insert buffer和辅助索引页子节点的merge合并操作,提高性能
使用insert buffer需要满足两个条件:
(1)索引是辅助索引
(2)索引不唯一,因为插入缓冲时,如果去查找判断记录是否唯一,又会发生离散读取的情况
1.0.x版本后,insert buffer升级为change buffer,可以对insert,delete,update都进行缓冲,分别是insert buffer,delete buffer,purge buffer,依然适用非唯一的辅助索引
2 两次写
doublewrite两次写提高数据页的可靠性
由两部分组成:
(1)内存中的doublewrite buffer,2M
(2)物理磁盘上共享表空间中的128个页,分成2个区,同样是2M
在刷新脏页时,先复制到doublewrite buffer,再分两次,每次1M顺序写入共享表空间的物理磁盘上,再调用fsync函数,同步磁盘
3 自适应哈希索引
innoDB会监控表上各索引页的查询,如果观察到建立哈希索引可以提升速度,就会建立哈希索引,称为自适应哈希索引
AHI是通过缓冲池的B+树页构建而来,因此速度很快
4 异步IO
1.1.x版本之前AIO通过代码来模拟实现,之后由内核级别AIO支持,称为Native AIO
5 刷新邻接页
刷新一个脏页时,会检测该页所在区的所有页,如果是脏页,一起刷新,将多个io写入操作,合并为一个
可由参数配置是否开启

浙公网安备 33010602011771号