Mysql之InnoDB中线程详解

InnoDB存储引擎是多线程的模型,因此其后台有多个不同的后台线程,负责处理不同的任务。主要分为:Master Thread、IO Thread、Purge Thread和Page Cleaner Thread

Master Thread

通过名字就可以看出,Master Thread是非常重要的线程,维护着InnoDB存储引擎中的大多数的操作,因为此线程的效率也直接影响着InnoDB的整体性能。所以,不同InnoDB版本的改进也主要针对此线程的功能进行的。InnoDB1.0.x版本之前 Master Thread的功能奠定了此线程操作的基础,后面的1.0.x、1.1.x和1.2.x的改动都是在其之前功能的基础上进行的,所以我们有必要先了解下1.0.x版本之前 Master Thread线程有哪些操作,然后再了解后续的版本中是怎么改进的。

Master Thread具备最高的线程优先级。其内部有多个循环(loop)组成:主循环(loop)、后台循环(backgroup loop)、刷新循环(flush loop)、暂停循环(suspend loop)。Master Thread会根据数据库的状态在这些循环之间切换。Loop被称为主循环,因为大多数的操作都是在这个循环中,其中有两大部分的操作----每秒钟的操作每10秒的操作

每秒钟的操作包含以下内容

  • 重做日志缓冲刷新到磁盘,即使这个事务还没有提交(总是)
  • 合并插入缓冲(可能)
  • 至多刷新100个InnoDB的缓冲池中的脏页到磁盘(可能)
  • 如果当前没有用户活动,则切换到BackGround loop(可能)

我们简单的解读一下“每秒中的操作”:
即使某个事务还没有提交,InnoDB存储引擎仍然每秒会将重做日志缓冲中的内容刷新到重做日志文件。这可以很好的解释为什么再大的事务提交的时间也是很短的。

合并插入缓冲并不是每秒都会发生的。InnoDB存储引擎会判断当前一秒内发生的IO次数是否小于5次,如果小于5次,InnoDB认为当前IO的压力很小,可以执行合并插入缓冲的操作。

刷新100个脏页也不是每秒都会发生的。InnoDB通过判断当前缓冲池中脏页的比例(buf_get_modified_ratio_pct)是否超过了配置文件中的innodb_max_dirty_pages_pct这个参数(默认是90,代表90%),如果超过了这个阈值,InnoDB认为需要做磁盘同步的操作,将100个脏页写入磁盘中。

每10秒的操作包含以下内容

  • 刷新100个脏页到磁盘(可能的情况下)
  • 合并至多5个插入缓冲(总是)
  • 将重做日志缓冲刷新到磁盘(总是)
  • 删除无用的undo页(总是)
  • 刷新100个或者10个脏页到磁盘(总是)

我们来解读一下“每十秒操作”的整个过程:
首先InnoDB会先判断过去十秒之内磁盘的IO操作是否小于200次,如果是,InnoDB认为当前有足够的磁盘IO操作能力,因此将100个脏页刷新到磁盘。接着,InnoDB会合并插入缓冲。不同于“每秒一次操作”时可能发生的合并插入缓冲操作,这次的合并插入缓冲一定会发生。之后,InnoDB会再进行一次重做日志缓冲刷新到磁盘的操作。

接着InnoDB会进行一步执行full purge的操作,即删除无用undo页。但是在删除前会判断是否有查询操作需要读取之前版本的undo信息,如果没有,这可以删除,但每次最大回收20个undo页。

然后,InnoDB会判断缓冲池中脏页的比例(buf_get_modified_ratio_pct),如果有超过70%的脏页,则刷新100个脏页到磁盘,如果脏页比例小于70%,则只需刷新10个脏页到磁盘。

若当前没有用户活动(数据库空闲时)或者数据库关闭,就会切换到background loop。background loop会执行一下操作:

  • 删除无用的Undo页(总是)
  • 合并20个插入缓冲(总是)
  • 跳回到主循环(总是)
  • 不断刷新100个页直到符合条件(可能,跳转到flush loop中完成)

若flush loop中也没有什么事情可以做了,InnoDB会切换到suspend_loop,将Master Thread 挂起,等待事件发生。若用户启用了InnoDB引擎,但是没有创建InnoDB的表,那么Master Thread总是处于挂起状态。

简单总结一下这四种循环的切换过程:

  1. 首先会进入主循环,执行“每一秒操作”和“每十秒操作”,其中先循环执行“每一秒操作”的逻辑,当计算器大于等于10时,就进入“每十秒操作”的逻辑,然后在跳回到“每一秒操作”的逻辑,一直这样循环下去,直到没有用户活动或数据库关闭,会跳到background loop的执行逻辑。
  2. background loop的逻辑执行完毕,如果有用户活动,这跳入主循环;如果没有用户活动,则跳到flush loop循环。
  3. flush loop的逻辑执行完毕,会跳入suspend_loop(暂停循环)。
  4. 暂停循环中会将Master Thread挂起,等待事件唤醒。
  5. 有新的事件发生时,MasterThread被唤醒,重复1~4的步骤。

