MySQL是怎么发数据给客户端的以及MySQL的缓存策略改进

我查这么多数据,会不会把数据库内存打爆?

肯定的说,不会。因为MySQL是边读边发的。

InnoDB 的数据是保存在主键索引上的,所以全表扫描实际上是直接扫描表 t 的主键索引。这条查询语句由于没有其他的判断条件,所以查到的每一行都可以直接放到结果集里面,然后返回给客户端。那么,这个“结果集”存在哪里呢?实际上,服务端并不需要保存一个完整的结果集。取数据和发数据的流程是这样的:

  • 获取一行,写到 net_buffer 中。这块内存的大小是由参数 net_buffer_length 定义的,默认是 16k。
  • 重复获取行,直到 net_buffer 写满,调用网络接口发出去。
  • 如果发送成功,就清空 net_buffer,然后继续取下一行,并写入 net_buffer。
  • 如果发送函数返回 EAGAIN 或 WSAEWOULDBLOCK,就表示本地网络栈(socket send buffer)写满了,进入等待。直到网络栈重新可写,再继续发送。

show processlist 中 Sending data 状态怎么理解?

Sending data 状态表示MySQL执行器开始工作中,将状态设置为Sending data,

如果State 状态是Sending to client 则表示服务器端的网络栈写满了。增加net_buffer_length 参数可以快速减少处于Sending to client 状态的线程数量。

谈谈MySQL缓存的LRU算法

Buffer Pool 是MySQL 的本地缓存,更新数据时可以先更新到本地缓存,配合redo log ,避免随机写盘。Buffer Pool 还有一个作用就是加速查询,怎么加速查询呢,如果内存数据页有,直接读内存页就可以了。
另一个跟更新有关的缓存时change buffer, change buffer也是buffer pool的一部分,当要更新的数据页不在缓存中时,直接把更新的改动写到change buffer,提高写能力。change buffer中的改动最终会merge到内存的数据页中,触发的时机为:

  • 当从数据库加载数据页;
  • 定时merge到数据库
  • mysql数据库关闭时。

change buffer也会持久化。存在唯一键场景下,每次都要读取内存页判断是否存在唯一键冲突,就不会用到change buffer。如果更新数据后就需要马上读取数据,change buffer反而马上需要merge到数据页,这种场景也不太适合change buffer

MySQL 将内存分为young 和 old 区域,yound占靠近链表头整个链表长度的5 / 8 ,剩下靠近链表尾部3 / 8为old区域。

访问更新策略为:

命中:

  1. 处于yound区域,直接移到链表头
  2. 处于old区域,如果它在old区域存在时间超过了1秒,就移到链表头,否则保持位置不变。1秒这个参数由 innodb_old_blocks_time控制。
posted @ 2022-07-28 23:33  yihailin  阅读(286)  评论(0编辑  收藏  举报