服务端并不需要保存一个完整的结果集。 取数据和发数据的流程是这样的:
1. 获取一行, 写到net_buffer中。 这块内存的大小是由参数net_buffer_length定义的, 默认是16k。
2. 重复获取行, 直到net_buffer写满, 调用网络接口发出去。
3. 如果发送成功, 就清空net_buffer, 然后继续取下一行, 并写入net_buffer。
4. 如果发送函数返回EAGAIN或WSAEWOULDBLOCK, 就表示本地网络栈(socket sendbuffer) 写满了, 进入等待。 直到网络栈重新可写, 再继续发送。

如果客户端使用–quick参数, 会使用mysql_use_result方法。 这个方法是读一行处理一行。 你可以想象一下, 假设有一个业务的逻辑比较复杂, 每读一行数据以后要处理的逻辑如果很慢, 就会导致客户端要过很久才会去取下一行数据, 可能就会出现如图2所示的这种情况
与“Sending to client”长相很类似的一个状态是“Sending data”, 这是一个经常被误会的问题。
有同学问我说, 在自己维护的实例上看到很多查询语句的状态是“Sending data”, 但查看网络也没什么问题啊, 为什么Sending data要这么久?
实际上, 一个查询语句的状态变化是这样的(注意: 这里, 我略去了其他无关的状态) :
1 MySQL查询语句进入执行阶段后, 首先把状态设置成“Sending data”;
2 然后, 发送执行结果的列相关的信息(meta data) 给客户端;
3 再继续执行语句的流程;
4 执行完成后, 把状态设置成空字符串
“Sending data”并不一定是指“正在发送数据”, 而可能是处于执行器过程中的任意阶段。 比如, 你可以构造一个锁等待的场景, 就能看到Sending data状态
在InnoDB实现上, 按照5:3的比例把整个LRU链表分成了young区域和old区域。 图中LRU_old指向的就是old区域的第一个位置, 是整个链表的5/8处。 也就是说, 靠近链表头部的5/8是young区
域, 靠近链表尾部的3/8是old区域
