背景:

某一天,一个客户打电话来需要技术帮助,并抱怨平常15秒就可以打开的网页现在需要20分钟才可以打开.

具体系统配置如下:

RedHat Enterprise Linux 3 update 7

Dell 1850 Dual Core Xenon Processors, 2 GB RAM, 75GB 15K Drives

Custom LAMP software stack(译注:Llinux+apache+mysql+php 环境)

性能分析之步骤

7.1. 首先使用vmstat 查看大致的系统性能情况

分析:

  1. 不会是内存不足导致,因为swapping 始终没变化(si 和 so).尽管空闲内存不多(free),但swpd 也没有变化.

  2. CPU 方面也没有太大问题,尽管有一些运行队列(procs r),但处理器还始终有50% 多的idle(CPU id).

  3. 有太多的上下文切换(cs)以及disk block从RAM中被读入(bo).

  4. CPU 还有平均20% 的I/O 等待情况.

结论:


从以上总结出,这是一个I/O 瓶颈.


7.2. 然后使用iostat 检查是谁在发出IO 请求

分析:

看上去只有/dev/sda3 分区很活跃,其他分区都很空闲.

差不多有1200 读IOPS,磁盘本身是支持200 IOPS左右(译注:参考之前的IOPS 计算公式).

有超过2秒,实际上没有一个读磁盘(rkb/s).这和在vmstat 看到有大量I/O wait是有关系的.

大量的read IOPS(r/s)和在vmstat 中大量的上下文是匹配的.这说明很多读操作都是失败的.

结论:


从以上总结出,部分应用程序带来的读请求,已经超出了I/O 子系统可处理的范围.


7.3. 使用top 来查找系统最活跃的应用程序

分析:

占用资源最多的好像就是mysql 进程,其他都处于完全idle 状态。

在top(wa) 看到的数值,和在vmstat 看到的wio 数值是有关联的.

结论:

从以上总结出,似乎就只有mysql 进程在请求资源,因此可以推论它就是导致问题的关键.

7.4. 现在已经确定是mysql 在发出读请求,使用strace 来检查它在读请求什么.

分析:

大量的读操作都在不断寻道中,说明mysql 进程产生的是随机IO.

看上去似乎是,某一sql 查询导致读操作.

结论:

从以上总结出,所有的读IOPS 都是mysql 进程在执行某些读查询时产生的.

7.5. 使用mysqladmin 命令,来查找是哪个慢查询导致的.

# ./mysqladmin -pstrongmail processlist

+—-+——+———–+————+———+——+———-+—————————————-
| Id | User | Host | db | Command | Time | State | Info
+—-+——+———–+————+———+——+———-+—————————————-
| 1 | root | localhost | strongmail | Sleep | 10 | |
| 2 | root | localhost | strongmail | Sleep | 8 | |
| 3 | root | localhost | root | Query | 94 | Updating | update `failures` set
`update_datasource`=’Y’ where database_id=’32′ and update_datasource=’N’ and |
| 14 | root | localhost | | Query | 0 | | show processlist

分析:

MySQL 数据库里,似乎在不断的运行table update查询.

基于这个update 查询,数据库是对所有的table 进行索引.

结论:

从以上总结出,MySQL里这些update 查询问题,都是在尝试对所有table 进行索引.这些产生的读请求正是导致系统性能下降的原因.

7.6. 后续

把以上这些性能信息移交给了相关开发人员,用于分析他们的PHP 代码.一个开发人员对代码进行了临时性优化.某个查询如果出错了,也最多到100K记录.数据库本身考虑最多存在4百万记录.最后,这个查询不会再给数据库带来负担了.