我有一个看起来像这样的查询:
SELECT id FROM user WHERE id='47'
对ID进行索引,并且在使用分析数据时,此查询的读取总是很快,如下所示.
SET profiling = 1; SHOW PROFILES;
查询总是在0.0002秒左右执行.
但是,如果我从PHP端分析查询,如下所示:
$current = microtime(true); $data = $conn->query($full_query); $elapsed = microtime(true) - $current;
然后偶尔可能有50个这样的查询会花费0.2秒.但是,在我的测试脚本中,我有代码来测试它,使用SET profiling = 1来描述查询; 即使PHP通过PDO往返可能是0.2秒,查询时间仍然是0.0002.
我知道的事情,或者知道没有引起问题:
查询并不慢.当我查看相同的查询时,从同一个查询运行,在PHP中进行分析并使用SET PROFILING进行分析,查询总是很快,并且从不记录在慢查询日志中,即使它显示从PHP端获取.2秒.
这不是与skip-name-resolve相关的 - 这是不一致的,我已经跳过了name-resolve-resolve
这与查询缓存无关,两者都存在这种行为
即使从缓存中出来的查询,也会发生此行为.
查询实际上并没有选择ID,但是我使用此查询进行测试以显示它不是磁盘访问问题,因为该字段肯定是索引的.
这个表只有10-20兆,类似1兆指数.机器显示非常小的负载,innodb没有使用它的所有缓冲区.
这是针对除了我的测试查询之外没有针对它的其他活动的表进行测试的.
有没有人知道还有什么要检查?在我看来,这似乎是一个网络问题,但我需要能够看到它并找到问题来解决它,而且我已经没有地方可以检查下一步了.有任何想法吗?
很高兴你已经使用了查询分析器.如果您使用的是MySQL 5.6,那么您还可以在PERFORMANCE_SCHEMA中访问许多新的性能测量.与查询分析器相比,它具有测量更多细节的能力,并且还可以全局测量而不是仅测量一个会话.据报道,P_S将取代查询分析器.
为了诊断您的问题,我首先要确认或排除TCP/IP问题.例如,测试PHP脚本以查看在通过UNIX套接字连接时是否会出现相同的间歇性延迟.您可以通过连接到localhost
这意味着PHP脚本必须在与数据库相同的服务器上运行.如果绕过TCP/IP时问题消失,这将告诉您根本原因可能是TCP/IP.
如果您处于虚拟环境(如云托管)中,则可以轻松体验性能差异,因为同一云的其他用户会间歇性地耗尽所有带宽.这是云的缺点之一.
如果您怀疑它是TCP/IP问题,您可以独立于PHP或MySQL测试TCP/IP延迟.现成的典型工具包括ping
或traceroute
.但还有很多其他的.您还可以使用netcat测试网络速度.使用可以随时间重复测量的工具,因为它听起来大多数时候都有良好的性能,偶尔会出现故障.
另一种可能性是错误在于PHP.您可以尝试使用XHProf对PHP进行分析,以找出它花费时间的位置.
我在我的系统上发现了同样的现象.通常需要一毫秒的查询将突然需要1-2秒.我的所有情况都是简单的单表INSERT/UPDATE/REPLACE语句---不在任何SELECT上.没有明显的负载,锁定或螺纹堆积.
我怀疑它是由于清除了脏页,刷新磁盘更改或一些隐藏的互斥锁,但我还没有将其缩小.
也排除了
服务器负载 - 与高无关
加载引擎 - 与InnoDB/MyISAM /内存MySQL查询一起发生
缓存 - 无论是打开还是关闭
记录旋转 - 事件中没有相关性
我会描述一下这台机器.
你说这种情况每50次发生一次,每次查询都有0.2秒的基准.您应该能够在屏幕中放置顶部,然后在PHP中运行查询循环以加载测试RDBMS并收集性能统计信息.
您可能需要运行更多50 * 0.2 =
10 seconds
,因为您的"50分之一"统计数据可能基于手动运行的个人查询 - 基于我在您的描述中阅读的内容.尝试30秒和90秒的负载测试.
在此期间,请观看您的top
过程屏幕.按下按CPU排序P
.每按一次'P',它将改变进程CPU消耗的排序顺序,因此请确保您拥有最耗费的消息.(按M
内存使用情况排序.请查看手册页以获取更多信息)
在负载测试的时间内寻找任何冒泡的东西.你应该看到一些东西跳得更高 - 但是暂时.
(注意,这样的进程可能无法到达列表的顶部 - 它不需要,但仍然可能引入足够的磁盘负载或其他活动来延迟MySQL服务器)