做全表扫描时数据表的内存大于 MySQL 内存,会不会被打爆?

news2024/11/14 15:10:49

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

我的数据库内存只有10G,现在我要对一个20G的大表做全表扫描,会不会把数据库内存(buffer pool)占满然后报OOM的错误?

答案是不会的。

InnoDB的数据是保存在主键索引上面的(主键索引最全),所以全表扫描扫描的是主键索引,由于没有其他的判定条件,所以查询到的每一行都放到结果集里面,然后返回给客户端。

这个结果集在哪呢?

实际上,服务端并不会保存一个完成的结果集之后在发送。 取数据和发数据的流程是这样的:

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

这个过程对应的流程图如下:

看完上面的流程图,可以得到:

  1. 即便表的数据比我MySQL的内存大得多,占用的内存也仅仅是 net_buffer_length 大小,所以并不会把内存占满。
  2. socket send buffer 也不可能达到 200G ,如果 socket send buffer 被写满,就会暂停读数据的流程。

也就是说 MySQL 是边读边发的,如果客户端接收的速度跟不上 MySQL 服务端发送的速度,就会造成发送的时间变长。

如果你看到 State 的值一直处于“Sending to client”,就表示服务器端的网络栈写满了。

如果客户端使用–quick 参数,会使用 mysql_use_result 方法。这个方法是读一行处理一行。你可以想象一下,假设有一个业务的逻辑比较复杂,每读一行数据以后要处理的逻辑如果很慢,就会导致客户端要过很久才会去取下一行数据,可能就会出现如图所示(Sending to client)的这种情况。

因此,对于正常的线上业务来说,如果一个查询的返回结果不会很多的话,建议你使用 mysql_store_result 这个接口,直接把查询结果保存到本地内存(客户端本地)。

如果要快速减少处于这个状态的线程的话,将 net_buffer_length 参数设置为一个更大的值是一个可选方案。

与“Sending to client”长相很类似的一个状态是“Sending data” ,但是经过排查网络没有问题。

实际上,一个查询语句的状态变化是这样的:

  • MySQL 查询语句进入执行阶段后,首先把状态设置成“Sending data”;
  • 然后,发送执行结果的列相关的信息(meta data) 给客户端;
  • 再继续执行语句的流程;
  • 执行完成后,把状态设置成空字符串。

也就是说,“Sending data”并不一定是指“正在发送数据”,而可能是处于执行器过程中的任意阶段。

仅当一个线程处于“等待客户端接收结果”的状态,才会显示"Sending to client";而如果显示成“Sending data”,它的意思只是“正在执行”。

在 server 层的处理逻辑我们都清楚了,在 InnoDB 引擎里面又是怎么处理的呢? 扫描全表会不会对引擎系统造成影响呢?

全表扫描对 InnoDB 的影响

内存的数据页是在 Buffer Pool (BP) 中管理的,在 WAL 里 Buffer Pool 起到了加速更新的作用。而实际上,Buffer Pool 还有一个更重要的作用,就是加速查询。

而 Buffer Pool 对查询的加速效果,依赖于一个重要的指标,即:内存命中率。

可以在 show engine innodb status 结果中,查看一个系统当前的 BP 命中率。一般情况下,一个稳定服务的线上系统,要保证响应时间符合要求的话,内存命中率要在 99% 以上。

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

在大约十年前,单机的数据量是上百个 G,而物理内存是几个 G;现在虽然很多服务器都能有 128G 甚至更高的内存,但是单机的数据量却达到了 T 级别。

所以,innodb_buffer_pool_size 小于磁盘的数据量是很常见的。如果一个 Buffer Pool 满了,而又要从磁盘读入一个数据页,那肯定是要淘汰一个旧数据页的。

InnoDB淘汰的逻辑是怎样的呢?

InnoDB 内存管理用的是最近最少使用 (Least Recently Used, LRU) 算法,这个算法的核心就是淘汰最久未使用的数据。

下图是一个 LRU 算法的基本模型。

InnoDB 管理 Buffer Pool 的 LRU 算法,是用链表来实现的。

  1. 在图中的状态 1 里,链表头部是 P1,表示 P1 是最近刚刚被访问过的数据页;假设内存里只能放下这么多数据页;
  2. 这时候有一个读请求访问 P3,因此变成状态 2,P3 被移到最前面;
  3. 状态 3 表示,这次访问的数据页是不存在于链表中的,所以需要在 Buffer Pool 中新申请一个数据页 Px,加到链表头部。但是由于内存已经满了,不能申请新的内存。于是,会清空链表末尾 Pm 这个数据页的内存,存入 Px 的内容,然后放到链表头部。
  4. 从效果上看,就是最久没有被访问的数据页 Pm,被淘汰了。

