在说Master Thread是怎样工作之前,举一个例子,一家饭店,只有老板自己,在人多的时候,老板只顾得上收银、上菜。人少的时候,才有时间收拾卫生、回收餐具,晚上没人的时候,准备材料、打扫卫生等。
同样,Master Thread也存在空闲和非空闲的时候。在非空闲的时候,Master Thread会刷新日志、合并插入缓存、刷新脏页。空闲的时候,Master Thread会插入缓存、删除undo页、刷新日志、刷新脏页等。
我们看到,在任何时候,都会刷新日志、脏页和合并插入缓存。但是,空闲和非空闲的条件判断是不一样的,合并插入缓存操作,在非空闲的时候是直接合并的,伪代码如下:
void masert_thread() {
if(innodb is idle)// 空闲时执行
srv_master_do_idle_tasks();
else // 非空闲时执行
srv_master_do_active_tasks();
}
// 非空闲方法
void srv_master_do_active_tasks(){
刷新重做日志到磁盘
if 上一秒io数量小于5 ? 合并5个插入缓存
if 缓存池脏页比例大于90% ? 刷新100个脏页到磁盘
}
// 空闲方法
void srv_master_do_idle_tasks(){
刷新重做日志到磁盘
if 前10秒io数小于200 ? 刷新100个脏页
合并5个插入缓存
删除无用的undo页,20个
if 脏页比例大于90% ? 刷新100个脏页 : 刷新10个脏页
}
同时,我们发现,当磁盘压力不管大不大的时候,每次都回收100个脏页、合并5个插入缓存,没有考虑到磁盘IO吞吐量的情况,举个例子,每个饭店的情况和老板不同,有的老板打算卫生快,有的老板打算卫生慢,快的多弄,慢的少弄,而不是固定打扫卫生。 磁盘的情况也不一样,所以,数据库提供了innodb_io_capacity参数表示系统吞吐量,合并插入缓存为 innodb_io_capacity的5%,刷新脏页数量为 innodb_io_capacity,举例:innodb_io_capacity 配置为200 则,合并插入缓存为:10,刷新脏页数为:200。
然后,当脏页比例为90%,才刷新脏页。这就相当于饭店都是没打扫的桌子10个有9个是脏的,老板才会打扫,脏桌子占用比例太大,老板决定7个桌子脏了的时候就打扫。同样,数据库调整为:脏页比例为75%就刷新脏页,通过参数innodb_max_dirty_pct来控制,默认为75%,同时引入了innodb_adaptive_flushing参数,默认为NO,在比例小于75%的时候,自适应刷新脏页。
第三,删除undo页的数量固定为20个,在此次变动也引入了innodb_purge_batch_size参数,默认为300,每次回收300个undo页,进一步提高数据性能。
现在,伪代码变为:
void masert_thread() {
if(innodb is idle)// 空闲时执行
srv_master_do_idle_tasks();
else // 非空闲时执行
srv_master_do_active_tasks();
}
// 非空闲方法
void srv_master_do_active_tasks(){
刷新重做日志到磁盘
if 上一秒IO数量小于 5% * innodb_io_capacity ? 合并 innodb_io_capacity * 5% 个插入缓存
if 缓存池脏页比例大于 innodb_max_dirty_pct ? 刷新 innodb_io_capacity 个脏页到磁盘
}
// 空闲方法
void srv_master_do_idle_tasks(){
刷新重做日志到磁盘
if 前10秒IO数小于 innodb_io_capacity ? 刷新 innodb_io_capacity 个脏页
合并 innodb_io_capacity * 5% 个插入缓存
删除 innodb_purge_batch_size 个无用的undo页
if 脏页比例大于 innodb_max_dirty_pct ? 刷新 innodb_io_capacity 个脏页 : 自适应刷新脏页
}
最后,我们总结一下。Master Thread主要操作为: 刷新脏页、回收undo页、刷新日志、合并插入缓存。通过innodb_io_capacity控制刷新脏页数量和合并插入缓存数量、innodb_purge_batch_size控制回收undo页数量,提高数据库的并发。