一个诊断案例()
我们看到了两种可能性要么是数据库导致了I/O(如果能找到源头的话那么可能就找到了问题的原因)要么不是数据库导致了所有的I/O 而是其他什么导致的而系统因为缺少I/O 资源影响了数据库性能我们也很小心地尽力避免引入另外一个隐式的假设磁盘很忙并不一定意味着MySQL 会有问题要记住这个服务器主要的压力是内存读取所以也很可能出现磁盘长时间无法响应但没有造成严重问题的现象
如果你一直跟随我们的推理逻辑就可以发现还需要回头检查一下另外一个假设我们已经知道磁盘设备很忙因为其等待时间很高对于固态硬盘来说其I/O 平均等待时间一般不会超过/ 秒实际上从iostat 的输出结果也可以发现磁盘本身的响应还是很快的但请求在块设备队列中等待很长的时间才能进入到磁盘设备但要记住这只是iostat 的输出结果也可能是错误的信息
究竟是什么导致了性能低下?
当一个资源变得效率低下时应该了解一下为什么会这样有如下可能的原因
资源被过度使用余量已经不足以正常工作
资源没有被正确配置
资源已经损坏或者失灵
回到上面的例子中iostat 的输出显示可能是磁盘的工作负载太大也可能是配置不正确(在磁盘响应很快的情况下为什么I/O 请求需要排队这么长时间才能进入到磁盘?)然而比较系统的需求和现有容量对于确定问题在哪里是很重要的一部分大量的基准测试证明这个客户使用的这种SSD 是无法支撑几百MB/s 的写操作的所以尽管iostat 的结果表明磁盘的响应是正常的也不一定是完全正确的在这个案例中我们没有办法证明磁盘的响应比iostat 的结果中所说的要慢但这种情况还是有可能的所以这不能改变我们的看法可能是磁盘被滥用注或者是错误的配置或者两者兼而有之是性能低下的罪魁祸首
在检查过所有诊断数据之后接下来的任务就很明显了测量出什么导致了I/O 消耗不幸的是客户当前使用的GNU/Linux 版本对此的支持不力通过一些工作我们可以做一些相对准确的猜测但首先还是需要探索一下其他的可能性我们可以测量有多少I/O来自MySQL但客户使用的MySQL 版本较低以致缺乏一些诊断功能所以也无法提供确切有利的支持
作为替代基于我们已经知道MySQL 如何使用磁盘我们来观察MySQL 的I/O 情况通常来说MySQL 只会写数据日志排序文件和临时表到磁盘从前面的状态计数器和其他信息来看首先可以排除数据和日志的写入问题那么只能假设MySQL 突然写入大量数据到临时表或者排序文件如何来观察这种情况呢?有两个简单的方法一是观察磁盘的可用空间二是通过lsof 命令观察服务器打开的文件句柄这两个方法我们都采用了结果也足以满足我们的需求下面是问题期间每秒运行df–h 的结果
下面则是lsof 的数据因为某些原因我们每五秒才收集一次我们简单地将mysqld 在/tmp 中打开的文件大小做了加总并且把总大小和采样时的时间戳一起输出到结果文件中
$ awk
/mysqld*tmp/ {
total += $;
}
/^Sun Mar / && total {
printf %s %f MB\n $ total//;
total = ;
} lsoftxt
:: MB
:: MB
:: MB
:: MB
:: MB
从这个数据可以看出在问题之初MySQL 大约写了GB 的数据到临时表这和之前在SHOW PROCESSLIST 中有大量的Copying to tmp table相吻合这个证据表明可能是某些效率低下的查询风暴耗尽了磁盘资源根据我们的工作直觉出现这种情况比较普遍的一个原因是缓存失效当memcached 中所有缓存的条目同时失效而又有很多应用需要同时访问的时候就会出现这种情况我们给开发人员出示了部分采样到的查询并讨论这些查询的作用实际情况是缓存同时失效就是罪魁祸首(这验证了我们的直觉)一方面开发人员在应用层面解决缓存失效的问题另一方面我们也修改了查询避免使用磁盘临时表这两个方法的任何一个都可以解决问题当然最好是两个都实施
返回目录高性能MySQL
编辑推荐
ASP NET开发培训视频教程
数据仓库与数据挖掘培训视频教程
Oracle索引技术