master thread是最高的线程优先级,由多个循环组成:
- loop
- background loop
- flush loop
- suspend loop
master thread会根据数据库运行状态来在各个循环间动态的切换
loop
主循环,大部分操作在这个循环,其中分为两部分:每秒钟的操作和每10秒的操作。
void master_thread(){
loop:
for(int i=0;i<10;i++){
do thing once per second
sleep 1 second if necessary
}
do things once per ten seconds
goto loop;
}
每秒一次的操作包括:
- 日志缓冲(redo log等)刷新到磁盘,即便这个事务没有提交
每秒可能的操作:
- 合并插入缓冲(如果前一秒的IO次数小于5次)
- 最多刷新100个缓冲池的脏页到磁盘(当前缓冲池脏页的比例超过innodb_max_dirty_pages_pct参数)
- 如果当前没有用户活动,切换到background loop
每10秒的操作:
- 合并至多5个插入缓存
- 将redo日志缓冲刷新到磁盘
- 删除无用的undo页(purge thread,每次最多删除20个undo页)
- 刷新100个或者10个脏页到磁盘(脏页比例小于70%则刷新10个,否则100个)
每10秒可能的操作: - 刷新100个脏页到磁盘(过去10秒内IO操作小于200次)
main loop的伪代码:
background loop
background loop的操作:
- 删除无用的undo 页
- 合并20个插入缓存
- 跳回主循环loop
- 不断刷新100个页知道符合条件(可能,跳转到flush loop中完成,如果flush loop没有事做,会切换到suspend loop,挂起master thread,等待事件唤醒)
1.0.x master thread的问题
从前面可以看出,无论何时loop最大只会刷新100个脏页和20个插入缓冲,会存在效率瓶颈。
所以后续的版本引进了以一个参数来控制刷新的脏页数量和插入缓冲数量:
- innodb_io_capacity表示磁盘IO吞吐量,合并插入缓冲的数量为其值的5%,刷新脏页的数量为其值
- 每次进行回收undo页的full purge操作时,后续的版本加入了innodb_purge_batch_size来控制每次回收的数量,默认值20
1.2.x版本的master thread
if InnoDB is idle:
srv_master_do_idle_tasks(); //每10秒的操作
else:
srv_master_do_active_tasks(); //每秒钟的操作
刷新脏页的操作新起了个Page Cleaner Thread来弄