Master_Thread的探索
引擎的核心工作之一是由Master_thread负责,Master_thread具有最高的线程优先级,有三大版本的Master_thread,分别是:
- 1.0.X之前
- 1.0.X~1.2.X
- 1.2.X
每个版本的Master_thread实现都各有不同,不变的是Master_thread在INNODB引擎中的地位。
一.Before 1.0.X
Master_thread的内部是由多个Loop构成,分别是:
- 主loop
- backgroup loop
- flush loop
- suspend loop
Master_thread会根据服务器的运行状态在各个loop之间进行动态切换,对这几个loop进行分析。
1.Loop
Loop也称为主循环,大多数的操作都是在这个Loop中执行,其中两个重要部分是1S操作与10S操作:
1、1S操作
- redo Log的刷盘(即使事务未提交)
- 可能会执行合并插入缓冲
- 可能执行至多刷新100个脏页到磁盘
- 如果当前没有用户活动,则不活跃,切换到backgroup loop
其中合并插入缓冲的条件必须是前一秒发生的IO次数低于阈值(5);而刷新100个脏页也是需要达到一个脏页阈值, 最大脏页百分比
,可以通过 show variables like 'innodb_max_dir%'
查看。
2、10S操作
- 可能刷新100个脏页到磁盘
- 合并至多5个插入缓冲
- 将日志缓冲冲刷到磁盘
- 删除无用的Undo页
- 刷新100个或者10个脏页到磁盘
其中,只有刷新100个脏页到磁盘这个操作是可能执行的,其它都是必然执行;删除UNDO页的操作即是Full Purge(完整清除)其中的插入缓冲,会根据过去十秒的io次数是否小于200决定是否刷新100个脏页到磁盘。
2.Backgroup Loop
1、执行条件
根据上面分析的,Master_thread的内部就是在多个Loop之间跳转,那么,跳转到该Loop的条件如下:
- 当前没有用户活动,数据库处于空闲状态
- 数据库执行shutdown
2、执行操作
- do full perge,即清除无用undo页
- do merge 20 insert buffer
这个循环称为后台循环,执行的主要是清除工作与合并插入缓冲。如果,数据库在这个时候处于空转,就会跳转向flush Loop,而如果这个数据处于活跃状态,就会跳进主Loop。
3.Flush Loop
1、执行条件
由Backgroup Loop跳转过来,可以跳转过去suspend loop
2、执行操作
顾名思义,就是在满足达到脏页阈值的时候执行100个脏页的冲刷工作,可以多次执行该操作;执行完毕后跳转进suspend loop。
4.Suspend Loop
在执行完冲刷Loop之后,挂断线程,等待唤醒,唤醒之后会跳转到主Loop。
画出流程图如下:
附上代码概图:
//这是1.0.x版本之前的master_thread
void master_thread() {
goto loop;
/**
* 这是主loop
*/
loop:
{
for (int i = 0; i < 10; ++i) {
Sleep(1000);//休眠1000MS
//do log flush to disk
if (last_one_second_ios < 5) {
//do merge 5 insert buffer
}
if (buf_get_modified_ratio_pct > innodb_max_dirty_page_pct) {
//do flush 100 dirty page
}
if (no_user_activity) {
goto backgrouploop;
}
}
//这里省略10s操作的代码。
};
backgrouploop:
{
/* do full perge,即清除无用undo页
do merge 20 insert buffer*/
if (not idle) {
goto loop;
} else {
goto flushloop;
}
};
flushloop:
{
//do flush 100 dirty page
};
if (buf_get_modified_ratio_pct > innodb_max_dirty_page_pct){
goto flushloop;
} else{
goto suspendloop;
}
suspendloop:{
//挂起线程
suspend_thread();
//等待唤醒
waiting_even();
goto loop;
};
}
二.1.0.X
1.0.x版本的master_thread做了如下几个修改:
- 最大脏页比列的调整:基于Google的意见后,作出了将默认值90%修改为75%的决定。
- 增加自适应刷新功能
:通过添加innodb_adaptive_flushing参数,且添加了对应的处理函数: buf_flush_get_desired_flush_rate
.
这个方法通过判断产生redo log的rate速度来决定刷新的脏页的数量,并进行刷新。
作出这两点修改之后,引擎的性能提高了不少,刷脏能力也提高了,哪怕在脏页没有达到最大值,也会进行刷脏。
三.1.2.X
1.2.X的最大改变在于分离出刷脏工作,由 page_cleaner
执行刷脏工作,则减轻了master_thread的负载。
//以下是大致的伪代码
if innodb is idle
srv_master_do_idle_tasks(void);
else
srv_master_do_active_tasks(void);
原本的master_thread负责的工作中有大部分就是刷脏工作,分离出之后自然轻松很多了。
当下的INNODB引擎已经将负责刷脏工作的 page_cleaner提升为多线程的模式,即拥有多个cleaner,一个 如果读者对刷脏工作感兴趣,可以在我的blog中查看《多线程刷脏》。
总结
- master_thread的工作在减轻,当前的版本已经没什么负担
- master_thread的演变过程体现了一种面向对象的编程思想
- master_thread逐渐体现出设计模式中的单一职责原则