作者回复: 好问题👍 很好的思考👍
是这样的,net_buffer_length 的最大值是 1G,这个值比 socket send buffer大(一般是几M)
比如假设一个业务,他的平均查询结果都是10M (当然这个业务有有问题,最终是要通过业务解决)
但是如果我把net_buffer_length 改成10M,就不会有“Sending to client” 的情况。虽然网络栈还是慢慢发的,但是那些没发完的都缓存在net_buffer中,对于执行器来说,都是“已经写出去了”。
作者回复: 非常好,正是我要说明的一个场景呢,直接用你的例子放在下篇答疑部分哈
作者回复: 1. “是一行一行的扔给socket send buffer,还是把net_buffer 里的内容一下子全部扔给 socket send buffer ?”
---- net_buffer写满,一起发,然后清空net_buffer,组装下一批 。好问题
2. 跟上一个问题同一个答案;
3. “对于一个查询,执行器拿到的所有结果,如果可以一次性放入net_buffer, 对于执行器来说是不是意味着“全都写出去了”,也就不会有 sending to client 状态?” ----是的
4. 是的
5. 对,这个就是我们其他文章中介绍的,“带着邻居节点一起刷”的那个阶段。
作者回复: 你的理解是对的,每个线程(session)一个
作者回复: 对,这种一般就是用mysql_use_result
各有优劣吧
一次性取的好处是,对服务端只全表,只扫描一遍;坏处是可能会出现大事务。
一般更常见的做法是,分批取,然后每一批拿到最大的一个id(主键值)
下一批查询的时候用 where Id > N 这种写法
好问题
作者回复: 👍
再考虑下都是update的情况 😆
作者回复: 网络栈 socket receive buffer 写满了
作者回复: 对的
作者回复: 会的
作者回复: 写net_buffer -- > net_buffer满了,调用网络接口发 -->发不出去
这个是同一个调用链条呀
“哪个阶段”没看懂,是同一个时刻
作者回复: 满16k就发给socket send buffer
作者回复: 你把他们当作两个单独的行为,只是刚好共同同一个文件系统而已
作者回复: InnoDB 的是buffer pool,是在内存里。
”内存重启了之后,缓存不就也丢失了,是怎么做到持久化保存的,老师可以帮忙详细解答下么?“
没有保存,重启就没有了,要访问的时候需要重新去磁盘读
作者回复: 还是会显示为“Sending to client”,但是语句已经执行完了。
不会占着资源(比如MDL读锁)
作者回复: 1. 是 ,但是也不是“全部放到buffer pool以后”才发,读的时候是一个page 一个page 地读的
2. 会,好在这个是“某一页”而已,量不大。 好问题
很好的思考
作者回复: “保存一段时间”是啥意思,LRU算法不是按照时间的哈,如果没人来淘汰,是可以一直保存的。
作者回复: 嗯,这个不会返回结果到客户端,所以网络上不会有问题
引擎内部的扫描机制是差不多的
唯一不同是这个过程可能对原表有行锁(如果设置的是RR)
万或者十万还好,是小数据,可以考虑拿到客户端再写回去,避免锁的问题
作者回复: 这三个问题其实是同一个
“边读边发”的意思是,算出来的结果才能发
像order by,得先排序得到结果,然后才发出去,如果读了数据直接发,那肯定不行,那是错误的结果。
所以要排序了以后再发,这时候就需要中间数据结构,sort buffer