MySQL的边查边发机制,可以结合以下文字和图片阅读:

mysql 打印sql dataSource_MySQL


当要执行一个大查询时,MySQL会将查询结果分批次发送给客户端,并不是在服务端查到所有数据后一次性发送给客户端;

Server层:

MySQL通过将查询到的结果依次存入net_buffer中,按页发送给客户端,并且在net_buffer发送数据给客户端的过程中,MySQL继续执行查询操作(边查边发),但是只有等客户端完全接受了net_buffer中的数据后,net_buffer才会清空,MySQL才能将最近查到的数据写入net_buffer中。

所以客户端读取速度会影响MySQL发送数据的速度。一般客户端有两种读取数据的方法:

  • mysql_use_result:这个设置使得客户端按行从net_buffer中读取数据,读一行去执行一遍用户的逻辑操作,大大加长了读取数据的时间,所以MySQL经常会卡在将数据写入net_buffer的环节(MySQL查询线程处于Sending to client状态)。
  • mysql_store_result:该设置时,客户端会一次性将net_buffer中的数据放入内存中,之后再去执行用户的逻辑操作,这样net_buffer就会很快清空,MySQL可以无阻塞写入,但是查询结果多的时候,客户端内存被占用率大。

InnoDB层

再看一下MySQL的InnoDB层是如何具体执行查询操作的(改进的LRU算法),LRU最近最少使用算法基本流程如下:

  1. 首先MySQL会去内存中找数据页,内存中多张数据页以链表的顺序存储(按照最近被访问的数据页放在最前面的原则),依次从头结点访问尾节点,如果命中内存,直接读取数据到server层,然后server层将数据写入到net_buffer。
  2. 如果内存中不存在该数据,就去磁盘IO查询数据页,因为该数据页是最新被访问的,所以加入到链表的头结点
  3. 当链表中节点满了,就要先删除尾节点(最久未被访问的数据页),再插入头结点的最新从磁盘读取的数据页。

为了提高MySQL的查询速度,最主要的就是提高InnoDB层的内存命中率,MySQL在以上LRU算法的基础上进行了改进,进一步提高了内存命中率。