3.4.1 单条查询问题还是服务器问题(1)
发现问题的蛛丝马迹了吗?如果有,则首先要确认这是单条查询的问题,还是服务器的问题。这将为解决问题指出正确的方向。如果服务器上所有的程序都突然变慢,又突然都变好,每一条查询也都变慢了,那么慢查询可能就不一定是原因,而是由于其他问题导致的结果。反过来说,如果服务器整体运行没有问题,只有某条查询偶尔变慢,就需要将注意力放到这条特定的查询上面。
服务器的问题非常常见。在过去几年,硬件的能力越来越强,配置16 核或者更多CPU的服务器成了标配,MySQL 在SMP 架构的机器上的可扩展性限制也就越来越显露出来。尤其是较老的版本,其问题更加严重,而目前生产环境中的老版本还非常多。新版本MySQL 依然也还有一些扩展性限制,但相比老版本已经没有那么严重,而且出现的频率相对小很多,只是偶尔能碰到。这是好消息,也是坏消息:好消息是很少会碰到这个问题;坏消息则是一旦碰到,则需要对MySQL 内部机制更加了解才能诊断出来。当然,这也意味着很多问题可以通过升级到MySQL 新版本来解决。
那么如何判断是单条查询问题还是服务器问题呢?如果问题不停地周期性出现,那么可以在某次活动中观察到;或者整夜运行脚本收集数据,第二天来分析结果。大多数情况下都可以通过三种技术来解决,下面将一一道来。
使用SHOW GLOBAL STATUS
这个方法实际上就是以较高的频率比如一秒执行一次SHOW GLOBAL STATUS 命令捕获数据,问题出现时,则可以通过某些计数器(比如Threads_running、Threads_connected、Questions 和Queries)的“尖刺”或者“凹陷”来发现。这个方法比较简单,所有人都可以使用(不需要特殊的权限),对服务器的影响也很小,所以是一个花费时间不多却能很好地了解问题的好方法。下面是示例命令及其输出:
$ mysqladmin ext -i1 | awk '
/Queries/{q=$4-qp;qp=$4}
/Threads_connected/{tc=$4}
/Threads_running/{printf "%5d %5d %5d\n", q, tc, $4}'
2147483647 136 7
798 136 7
767 134 9
828 134 7
683 134 7
784 135 7
614 134 7
108 134 24
187 134 31
179 134 28
1179 134 7
1151 134 7
1240 135 7
1000 135 7
这个命令每秒捕获一次SHOW GLOBAL STATUS 的数据,输出给awk 计算并输出每秒的查询数、Threads_connected 和Threads_running(表示当前正在执行查询的线程数)。这三个数据的趋势对于服务器级别偶尔停顿的敏感性很高。一般发生此类问题时,根据原因的不同和应用连接数据库方式的不同,每秒的查询数一般会下跌,而其他两个则至少有一个会出现尖刺。在这个例子中,应用使用了连接池,所以Threads_connected 没有变化。但正在执行查询的线程数明显上升,同时每秒的查询数相比正常数据有严重的下跌。
如何解析这个现象呢?凭猜测有一定的风险。但在实践中有两个原因的可能性比较大。其中之一是服务器内部碰到了某种瓶颈,导致新查询在开始执行前因为需要获取老查询正在等待的锁而造成堆积。这一类的锁一般也会对应用服务器造成后端压力,使得应用服务器也出现排队问题。另外一个常见的原因是服务区突然遇到了大量查询请求的冲击,比如前端的memcached 突然失效导致的查询风暴。
这个命令每秒输出一行数据,可以运行几个小时或者几天,然后将结果绘制成图形,这样就可以方便地发现是否有趋势的突变。如果问题确实是间歇性的,发生的频率又较低,也可以根据需要尽可能长时间地运行此命令,直到发现问题再回头来看输出结果。大多数情况下,通过输出结果都可以更明确地定位问题。
使用SHOW PROCESSLIST
这个方法是通过不停地捕获SHOW PROCESSLIST 的输出,来观察是否有大量线程处于不正常的状态或者有其他不正常的特征。例如查询很少会长时间处于“statistics”状态,这个状态一般是指服务器在查询优化阶段如何确定表关联的顺序——通常都是非常快的。另外,也很少会见到大量线程报告当前连接用户是“未经验证的用户(Unauthenticateduser)”,这只是在连接握手的中间过程中的状态,当客户端等待输入用于登录的用户信息的时候才会出现。
【责任编辑:book TEL:(010)68476606】
点赞 0