这个算法乍一看上去没什么问题,但是如果考虑到要做一个全表扫描,会不会有问题呢?

假设按照这个算法,我们要扫描一个 20G 的表,而这个表是一个历史数据表,平时没有业务访问它。那么,按照这个算法扫描的话,就会把当前的 Buffer Pool 里的数据全部淘汰掉,存入扫描过程中访问到的数据页的内容。

也就是说 Buffer Pool 里面主要放的是这个历史数据表的数据。对于一个正在做业务服务的库,这可不妙。你会看到,Buffer Pool 的内存命中率急剧下降,磁盘压力增加,SQL 语句响应变慢。

所以,InnoDB 不能直接使用这个 LRU 算法。实际上,InnoDB 对 LRU 算法做了改进。

在 InnoDB 实现上,按照 5:3 的比例把整个 LRU 链表分成了 young 区域和 old 区域。图中 LRU_old 指向的就是 old 区域的第一个位置,是整个链表的 5/8 处。也就是说,靠近链表头部的 5/8 是 young 区域,靠近链表尾部的 3/8 是 old 区域。

改进后的 LRU 算法执行流程变成了下面这样。

  1. 图 7 中状态 1,要访问数据页 P3,由于 P3 在 young 区域,因此和优化前的 LRU 算法一样,将其移到链表头部,变成状态 2。
  2. 之后要访问一个新的不存在于当前链表的数据页,这时候依然是淘汰掉数据页 Pm,但是新插入的数据页 Px,是放在 LRU_old 处。
  3. 处于 old 区域的数据页,每次被访问的时候都要做下面这个判断:
    • 若这个数据页在 LRU 链表中存在的时间超过了 1 秒,就把它移动到链表头部;
    • 如果这个数据页在 LRU 链表中存在的时间短于 1 秒,位置保持不变。1 秒这个时间,是由参数 innodb_old_blocks_time 控制的。其默认值是 1000,单位毫秒。

可以看到,这个策略最大的收益,就是在扫描这个大表的过程中,虽然也用到了 Buffer Pool,但是对 young 区域完全没有影响,从而保证了 Buffer Pool 响应正常业务的查询命中率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99358.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【图像处理 -1图像恢复】非线性过滤器修复图像

【论文参考】文章地址: https://www.researchgate.net/publication/303996052_Image_Restoration_Technique_with_Non_Linear_Filter Image Restoration 一、摘要 在本文中,提出了一种新的处理方法图像使用不同的过滤方法 实现Image恢复。目的是增强数…

计算机网络原理第4章 网络层

目录~ 4.1 网络层提供的两种服务 面向连接:让网络负责可靠交付,通信之前先建立虚电路 无连接:网络提供数据报服务,网络层提供简单灵活的、无连接的、尽最大努力交付的数据报服务 4.2 网际协议 IP 网际协议 IP 是 TCP/IP 体系…

基于JAVA的校友录

开发工具(eclipse/idea/vscode等): 数据库(sqlite/mysql/sqlserver等): 功能模块(请用文字描述,至少200字): 网站前台:关于我们、联系我们、校园通知、组织信息、活动信息 管理员功能: 1、管理关于我们、联…

java方法耗时统计,JavaAgent javassist bytebuddy统计方法耗时,jvm监控prometheus

前言介绍 JavaAgent是在JDK5之后提供的新特性,又叫叫java代理。开发人员可通过这种机制(Instrumentation)在jvm加载class文件之前修改类的字节码,动态更改类方法实现AOP,提供监控服务如:方法调用时长、jvm内存等。修改字节码领域…

jsp+ssm计算机毕业设计大学生校园新闻发布系统【附源码】

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: JSPSSM mybatis Maven等等组成,B/S模式 Mave…

色温及其相关参数

光学膜层和大多数着色表面不是自发光的。为了看到它们,我们需要一个光源。显然,对颜色的任何评估都将包括光源的属性。在计算颜色时,我们通常使用标准光源,其中大部分是由CIE根据其相对光谱输出来定义的,并且尽可能地表…

java计算机毕业设计springboot+vue在线选课系统

项目介绍 本系统是针对目前在线选课系统管理的实际需求,从实际工作出发,对过去的在线选课系统系统存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结合计算机系统的结构、概…

ARM寻址方式(ARM指令获取操作数的方式)

所谓寻址方式,指的是CPU去获取一个操作数的方式,可以是从指令中获取立即数、可以是从寄存器中获取,也可以是从内存中获取。 目录 1、立即数寻址 2、寄存器寻址 3、寄存器移位寻址 4、寄存器间接寻址 5、基址加变址寻址 (1) 前向索引…

