MySQL千万数据方案调研,一不小心直接打挂我系统

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 大家好,我是Leo。之前聊的RocketMQ暂时放放,目前正在调研一个千万数据的处理方案。在准备测试数据的时候,执行了个 select 把我电脑内存打光了。然后OOM,黑屏,宕机。。

本章概括

image.png


对Server影响


当执行下列代码时,因为InnoDB的数据是保存在主键索引上的,所以全表扫描是直接查主键索引的数据。他会从第一行一直查到最后一行放入结果集,然后返回给客户端。

select * from waybill

这个结果集是啥,为什么会导致我OOM?

先看一下Server层的查询流程

image.png

  1. 获取一行数据,把数据写入 net_buffer
  2. 直至到最后一行,如果 net_buffer 满了,就会调用网络接口把数据发送给 Client
  3. 发送成功之后,清空 net_buffer 继续接收
  4. 如果发送失败,返回 EAGAINWSAEWOULDBLOCK,就表示本地网络栈socket buffer写满了,进入等待。直到网络栈重新可写,再继续发送

socket buffer  属于操作系统层,他是操作系统提供的socket缓冲区。缓冲区默认大小为8K(1024×8=8192字节),也可以设置成64K。

使用socket发送数据时先把数据发送到socket缓冲区中,之后接收函数从缓冲区中读取数据,如果发送端特别快的时候,缓冲区很快就被填满,我们可以根据情况设置缓冲区的大小,通过setsockopt函数实现

从流程可以得知 MySQL是边读边发的

占用最大的就是 net_buffer ,而且 net_buffer 的上限会控制在8K,为什么还会出现 OOM

一开始执行的时候这类知识我是知道的,但是我忽略了一个问题,日常使用时,我们会把数据库放在云服务器或者RDS中,今天为了测试千万数据我就直接在本地测了。

这就直接导致,服务器一直把数据返给客户端。都在本地,一不留神,悲剧了


强调一点! 对Server层来说,查询的结果是分段发给客户端的,所以Server不会把内存打爆。问题自然出在客户端了。


对InnoDB影响


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

这个加速查询还依赖一个重要的指标 内存命中率

可以通过 show engine innodb status 命令查看,或者通过百度搜索 MySQL内存命令率查询

如果所有的查询都能在内存页中找到答案,那命中率肯定是 100% 。但是在生产环境上业务是比较复杂的,这个很难做到。

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

InnoDB Buffer Pool innodb的缓冲池

innodb_buffer_pool_size innodb缓冲池大小的配置项

在查询时,如果 Buffer Pool 满了,而又要从磁盘读入一个数据页时,它会淘汰一个数据页进行存放新的数据页。淘汰的依据就是 LRU 算法

LRU 最近最少使用算法,淘汰最久未使用的数据。

可以参考如下图,是一个LRU基本模型,它是使用链表实现的。

image.png

  1. 第一张图是读取数据2时,会把2放入链表的头部,然后其他数据依次向后移动
  2. 第二张图同感
  3. 第三张图是读取了链表上没有的数据,就会把当前最久未使用的数据移出,把头部的最新数据写入。

是不是觉得设计的很奇妙? 我也觉得这个思想好奇妙,但是对于当前场景不实用!

大数据量写入之后,他会不断把链表的数据不断替换,也就是不断淘汰,最终导致内存命中率急剧下降,磁盘压力增加,SQL语句响应变慢。

在LRU的基础上InnoDB做了一些优化!

image.png

  1. 第一张图就是大概按照5:3的比例,把链表分成了young 区和 old 区。访问2时,会把2提到最前面,其他数据依靠靠后一格
  2. 第二张图是写入一个新数据88时,他会把old区域的最后一个数8移出,然后把新数据88写入old区的第一个位置

处于 old 区域的数据页,每次被访问的时候都要做下面这个判断:

  • 若这个数据页在 LRU 链表中存在的时间超过了 1 秒,就把它移动到链表头部;
  • 如果这个数据页在 LRU 链表中存在的时间短于 1 秒,位置保持不变。1 秒这个时间,是由参数 innodb_old_blocks_time 控制的。其默认值是 1000,单位毫秒。

这个策略,就是为了处理类似全表扫描的操作量身定制的。我们可以看一下全表查询的逻辑

  1. 扫描过程中,需要新插入的数据页,都被放到 old 区域 ;
  2. 一个数据页里面有多条记录,这个数据页会被多次访问到,但由于是顺序扫描,这个数据页第一次被访问和最后一次被访问的时间间隔不会超过 1 秒,因此还是会被保留在 old 区域;
  3. 再继续扫描后续的数据,之前的这个数据页之后也不会再被访问到,于是始终没有机会移到链表头部(也就是 young 区域),很快就会被淘汰出去。

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


对我的影响


知道了原理之后,再进行实现下一步方案的时候就类似于搭积木一样。

万丈高楼平地起,地基不搭好,上面再豪华,轻轻一晃就倒了


结尾


有些不懂的地方或者不对的地方,麻烦各位指出,一定修改优化!


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
26天前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
178 43
|
23天前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
83 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
19天前
|
存储 SQL 关系型数据库
MySQL底层概述—4.InnoDB数据文件
本文介绍了InnoDB表空间文件结构及其组成部分,包括表空间、段、区、页和行。表空间是最高逻辑层,包含多个段;段由若干个区组成,每个区包含64个连续的页,页用于存储多条行记录。文章还详细解析了Page结构,分为通用部分(文件头与文件尾)、数据记录部分和页目录部分。此外,文中探讨了行记录格式,包括四种行格式(Redundant、Compact、Dynamic和Compressed),重点介绍了Compact行记录格式及其溢出机制。最后,文章解释了不同行格式的特点及应用场景,帮助理解InnoDB存储引擎的工作原理。
MySQL底层概述—4.InnoDB数据文件
|
9天前
|
监控 关系型数据库 MySQL
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
40 9
|
3天前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
16 2
|
11天前
|
存储 关系型数据库 MySQL
MySQL进阶突击系列(09)数据磁盘存储模型 | 一行数据怎么存?
文中详细介绍了MySQL数据库中一行数据在磁盘上的存储机制,包括表空间、段、区、页和行的具体结构,以及如何设计和优化行数据存储以提高性能。
|
2天前
|
人工智能 关系型数据库 分布式数据库
100%兼容MySQL!手把手教你基于PolarDB搭建RAG系统
100%兼容MySQL!手把手教你基于PolarDB搭建RAG系统
|
10天前
|
存储 SQL 关系型数据库
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
|
2月前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决
|
24天前
|
关系型数据库 MySQL 数据库
Docker Compose V2 安装常用数据库MySQL+Mongo
以上内容涵盖了使用 Docker Compose 安装和管理 MySQL 和 MongoDB 的详细步骤,希望对您有所帮助。
131 42