Mysql优化查询时对内存的利用

Posted by KANG's BLOG on Tuesday, March 15, 2022

1. 服务层

Mysql查询时数据传输流程

  1. 获取一行,写到net_buffer。该内存大小由参数net_buffer_length定义,默认16k

    -- 查询net_buffer大小
    show variables like 'net_buffer_length';
    
  2. 继续获取行,直到写满net_buffer,发出去

  3. 若发送成功,则清空net_buffer,继续读取下一行,并写入net_buffer(避免了OOM)

  4. 若发送返回EAGAIN或WSAEWOULDBLOCK,表示本地网络栈(socket send buffer)写满,进入等待。直到网络栈重新可写,再继续发送

2. InnoDB引擎

由于WAL特性,事务结束后数据并未立刻刷新到磁盘上,但此时查询数据为什么不会出现不一致问题呢?

原因在于最新的数据存在于Buffer Pool中,查询时会优先查找BP中的数据。

什么是Buffer Pool

BP大小由参数innodb_buffer_pool_size决定,推荐设成可用物理内存的60%~80%,

可通过如下命令查询BP命中率

show engine innodb status

其BP的刷新策略为改良版的LRU算法,其分为New和Old区,其新插入的数据仅仅进入Old区。

处于old区的数据页,每次被访问时,都要判断:

  • 若该数据页在LRU链表中存在时间>1s,就把它移动到链表头部

  • 若该数据页在LRU链表中存在时间<1s,位置保持不变

所以即使全表扫描的场景,由于大部分数据均为低频访问,所以并不会占据算法中指向的较新的位置。