以上的逻辑是InnoDB1.0.x版本之前中Master Thread的执行逻辑,在后来的1.0.x和1.1.x版本中对Master Thread的功能做了一些优化,来提升Master Thread的执行效率,进行提升InnoDB的性能,主要优化内容如下

从之前的版本中我们可以看出,无论何时,InnoDB最大只会刷新100个脏页,合并20个插入缓冲,这是硬编码的。但是随着固态硬盘的出现大大提升了磁盘的写入性能,如果每次刷新脏页和合并插入缓冲的数量不变的话,就会造成磁盘写性能的浪费。特别是对于写入密集的应用程序,每秒可能会产生大于100个的脏页,如果是产生大于20个插入缓冲的情况,Master Thread似乎会“忙不过来”,或者说它总是做得很慢。同时,当发生宕机需要恢复时,由于很多数据还没有刷新回磁盘,会导致恢复的时间可能需要很久,尤其是对于insert buffer来说。

因此从InnoDB1.0.x开始,提供了参数innodb_io_capacity,来表示磁盘IO的吞吐量,默认为200。执行规则如下:

  • 在合并插入缓冲时,合并插入缓冲的数量为innodb_io_capacity值为5%;
  • 在从缓冲区刷新脏页时,刷新脏页的数量为innodb_io_capacity.

另外一个优化是,参数innodb_max_dirty_pages_pct默认值由之前的90变成了75,这个改动既可以加快刷新脏页的频率,又能保证磁盘IO的负载。

Innod1.0.x版本还有增加了一个参数是innodb_adaptive_flushing(自适应刷新),该值影响每秒刷新脏页的数量。具体规则:InnoDB会通过判断产生重做日志(redo log)的速度来决定最合适的刷新脏页数量。因此,当脏页的比例小于innodb_max_dirty_pages_pct时,也会刷新一定量的脏页。

还有一个改变是:在InnoDB1.0.x版本开始引入innodb_purge_batch_size,用于控制每次full purge操作时回收Undo页的数量。并且从InnoDB1.1版本开始,purge操作独立到单独的线 程(purge Thread)中进行,以此来减轻Master Thread的工作。

在InnoDB1.2.x版本中又进行了优化,主要优化内容如下
这个版本中最大的优化就是:对于刷新脏页的操作,从Master Thread线程分离到一个单独的Page Cleaner Thread,从而减轻了Master Thread的工作,同时进一步提高了系统的并发性。

IO Thread

在InnoDB中大量使用了AIO(Async IO)来处理写请求,这样可以极大的提高数据库的性能。而IO Thread的工作主要是负责这些IO请求的回调处理。在InnoDB1.0版本之前共有4个IO Thread,分别是write、read、inser buffer和log IO Thread。从InnoDB1.0.x版本开始,read thread和write thread分别增大到了4个,分别使用innodb_read_io_threads和innodb_write_io_threads参数进行设置,并且读线程ID总是小于写线程。

异步IO是InnoDB很重要的一个特性,也是提升性能的一个重要功能。与AIO对应的是Sync IO,即每进行一次IO操作,需要等待此次操作结束才能继续接下来的操作。但是如果用户发出的是一条索引扫描的查询,那么这条SQL查询语句可能需要扫描多个索引页,也就是需要进行多次的IO操作。在每扫描一个页并等待其完成后再进行下一次的扫描,这是没有必要的。用户可以发出一个IO请求后立即再发出另一个IO请求,当全部IO请求发送完毕后,等待所有IO操作的完成,这就是AIO。

AIO的另一个优势是可以进行IO Merge操作,也就是将多个IO合并为1个IO,这样可以调高IOPS的性能。

Purge Thread

Purge Thread是InnoDB1.1版本开始新加入的线程,专门用于处理回收不再需要的undo页的工作,以此来减轻Master Thread的工作,从而提高CPU的使用率以及提升存储引擎的性能。在Mysql配置文件中,通过Innodb_purge_threads参数来设置线程数。但是在InnoDB1.1版本中,即使设置了此参数大于1,在InnoDB启动时也会将其设为1。在InnoDB1.2版本开始,InnoDB支持多个Purge Thread,这样做的目的是为了加快undo页的回收。同时由于Purge Thread需要离散地读取undo页,这样也能更进一步利用磁盘的随机读取性能。

Page Cleaner Thread

Page Cleaner Thread是INnoDB1.2版本开始引入的。其作用是将之前版本中脏页的刷新操作都放入到单独的线程中来完成。其目的是为了减轻原Master Thread的工作及对于用户查询线程的阻塞,进一步提高InnoDB的性能。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值