1. 系统环境
- OS: CentOS Linux release 7.8.2003 (Core)
- Kernel: 3.10.0-1127.19.1.el7.x86_64
- MySQL: 用5.0、5.7均有此问题,应该和版本无关
2. 压测工具
- benchyou[1]
- mysql_random_load[2]
3. 问题现象
利用 mysql_random_load 工具连接MySQL写入数据时,性能非常非常低。
由于 mysql_random_load 工具不支持通过socket连接,只好放弃,改用benchyou。顺便说一下,benchyou和sysbench极为相似,也非常好用。
改用benchyou工具后,压测正常。看来的确不是MySQL版本的问题。
用 mysql_random_load 工具进行压测时,系统负载非常高,同时可观测到系统的中断也很高并且也很不均衡。
# vmstat -S m 1
可以看到 system.in 这列的值非常高,改成benchyou工具后,这列的值从5.5万降到1.6万。
# vmstat -S m 1
再看下有问题时的系统中断表现
# mpstat -I SUM -P ALL 1
可以看到每秒中断总量有5.5万,但多个CPU间并不均衡。
4. 问题分析
初步认定是因为系统中断太高导致的写入性能差,并且也认定是因为多个CPU间中断不均衡导致的这个问题。
观察是都有哪些中断比较高,发现主要是 LOC 和 RES 这两个每秒的增长比较大。
# watch -d cat /proc/interrupts
在尝试修改相关中断号绑定的CPU后(参考:SMP affinity and proper interrupt handling in Linux[3]),问题还是没有得到缓解。
后来某神秘大佬给指点了下,才发现原来是个内核的bug,涉及到参数 kernel.timer_migration,需要将其设置为 0 才行。
# sysctl -w kernel.timer_migration=0
当然了,最好持久化写入到 /etc/sysctl.conf 文件中。
# cat /etc/sysctl.conf
再次用 mysql_random_load 工具进行压测就没事了。
下面是关于该bug的描述
The bug is when linux os receive too many tcp packages,
and the tcp may add too many timer, but in
get_target_base->get_nohz_timer_target it check current
cpu is idle, sometimes thouth the current core is very busy,
but the idle_cpu result is 1, in this time
if set kernel.timer_migration=1 ,the timer will be move to next cpu.
bug详情见:Bug 124661 - kernel.timer_migration=1 cause too many Rescheduling interrupts[4]
最后,值得一提的是,在云主机上修改该参数应该是不管用,除非修改物理机的。我在某云主机上运行 mysql_random_load 工具压测也遇到类似问题,修改内核参数后问题依旧。
文内链接
- [1]:https://github.com/xelabs/benchyou
- [2]:https://github.com/Percona-Lab/mysql_random_data_load
- [3]:http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux
- [4]:https://bugzilla.kernel.org/show_bug.cgi?id=124661
Enjoy Linux & MySQL :)
「MySQL核心优化」课已升级到MySQL 8.0,扫码开启MySQL修行之旅