系统报警,数据库CPU达到了100%。接着业务部门的投诉接踵而来。因为是老司机,所以处理问题也比较“按部就班“。
(画外之音:这不是第一次了,随着系统的开发,一些慢sql会时不时的渗入。这种情况经常遇到。)
导致CPU打满的情况比较多,最常见的就是慢查询,导致链接无法释放,逐渐堆积占用了大量数据库资源。
直接查询mysql 的线程, show processList 。 看到了大量的【converting HEAP to MyISAM】线程。这次应该不是慢查询导致。该语句表明了在执行过程中,内存临时表转变成了硬盘临时表。说明有问题的sql导致了产生了大量临时表,但是内存表空间不够了,需要写入硬盘进行文件排序,再写回。到底是什么语句导致了临时表的生成呢?
来看看sql,一个很大的统计sql。用EXPLAIN分析了一下执行计划,发现了问题。
一个多表外链接查询,在最后用了sort,结果导致了大量数据进行内存排序,结果空间不够,进行了文件排序。占用了链接很长时间。最简的修正方案就是修改tmp_table_size。但是这不是最好的方案,就是优化一下sql。
优化后的sql和效果如下
就是把排序挪到了主表里,而不是在最外面,减少了排序的条数。这样就可以在内存解决,不需要写入硬盘进行文件排序了。
整个过程也就20分钟。不知道大家的公司容忍度是多长时间呢?