MySQL之后台线程

InnoDB采用的是多线程模型,后台有多个不同的线程负责处理不同的任务。

1.jpg

1. Master Thead

master thread是一个非常核心的后台线程,具有最高的线程优先级。InnoDB存储引擎的主要工作都是在一个单独的后台线程Master Thread完成的,比如将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页面的刷新、合并插入缓冲、undo页的回收等。

Master Thread内部有多个循环组成(loop):

  • 主循环(loop)
  • 后台循环(backgroup loop)
  • 刷新循环(flush loop)
  • 暂停循环(suspend loop)

Master Thread会根据数据库运行的状态在四中循环之间切换。

1.1 主循环

大多数的操作都是在主循环中完成,根据执行频率,可以分为两类操作:

1.1.1 每秒一次的操作

  • 日志缓冲刷新到磁盘(总是)
  • 合并插入缓冲(可能)
  • 刷新脏页到磁盘(可能)
  • 如果没有用户活动切换到background thread(可能)

即使某个事务没有提交,InnoDB仍然每秒将重做日志缓冲刷新到磁盘,这一点保证了再大的事务提交也是很快的。

只有脏页比例超过了一个阈值,InnoDB才会执行刷新操作,该值与参数innodb_max_dirty_pages_pct有关,默认为75%:

mysql> show variables like 'innodb_max_dirty_pages_pct'\G;
*************************** 1. row ***************************
Variable_name: innodb_max_dirty_pages_pct
        Value: 75.000000

需要注意的是,在自适应刷新策略下,即使脏页比例小于75%也可能执行刷新操作。

而一次最多合并多少个插入缓冲、刷新多少个脏页,由另一个参数innodb_io_capacity来控制,默认为200:

mysql> show variables like 'innodb_io_capacity'\G;
*************************** 1. row ***************************
Variable_name: innodb_io_capacity
        Value: 200
  • 刷新脏页数量 = innodb_io_capacity
  • 合并插入缓冲数量 = innodb_io_capacity * 5%

1.1.2 每10秒一次的操作

  • 刷新脏页到磁盘(可能)
  • 合并至多5个插入缓冲(总是)
  • 日志缓冲刷新到磁盘(总是)
  • 删除无用的Undo页(总是)
  • 刷新innodb_io_capacity个或10%的脏页到磁盘(总是)

第一步与第五步都是刷新脏页操作,但是执行条件不一样:

  • 第一步不是必现的,InnoDB会先判断过去10秒之内的磁盘IO操作是否小于innodb_io_capacity次,如果是,认为当前有足够的磁盘IO操作能力,然后将脏页刷新到磁盘;
  • 第五步是必现的,InnoDB会判断脏页比例,如果超过70%,则刷新100个脏页;否则,只刷新10%的脏页。

在InnoDB 1.2.x版本以后,刷新脏页的操作从Master Thread分离出来,交由单独的Page Cleaner Thread执行。

其中,InnoDB还会执行一项称为full purge操作,即删除无用的undo页。InnoDB对表进行update、delete这类操作时,原先的行被标记为删除,但是需要保留这些行版本的信息,有时候可能还有查询操作需要能读取之前版本的undo信息。如果undo页确认可以删除。每次回收undo页的数量由参数innodb_purge_batch_size控制:

mysql> show variables like 'innodb_purge_batch_size'\G;
*************************** 1. row ***************************
Variable_name: innodb_purge_batch_size
        Value: 300

1.2、后台循环

若当前没有用户活动或数据库关闭,就会切到这个循环,执行以下操作:

  • 删除无用的undo页(总是)
  • 合并20个插入缓冲(缓冲)
  • 跳回到主循环(总是)
  • 跳到flush loop(可能)

1.3、刷新循环

只干一件事,就是刷新页到缓冲池。

1.4、 暂停循环

若flush loop中也没有什么事情可以做了,InnoDB会切换到suspend loop,将Master Thread挂起,等待事件的发生。

2. IO Thread

InnoDB使用了大量AIO(Async IO)来处理IO请求,而IO Thread的工作主要是负责这些IO请求的回调处理。

可以通过show engine innodb status命令来观察InnoDB的状态,从中可以看到IO Thread的情况

mysql> show engine innodb status\G;
*************************** 1. row ***************************
  Type: InnoDB
  Name:
Status:
=====================================
2019-03-07 22:09:08 0x7000013d8000 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 3 seconds
...
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread)
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
 ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
242 OS file reads, 53 OS file writes, 7 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
...

可以发现,默认情况下一共有10个IO线程:

  • (insert buffer thread)* 1
  • (log thread) * 1
  • (read thread) * 4
  • (write thread) * 4

read thread与write thread数量可以通过参数进行调整:

mysql> show variables like 'innodb_%io_threads'\G;
*************************** 1. row ***************************
Variable_name: innodb_read_io_threads
        Value: 4
*************************** 2. row ***************************
Variable_name: innodb_write_io_threads
        Value: 4

3. Purge Thread

事务被提交后,其所使用的undo log(用于事务commit失败后回滚操作用)可能不在需要,因此需要purge线程来回收undo页。

还可以通过参数`innodb_purge_threads设置多个purge thread以进一步加快undo页回收。

mysql> show variables like 'innodb_purge_threads'\G;
*************************** 1. row ***************************
Variable_name: innodb_purge_threads
        Value: 4

4. Page Cleaner Tread

为了减轻Maser Thread的工作压力及对于用户查询线程的阻塞,将脏页的刷新交由单独的Page Cleaner Thread来完成。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。