众所周知,想要清晰的了解一款软件的运作原理,最重要的就是要了解它的物理结构、内存结构和内部线程运行分工。下面让我们一起来看看innodb的后台线程是如何分工的。
这里要区分一下MySQL用户线程和innodb后台线程,MySQL的用户线程不属于innodb,它和用户会话session属于一对一的关系,用于处理用户的连接与命令。对于innodb的缓冲管理,内存和物理磁盘间的数据同步,由innodb的后台线程来操作:主线程、IO线程、Purge线程、Page Cleaner线程。
主线程
Master Thread是一个核心的后台线程,原本主要负责刷新脏页、合并插入缓冲、undo页回收等工作。不过随着innodb的升级,一些任务逐渐分离给别的线程处理,像脏页的刷新后面分给了page Cleaner线程,undo页的回收分给了purge线程。这里画几个流程图演示master线程的执行过程:
上图为innodb1.0.x版本前的master线程运行过程,可以发现刷新缓冲日志不仅仅在事务提交后或LRU列表不足时才执行,master线程每秒都会执行刷新操作,因此再大的事务都可以很快的完成提交,而不会被IO占用很长时间。
而合并插入缓冲操作执行次数却比较谨慎,只有在没有用户活动的时候才会较大量的执行,这是由于当年只有机械硬盘,IO速度受到限制(固态硬盘牛逼)。直到1.0.x之后,随着硬件的发展,主线程的执行过程页慢慢开始调整,innodb添加了参数innodb_io_capacity来设置磁盘io吞吐量,此时,合并插入缓冲的数量由5个调整成 innodb_io_capacity*5%个,脏页刷新数量由100个调整成innodb_io_capacity个。
并且当你使用固态硬盘SSD之后,可以尝试关闭innodb的刷新邻接页功能来提高性能,因为刷新邻接页的历史背景是机械盘寻道速度慢,当刷新脏页是会顺便检测邻接的页是否也是脏页。而这有可能会把稍微有点“脏”的页也给处理了。
到innodb1.1.x版本后,可设置innodb_purge_threads =1,将undo页回收的操作交给Purge线程。直到innodb1.2.x版本后,innodb_purge_threads变成默认为1,且可设置为更大的数字。此时的脏页刷新操作也分离到了Page Cleaner线程。主线程的流程也做了适当的调整:
IO线程
innodb使用大量的AIO(异步非阻塞IO)来处理写IO的请求, IO Thread负责处理IO请求的回调:异步:线程调用了IO的API如read、write后不等待返回,继续作别的事情。非阻塞:IO的API处理数据流的时候线程状态不会被阻塞,由操作系统写完流后回调专门的线程(IO Thread)来处理。IO线程共有四个类型:write、read、insert buffer、log,各线程数量可由参数设置。使用show engine innodb status可以看到这四个线程的状态:
--------
FILE I/O
--------
I/O thread 0 state: wait Windows aio (insert buffer thread)
I/O thread 1 state: wait Windows aio (log thread)
I/O thread 2 state: wait Windows aio (read thread)
I/O thread 3 state: wait Windows aio (read thread)
I/O thread 4 state: wait Windows aio (read thread)
I/O thread 5 state: wait Windows aio (read thread)
I/O thread 6 state: wait Windows aio (write thread)
I/O thread 7 state: wait Windows aio (write thread)
I/O thread 8 state: wait Windows aio (write thread)
I/O thread 9 state: wait Windows aio (write thread)
Purge线程
在innodb1.1.x版本后,主线程的purge操作被分离到Purge Thread,purge操作用于对不需要的undo log页进行回收:通常是事务被提交后,并且确定页上的数据没有被用于MVCC的undo log页。
Page Cleaner线程
innodb1.2.x版本后,主线程刷新脏页的操作分离到Page Cleaner线程。
如有错误,敬请斧正;欢迎转载,但请务必注明出处;最后,在此向神奇的海螺保证,绝不太监!!!