您现在的位置是:主页 > 数据库技术 > 数据库技术

MySQL数据查询太多会怎么样

IDCBT2022-01-12服务器技术人已围观

简介这篇文章主要介绍“MySQL数据查询太多会怎么样”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“MySQL数据查询太多会怎么样”文章能帮

这篇文章主要介绍“MySQL数据查询太多会怎么样”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“MySQL数据查询太多会怎么样”文章能帮助大家解决问题。

主机内存只有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被写满,就会暂停读数据的流程

    所以MySQL其实是“边读边发”。这意味着,若客户端接收得慢,会导致MySQL服务端由于结果发不出去,这个事务的执行时间变长。

    比如下面这个状态,就是当客户端不读**「socket receive buffer」**内容时,在服务端show processlist看到的结果。

    服务端发送阻塞

    若看到State一直是“Sending to client”,说明服务器端的网络栈写满了。

    若客户端使用–quick参数,会使用mysql_use_result方法:读一行处理一行。假设某业务的逻辑较复杂,每读一行数据以后要处理的逻辑若很慢,就会导致客户端要过很久才取下一行数据,可能就会出现上图结果。

    因此,对于正常的线上业务来说,若一个查询的返回结果不多,推荐使用**「mysql_store_result」**接口,直接把查询结果保存到本地内存。

    标签:

    很赞哦! ()

本栏推荐