我的主机内存只有100G,现在要全表扫描一个200G大表,会不会把DB主机的内存用光?
逻辑备份时,可不就是做整库扫描吗?若这样就会把内存吃光,逻辑备份不是早就挂了?
所以大表全表扫描,看起来应该没问题。这是为啥呢?
全表扫描对server层的影响
假设,我们现在要对一个200G的InnoDB表db1. t,执行一个全表扫描。当然,你要把扫描结果保存在客户端,会使用类似这样的命令:
mysql -h$host -P$port -u$user -p$pwd -e
"select * from db1.t" > $target_file
InnoDB数据保存在主键索引上,所以全表扫描实际上是直接扫描表t的主键索引。这条查询语句由于没有其他判断条件,所以查到的每一行都可以直接放到结果集,然后返回给客户端。
那么,这个“结果集”存在哪里呢?
服务端无需保存一个完整结果集。取数据和发数据的流程是这样的:
- 获取一行,写到net_buffer。这块内存的大小是由参数net_buffer_length定义,默认16k
- 重复获取行,直到net_buffer写满,调用网络接口发出去
- 若发送成功,就清空net_buffer,然后继续取下一行,并写入net_buffer
- 若发送函数返回EAGAIN或WSAEWOULDBLOCK,就表示本地网络栈(socket send buffer)写满了,进入等待。直到网络栈重新可写,再继续发送
查询结果发送流程:
可见:
- 一个查询在发送过程中,占用的MySQL内部的内存最大就是net_buffer_length这么大,不会达到200G
- socket send buffer 也不可能达到200G(默认定义/proc/sys/net/core/wmem_default),若socket send buffer被写满,就会暂停读