同事问了个线上现象:主备机器配置一样,主库上有更新查询,备库设置为主库的从库,没有其他更新和查询压力。但备库的io util比主库的重。本来看主库的压力比较大,想把一部分查询切到备库,一看io这样,不太敢切。
1、原因
这个原因两年前在之前公司碰到过一次,只是现象不同。那个现象描述起来比较复杂,这回刚好借这个现象说明一下。
原因还是从srv_master_thread说起。这个InnoDB后台的主进程一直在循环作各种事情。其中有一个for (i = 0; i < 10; i++) ,循环体每执行一次sleep 1秒,作一些flush和merge的事情,网上这类文章很多,不细数了。我们要关注的是循环中的这句话
if (srv_activity_count == old_activity_count) { /* There is no user activity at the moment, go to the background loop */ goto background_loop; } |
注释也说的明白,如果此时没有用户活动,则认为是系统空闲,执行background_loop。这个background_loop流程作的事情包括insert buffer merge和 flush buffer pool pages。 都是些耗系统资源的活儿。做完之后又回到for前面的逻辑。
而对于从库来说,一直没有用户请求,所以一进入for就符合进入background_loop的条件,所以整个线程实际上就是不停的在作background_loop里面的事情。
所以结论就是由于没有用户请求,InnoDB认为系统空闲,因此玩儿命地刷盘,看上去io就很重。
2、 验证
既然如此,就想办法告诉InnoDB:其实现在很忙。 可以简单的写个脚本不停的执行一个简单的语句,让if (srv_activity_count == old_activity_count)这条件不满足就行。比如 select sql_no_cache * from t where key = xxx limit 1;
会看到加了这脚本后,备库的io util也下去了。
3、 结论
切点查询流量去备库没有问题,反而会让备库看上去“正常” ;
InnoDB的这个判断机制有点囧,实际上有很多条件都可以比较合理的判断,不过也不是什么大问题,好歹还有些方法可以绕过的嘛,就是土了点。。。