MySQL数据库SYS CPU高的可能性分析
来源:互联网 发布:java thread.sleep用法 编辑:程序博客网 时间:2024/06/05 22:54
问题背景
我们在管理繁忙的 MySQL 数据库时,可能都有碰到 SYS CPU 高的经历:系统突然 SYS CPU 高起来,甚至比 USER CPU 高很多,这时系统 QPS、TPS 急剧下降。
SYS CPU高是什么造成的呢?主要有2种可能:
1. context switch 不高,但在内核态 spin,导致 SYS CPU 高
2. context switch 高,每秒超过 200K,有时超过1M,过多 context switch 导致 SYS CPU 高
下面我们对这两种情况逐一分析。
context switch 不高,但在内核态 spin
MySQL 在内核态 spin,说明需要系统资源,当这个资源紧张不足时,就会在内核态 spin。
有些资源,用户进程(或线程)通过执行系统调或因中断进入内核,一般来说申请这些资源的执行时间很短,当出现资源争用时,如果采用 sleep 再唤醒机制,代价较大,因此多采用在内核态spin的策略。
例如申请内存或发生缺页中断,没有 free 内存可用时,进程或线程就可能在内核态先执行内存回收再执行内存分配,但系统内存是共享资源,分配回收时需要锁保护,当多个进程(或线程)同时回收分配内存时。就会在内核态 spin。
当 free 内存不足时,可能出现这种情况。典型症状:
- MySQL running 高,但系统 qps、tps 下降
- 系统 free 内存不足;或系统 free 内存充足时,但启用了 numa 内存分配策略,有的节点 free 内存很少
- 系统 context switch 不高
- MySQL InnoDB 的 mutex、RWlock 查不到等待信息
- sar -B 显示有 pgscand 产生
分析
当系统内存不足时,MySQL 突然有大量访问,紧急需要大量内存,kswapd 在短时间内回收不了足够多的 free 内存,或 kswapd 还没有触发执行,这时 MySQL 用户线程就会在内核态执行内存回收操作,从而出现以上症状。
sar -B 输出中,pgscank 是表示内核线程 kswapd 回收内存,k意思是 kernel;pgscand是表示用户进程或线程直接回收内存,d意思是direct。
解决办法:保证系统有充足 free 内存可用,NUMA 环境要求每个节点都有足够free内存可用。
由于 Linux 系统会尽量使用 free 内存,一个运行很久的 Linux 系统,free内存通常很少,存在大量 filecache 内存,但 Linux 没有直接提供控制 filecache 占用多少的参数,那怎么能够保留足够可用的 free 内存,以应对突然内存需求呢?
对此,Linux 2.3.32+ 内核中增加一个新的参数vm.extra_free_kbytes
,就是控制free内存的。
关于系统free内存,有2个重要参数:vm.min_free_kbytes
和 vm.extra_free_kbytes
(2.6.32+)
vm.min_free_kbytes
:系统保留给内核用的内存。
这个值决定 /proc/zoneinfo
中 zone 的min值。当系统 free 内存小于这个值时,kswapd 会回收内存,直到free内存达到/proc/zoneinfo
中 high 值才停止回收;
当用户进程或线程分配内存或发生缺页中断时,free 内存少于 vm.min_free_kbytes
,会在用户线程上下文中直接进行回收内存(pgscand)和分配内存。
vm.extra_free_kbytes
:系统保留给应用的free内存。
这个值决定了/proc/zoneinfo
中Normal zone的low值。当系统free内存小于vm.min_free_kbytes + vm.extra_free_kbytes
时,kswapd会开始回收内存,直到free内存达到 /proc/zoneinfo
中high值才停止回收。
这个额外的vm.extra_free_kbytes
就是给应用突发内存需求时使用的,避免急需内存时发生pgscand或kswapd回收内存不及时。
vm.extra_free_kbytes
分配多大合适呢?一般能应对流量高峰时1-2秒内存需求就可以了。free内存减少后,kswapd进程会在后台回收内存的,一般512M-2G可以满足要求。
context switch 高
有很多种情况都会导致 context switch。MySQL 中的 mutex 和 RWlock 在获取不成功后,短暂spin,还不成功,就会发生 context switch,sleep,等待唤醒。
在 MySQL中,mutex 和 RWlock导致的 context switch,一般在show global status
,show engine innodb mutex
,show engine innodb status
,performance_schema
等中会体现出来,针对不同的mutex和RWlock等待,可以采取不同的优化措施。
除了MySQL的mutex和RWlock,还发现一种情况,是MySQL外的mutex竞争导致context switch高。
典型症状:
- MySQL running 高,但系统 qps、tps 低
- 系统context switch很高,每秒超过200K
- 在 MySQL 内存查不到mutex和RWlock竞争信息
- SYS CPU 高,USER CPU 低
- 并发执行的SQL中出现timestamp字段,MySQL的time_zone设置为system
分析
对于使用 timestamp 的场景,MySQL 在访问 timestamp 字段时会做时区转换,当 time_zone 设置为 system 时,MySQL 访问每一行的 timestamp 字段时,都会通过 libc 的时区函数,获取 Linux 设置的时区,在这个函数中会持有mutex,当大量并发SQL需要访问 timestamp 字段时,会出现 mutex 竞争。
MySQL 访问每一行都会做这个时区转换,转换完后释放mutex,所有等待这个 mutex 的线程全部唤醒,结果又会只有一个线程会成功持有 mutex,其余又会再次sleep,这样就会导致 context switch 非常高但 qps 很低,系统吞吐量急剧下降。
解决办法:设置time_zone=’+8:00’,这样就不会访问 Linux 系统时区,直接转换,避免了mutex问题。
NOTE:作者这里给出的解决方法是修改数据库参数,但是这样会影响整个数据库,所以个人认为如果可能的话,可以在需要访问时间字段的应用程序中指定时区,这样也可以避免mutex问题(我遇到过该问题导致SYS CPU使用率高的问题,通过在程序中指定时区后问题解决)
另外,对于spin消耗,MySQL配置变量中的innodb_spin_wait_delay
和 innodb_sync_spin_loops
可以用于微调。
NOTE: 上面说到的第二种情况,即mysql中大量并发访问timestamp字段时,导致sys cpu使用率高的现象,我使用mysqlslap进行如下模拟
mysqlslap --concurrency=100 --iterations=1 --create-schema=test1 --query='select now();' --number-of-queries=10000000 --debug-info -uroot -h127.0.0.1 -p
##模拟100个客户端同时访问test1数据库,每个客户端执行10000000 次"select now();"查询,模拟的结果发现context switch确实很高,SYS CPU也高,但是USER CPU更高(但是上面分析中的结论是USER CPU低),下面是cpu使用率和context switch情况
[root@shaofei-test-mysql-01 ~]# vmstat 2 50procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st102 0 1601848 136256 99260 680180 0 1 8 26 2 2 0 0 100 0 0102 0 1601848 135556 99260 680208 0 0 0 0 4230 139932 65 35 0 0 0103 0 1601848 135432 99260 680208 0 0 0 0 4208 139768 67 33 0 0 0101 0 1601848 135440 99268 680208 0 0 0 6 4186 140673 65 35 0 0 0103 0 1601848 135440 99268 680208 0 0 0 0 4179 140835 67 33 0 0 0101 0 1601848 135432 99268 680208 0 0 0 0 4206 140001 66 34 0 0 046 0 1601848 135432 99268 680208 0 0 0 0 4187 140909 66 34 0 0 0 0 0 1601848 141504 99268 680208 0 0 0 0 2497 72160 33 18 48 0 0 0 0 1601848 139924 99276 680000 0 0 0 20 441 467 2 1 97 0 0 0 0 1601848 139924 99276 680212 0 0 0 0 76 138 0 0 100 0 0 0 0 1601848 139924 99280 680212 0 0 0 44 89 145 0 0 100 0 0 0 0 1601848 139988 99280 680212 0 0 0 0 82 133 0 0 100 0 0##我们看到正常情况下cs值为100左右,在mysqlslap进行压测时该值上升到10万以上,修改time_zone='+8:00',进行同样的测试发现 cs值下降为6万左右(修改该参数后,上下文切换明显减少)
toptop - 11:27:34 up 29 days, 20:38, 3 users, load average: 28.63, 7.67, 2.61Tasks: 147 total, 1 running, 146 sleeping, 0 stopped, 0 zombieCpu(s): 66.6%us, 25.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 8.2%si, 0.0%stMem: 8058540k total, 7926100k used, 132440k free, 99284k buffersSwap: 16777212k total, 1601848k used, 15175364k free, 680436k cached##我们看到USER CPU使用率比SYS CPU 使用率高很多,修改time_zone='+8:00',进行同样的测试发现 cpu使用率与修改之前没有多大变化
- MySQL数据库SYS CPU高的可能性分析
- MySQL数据库SYS CPU高的可能性分析
- MySQL数据库SYS CPU高的可能性分析
- MySQL数据库SYS CPU高的可能性分析
- Mysql 占用cpu资源高的分析
- mysql占用CPU资源高的分析
- Mysql数据库服务器CPU冲高问题定位及分析
- MySQL数据库的高可用性分析
- MySQL数据库的高可用性分析
- MySQL数据库的高可用性分析
- 关于cpu的分析--us,sys百分比代表什么
- 阿里云数据库维护记录-RDS MySQL IOPS 使用率高的原因和处理--RDS实例CPU超过100%的分析
- Oracle数据库 慢的可能性
- 腾讯云:MySQL数据库的高可用性分析
- CPU占用率高的原因分析
- oracle数据库CPU特别高的解决方法
- Mysql队列数据库cpu wait IO高的问题排查经历
- mysql cpu占用高的原因
- Visual Studio 2013 、Matlab 2014产品密钥
- opencv实现灰度图像的直方图点计算以及灰度直方图显示
- Runtime.getRuntime().exec()出现阻塞,导致后续程序无法运行!
- Storm集群安装部署步骤【详细版】
- Rabbitmq 学习笔记(四)HA
- MySQL数据库SYS CPU高的可能性分析
- 我的Android进阶之旅------>关于使用Android Studio替换App的launcher图标之后仍然显示默认的ic_launcher图标的解决方法
- rxJava------>看我72变
- eclipse下git的配置和使用
- Error creating context 'spring.root': InputStream is null from Resource
- MyEclipse2015+Tomcat+MAVEN+SVN项目环境搭建
- 易语言,窗口总在最前的思路
- bean的加载(八)创建bean的实例
- 在线实时大数据平台Storm集群组件学习