springboot-mybatis/JPA流式查询

项目中有几个batch需要检查所有的用户参与的活动的状态,以前是使用分页,一页一页的查出来到内存再处理,但是随着数据量的增加,效率越来越低。于是经过一顿搜索,了解到流式查询这么个东西,不了解不知道&…

计算机毕业设计springboot+vue基本微信小程序的演出门票管理系统-票务转票系统

项目介绍 转票是一个传统的行业。根据当前发展现状,网络信息时代的全面普及,转票也在发生着变化,单就出票这一方面,利用手机预约考试正在逐步进入人们的生活。传统的转票方式,不仅会耗费大量的人力、时间,有时候还会出错。小程序系统伴随智能手机为我们提供了新的方向。手机微信…

新兴物种:程序猿的饲养指南

程序猿,一种主要生存在中国印度等亚太国家的新型猿类,生存活动以及消费活动的范围遍布世界各地,其中最优渥的产地位于美国硅谷。 主要的生存环境需求有,两脚兽一切的日用饮食以及物资需求。 该物种所获得的荣誉勋章有&#xff0…

Spring系列之SpringBoot概述及入门

SpringBoot入门 文章目录SpringBoot入门一、SpringBoot是什么?二、Spring的缺点1.配置繁琐2.依赖繁琐三、SpringBoot功能四、SpringBoot起步依赖原理五、SpringBoot快速入门总结一、SpringBoot是什么? SpringBoot是由Pivotal团队提供的全新框架&#xf…

Splunk Enterprise 9.0.X Crack

Splunk Enterprise 9.0.X Crack Splunk 有能力了解用户小型企业中实际发生的情况,并快速采取有目的的行动来了解用户和开发人员的情况。它能够轻松灵活地将简单信息转化为答案,以及自动机器学习支持的分析过程 搜索、分析和可视化,从您的所…

基于springcloud的简单易用的java分布式日志组件

真正的大师,永远都怀着一颗学徒的心! 一、项目简介 基于springcloud的简单易用的java分布式日志组件 二、实现功能 支持基于traceId的日志记录 支持日志查询 支持日志缓冲队列 redis或者kafka 支持错误报警模块 支持内容组合查询功能 支持日志分应用统计条数…

【神奇bug】“金”、“⾦”不是同一个字

身为程序员,总能遇见那些神奇的bug。我前段时间遇到了 “中国黄金” 和 “中国黄⾦”,我咋看咋觉得是同一个词,但是程序就是判定不一致,十分郁闷,多方搜索,最后发现2个金居然不是一个字。真是个神奇的bug&a…

计算机基础学习笔记:操作系统篇之硬件结构,CPU Cache基础概念

三、CPU Cache的数据结构和读取过程 本文知识来源小林Coding阅读整理思考,原文链接请见该篇文章 Cache结构 CPU Cache 是由很多个 Cache Line 组成的,Cache Line 是 CPU 从内存读取数据的基本单位,而 Cache Line 是由各种**标志(…

基于java+springmvc+mybatis+vue+mysql的智能新冠疫苗接种助手

项目介绍 随着全球新冠疫情的蔓延,基本所有的发达国家都开始了全民疫苗接种的行为,在我国更是进行了全民的新冠疫苗接种,为了能够让民众更加方便快捷的进行疫苗的接种我们通过java编程语言,后端ssm框架,前端vue技术开…

【Python百日进阶-数据分析】Day129 - plotly柱状图(条形图):px.bar()实例

文章目录四、实例4.1 Plotly Express条形图4.1.1 加拿大人口4.1.2 一维数据的条形图4.1.3 多维数据条形图4.1.4 彩条4.1.5 堆叠与分组条形图4.1.6 聚集成单色条4.1.7 带文本的条形图4.1.8 填充图案4.1.9 分面子图4.1.10 带Plotly Express的基本水平条形图4.1.11 配置水平条形图…

nacos服务注册与发现

目录 1. 应用系统架构的演变(单应用>分布式) 2. Spring Cloud Alibaba介绍 3. 开发示例 3.1 版本的选择 3.2 nacos安装 3.3 创建工程 3.3.1 创建父工程 3.3.2 创建服务提供者模块 3.3.2 服务消费者 3.4 测试 今天与大家们简单的聊一下&#…

远程的Win11主机没有连接屏幕,通过向日葵远程后只有一个640x480的分辨率选项

背景 远程的 Win11 主机没有连接屏幕,通过向日葵远程后只有一个 640x480 的分辨率选项,界面特别小,用起来很不方便。而且远程主机本身还无法调整分辨率,向日葵上面的工具栏里也没有分辨率这一选项。 问题分析 主要原因是远程主机…