天天看点

Mysql 45讲学习笔记(三十三)全表扫描为啥不会OOM(out of memory)

一.全表扫描server层如何执行

使用场景:

       我们现在要对一个200G的InnoDB表执行全表扫描:

mysql -h$host -P$port -u$user -p$pwd -e "select * from db">$target_file      

取数据和发数据的流程:

  • 获取一行,写到net_buffer中,这块内存的大小是由参数net_buffer_length定义,默认16k
  • 重复,知道16k写满,网络接口发送出去,并清空缓存
  • 直到函数返回EAGAIN 或 WSAEWOULDBLOCK,表示本地网络栈(socket send buffer)写满了,表示本地网络栈写满了,进入等待。直到网络栈重新可写,继续发送。
Mysql 45讲学习笔记(三十三)全表扫描为啥不会OOM(out of memory)
  • MySQL 是“边读边发的”---流式
  • 客户端接收 慢,导致MySQL服务端结果发布出去 ,事务执行时间变长

二.全表扫描对InnoDB

   Buffer Pool两个作用:

  • 加速更新
  • 加速查询  (查询不需要读磁盘,直接从内存中取结果)

内存命中率

查看方式: 

show engine innodb status结果,查看系统当前的BP命中率      

InnoDB Buffer Pool的大小由参数innodb_buffer_pool_size,一般建议设置成可用物理内存60%-80%

Buffer Pool如何淘汰数据

三.Least Rencently Used--LRU算法

存在问题:

  • 全表扫描的时候,Buffer Pool 里的数据全部淘汰掉,存入扫描过程中访问到的数据页的内容
  • 此时,业务数据进来会导致内存命中率急剧下降,磁盘压力增加,SQL 语句响应变慢

解决方案: