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写入操作,合并为一个

可由参数配置是否开启

 

posted @ 2019-07-03 15:14  褐色键盘  阅读(271)  评论(0)    收藏  举报