(1)SQL调优利器
    上一讲在当时这个案例的场景发生之后,也就是针对某个表的大量简单的单行数据查询SQL变成慢查询,我们先排查了执行计划以及MySQL服务器负载,发现没有问题。此时必须用上一个SQL 调优的利器,也就是profiling工具,这个工具可以对SQL语句的执行耗时进行非常深入和细致的分析,使用这个工具的过程,大致如下所示:

    (2)调优利器的使用: profiling MySQL 剖析工具可以检测执行这个SQL语句的负载情况
    首先打开这个profiling,使用set profiling=1这个命令,接着MySQL就会自动记录查询语句的profiling信息了。此时如果执行show profiles命令,就会列出各种查询语句的profiling 信息,这里很关键的一点,就是他会记录每个查询语句的id,所以要针对需要分析的query找到他对应的query id,针对慢查询的那个SQL语句找到query id,然后就可以针对单个查询语句,看一下 他的profiling具体信息,使用show profile cpu,block io for query id ,除了cpu以及block io以外,还可以指定去看这个SQL语句执行时候的其他各项负载和耗时,具体自行网上搜索。
    这里会给你展示各种耗时,比如磁盘IO的耗时,CPU等待耗时,发送数据耗时,拷贝数据到临时表的耗时,等等,反正SQL执行过程中的耗时都会展示出来。当时检查profiling信息发现 一下重点问题,就是Sending Data的耗时是最高的,几乎使用了1s,占据了SQL执行耗时的99%,这个就很坑了, MySQL官方解释如下:Sending Data为一个SELECT语句读取和处理数据行,同时 发送数据给客户端的过程,简单来说,就是为你的SELECT语句把数据读取出来,同时发送个客户端。

    可为什么这个过程这么慢,profiling确实提供了更多的线索,但是没法解决掉问题,但是毕竟已经捕获到一个比较异常的点,就是Sending Data耗时高,
    接着我们又用了一个命令,show engine innodb status; 看下innodb存储引擎的一些状态,发现一个奇怪的指标,就是history list length 这个指标,这个值特别高,达到上万级别, MVVC机制:说白了就是多个事务在对同一个数据,有人读,有人写,此时可以有多种隔离级别,至于这个MVVC和隔离级别的实现原理,跟一个Read View机制是有关的,同时还有一个至关重要的机制, 就是数据的undo多版本快照链条,必须对一个数据得有一个多版本快照链条,才能实现MVVC和各种隔离级别,这个具体得原理,可以看之前得文章,所以当执行大量事务得时候,就会构建这种undo 多版本链条,此时history list length 的值就会很高,然后在事务提交之后,会有一个多版本快照链条的自动purge清理机制,只要有清理,那么这个值就会降低
    一般来说,这个值不应该过高,所以在这里注意到第二个线索,history list length值过高,大量的undo多版本链条数据没被清理!推测很可能就是有的事务长时间运行,所以他的多版本 快照不能被purge清理掉,进而导致了这个 history list length 的值过高。

    (3)总结
    基本上可以肯定的一点是,经过两个线索的推测,在大量简单SQL语句变成慢查询的时候,SQL因为Sending Data 环节异常耗时过高,同时此时出现了一些长事务长时间运行,大量的频繁更新 数据,导致有大量的undo 多版本快照链条,还无法purge清理掉。
    但是这两个线索之间的关系是什么呢?是第二个线索推导出的事务长时间运行现象的发生,进而导致了第一个线索发现的Sending Data耗时过高的问题?可是二者之间的关系是什么呢?是不是 还得有更多的线索才行?