系统资源瓶颈诊断
当操作系统的资源出现瓶颈时,不仅操作系统上的应用服务受到影响,而且在操作系统执行简单的命令可能都无法返回结果。在操作系统尚未完全夯死前,可以使用相关命令对CPU、内存、IO和网络资源的使用情况进行信息的收集,然后分析确认这些资源是否被合理利用,是否存在瓶颈。
CPU
top、vmstat都可以检查CPU的使用情况,但top的结果显示的更全面。top返回的结果有两层,上层是系统性能的统计信息,下层是进程的统计信息,默认按照CPU的使用率排序。 top返回结果示例如下:
top - 10:12:21 up 5 days, 22:31, 4 users, load average: 1.00, 1.00, 0.78
Tasks: 731 total, 1 running, 730 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.7 us, 0.0 sy, 0.0 ni, 98.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 257841.3 total, 1887.5 free, 45581.6 used, 210372.2 buff/cache
MiB Swap: 8192.0 total, 8188.7 free, 3.3 used. 210450.4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
908076 mysql 20 0 193.0g 42.4g 44088 S 100.3 16.8 228:10.34 mysqld
823137 root 20 0 6187564 83772 51636 S 6.6 0.0 6:36.12 dockerd
822938 root 20 0 3278696 58500 35420 S 0.7 0.0 38:37.69 containerd
1483 root 20 0 239280 9260 8136 S 0.3 0.0 0:19.16 accounts-daemon
928343 root 20 0 9936 4576 3240 R 0.3 0.0 0:00.04 top
......
第一行
-
10:12:21
:当前系统时间 -
up 5 days
:自上一次系统启动后到现在的运行天数 -
4 user
:登录到系统的用户数 -
load average
:过去1分钟、5分钟、15分钟,系统负载的平均值
第二行
-
total
:系统进程总数 -
running
:处于运行状态的进程数 -
sleeping
:处于休眠状态的进程数 -
stopped
:处于被停止状态的进程数 -
zombie
:处于僵尸状态进程数
第三行
-
us
:用户进程占用CPU的百分比 -
sy
:系统进程占用CPU的百分比 -
ni
:优先级被改变过的进程占用CPU的百分比 -
id
:空闲CPU占用的百分比 -
wa
:IO等待占用CPU的百分比 -
hi
:硬件中断占用CPU的百分比 -
si
:软件中断占用CPU的百分比 -
st
:虚拟化环境占用CPU的百分比
需要重点关注CPU的使用率,当us值较高时,说明用户进程消耗CPU时间较多,如果长时间超过50%时,应尽快优化应用服务。当sy值较高时,说明系统进程消耗CPU时间较多,比如可能是操作系统配置不合理或者出现操作系统的Bug。当wa值较高时,说明系统IO等待比较严重,比如可能是发生了大量的随机IO访问,IO带宽出现瓶颈。
第四行
-
total
:物理内存总大小,单位为M -
free
:空闲的内存大小 -
used
:已使用的内存大小 -
buff/cache
:已缓存的内存大小
第五行
-
total
:Swap大小 -
free
:空闲的Swap大小 -
used
:已使用的Swap大小 -
avail Mem
:已缓存的Swap大小
进程列表
-
PID
:进程的id -
USER
:进程的拥有者 -
PR
:进程的优先级,值越小越优先执行 -
NI
:进程nice值,正值表示降低进程优先级,负值表示提高进程优先级,nice取值范围为(-20,19),默认情况下,进程的nice值为0 -
VIRT
:进程占用的虚拟内存大小 -
RES
:进程占用的物理内存大小 -
SHR
:进程占用的共享内存大小 -
S
:进程状态,其中S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数 -
%CPU
:进程CPU使用率 -
%MEM
:进程内存使用率 -
TIME+
:进程启动后占用CPU的总时间,即占用CPU使用时间的累加值 -
COMMAND
:进程启动命令名称
出现CPU使用率高诊断方法: 1)找出调用的函数
top -H
perf top -p xxx
xxx为top -H返回最消耗CPU的进程。
2)找出消耗CPU的SQL
pidstat -t -p <mysqld_pid> 1 5
select * from performance_schema.threads where thread_os_id = xxx\G
select * from information_schema.processlist where id = performance_schema.threads.processlist_id\G
xxx为pidstat返回最消耗CPU的线程。
内存
top、vmstat、free都可以检查内存的使用情况。
free返回结果示例如下:
# free -g
total used free shared buff/cache available
Mem: 251 44 1 0 205 205
Swap: 7 0 7
total
:物理内存总大小,total = used + free + buff/cacheused
:已使用的内存大小free
:空闲的内存大小shared
:共享内存大小buff/cache
:缓存内存大小available
:可用物理内存大小,available = free + buff/cache
出现内存使用率高诊断方法:
1)检查配置是否合理,例如:操作系统物理内存128G,而分配给数据库实例110G,由于操作系统进程和其它应用程序也需要内存,很容易导致内存被消耗光;
2)检查并发连接数是否过高,read_buffer_size、read_rnd_buffer_size、sort_buffer_size、thread_stack、join_buffer_size、binlog_cache_size都是session级别的,连接数越多,需要的内存就越多,因此这些参数也不能设置太大;
3)检查是否有不合理的join,例如:多表关联时,执行计划中驱动表的结果集比较大,需要循环多次执行,容易导致内存泄漏;
4)检查打开文件数是否过多和table_open_cache是否设置合理,访问一个表时,会将该表放入缓存区table_open_cache,目的是下次可以更快的访问,但如果table_open_cache设置太大,且打开的表又多的情况下,是很消耗内存的。
IO
iostat、dstat、pidstat都可以检查IO的使用情况。
iostat返回结果示例如下:
# iostat -x 1 1
Linux 3.10.0-957.el7.x86_64 (htap2) 06/13/2022 _x86_64_ (64 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.06 0.00 0.03 0.01 0.00 99.90
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.00 0.00 0.00 0.04 0.00 85.75 0.00 0.25 0.25 0.00 0.15 0.00
sdb 0.06 0.11 7.61 1.10 1849.41 50.81 436.48 0.36 40.93 46.75 0.48 1.56 1.35
dm-0 0.00 0.00 0.28 0.19 8.25 12.05 87.01 0.00 4.81 7.37 0.94 1.61 0.08
-
rrqm/s
: 每秒进行merge的读操作数 -
wrqm/s
: 每秒进行merge的写操作数 -
r/s
:每秒读IO次数 -
w/s
:每秒写IO次数 -
rkB/s
:每秒读IO大小,单位为KB -
wkB/s
:每秒写IO大小,单位为KB -
avgrq-sz
:平均请求大小,单位为扇区(512B) -
avgqu-sz
:在驱动请求队列和在设备中活跃的平均请求数 -
await
:平均IO响应时间,包括在驱动请求队列里的等待和设备的IO响应时间 -
r_await
:每次读操作IO响应时间 -
w_await
:每次写操作IO响应时间 -
svctm
:磁盘设备的IO平均响应时间 -
%util
:设备忙处理IO请求的百分比(使用率),磁盘的繁忙程度 -
r/s + w/s
:IOPS
出现IO使用率高诊断方法: 1)找出使用率最高的磁盘设备
iostat -x -m 1
iostat -d /dev/sda -x -m 1
2)找出占用IO高的应用程序
pidstat -d 1
3)找出占用IO高的线程
pidstat -dt -p mysqld_id 1
4)找出占用IO高的SQL
select * from performance_schema.threads where thread_os_id = xxx\G
select * from information_schema.processlist where id = performance_schema.threads.processlist_id\G
xxx为pidstat返回最消耗IO的线程。