MYSQL-7.内存

内存

Mysql的内存结构

  1. 大体可分为四个板块:mysql工作组件、线程本地内存、mysql共享内存、存储引擎缓冲区;

在这里插入图片描述

Mysql server工作组件

  1. 对应着mysql架构图中的组件层:

    在这里插入图片描述

  2. Mysql在启动时,会将这些工作组件初始化到内存中;

  3. 数据库连接池:存储数据库内部的连接对象,这些连接对象中包含了客户端连接信息(客户端IP、登陆的用户、所连接的DB等),同时还会在内部绑定一个工作线程,所以也可以将其理解为线程池;mysql复用连接的本质是复用线程,当出现一个新的客户端连接时,会根据客户端信息为其创建连接对象,然后再服用线程池中的空闲线程;

工作线程的本地内存:

  1. 线程之间相互独立,Mysql在创建每条线程时,都会为其分配这些本地内存;
    在这里插入图片描述

    • thread_stack:线程堆栈,主要用于暂时存储运行的SQL语句及运算数据;
    • sort_buffer:排序缓冲区,执行排序SQL时,用于存放排序后数据的临时缓冲区;
    • join_buffer:连接缓冲区,做连表查询时,存放符合连表查询条件数据的临时缓冲区;
    • read_buffer:顺序读缓冲区,MySQL磁盘IO一次读一页数据,存放顺序IO的数据的临时缓冲区;
    • read_rnd_buffer:随机读缓冲区,当基于无序字段查询数据时,这里存放随机读到的数据;
    • net_buffer:网络连接缓冲区,这里主要是存放当前线程对应的客户端连接信息;
    • tmp_table:内存临时表,当SQL中用到了临时表时,这里存放临时表的结构及数据;
    • bulk_insert_bufferMyISAM批量插入缓冲区,批量insert时,存放临时数据的缓冲区;
    • bin_log_bufferbin-log日志缓冲区;
  2. 存放的信息大部分是一条信息在执行SQL时产生的临时数据,或者是线程独有数据;

Mysql共享内存区域:

  1. 结构图
    在这里插入图片描述

    • Key Buffer:MyISAM表的索引缓冲区,提升MyISAM表的索引读写速度;
    • Query Cache:查询缓存区,缓冲SQL的查询结果,提升热点SQL的数据检索效率;
    • Thread Cache:线程缓存区,存放工作线程运行期间,一些需要被共享的临时数据;
    • Table Cache:表数据文件的文件描述符缓存;当需要对某张表进行操作时,不需要将整个磁盘检索一遍,而可以查找缓存,如何根据其上面记录的地址,去读取操作表数据,提升数据表的打开效率;
    • Table Definition Cache:表结构文件的文件描述符缓存,提升结构表的打开效率;
  2. qureyCahce查询缓存:利用热点探测技术,对于一些频繁执行的查询SQL,直接将结果缓存在内存中,之后再使用相同sql(以sql的哈希值来作为Key)来查询相同数据时,就无需走磁盘,而是直接从查询缓存中获取数据并返回;

    1. 缺点,也是Mysql8.X版本移除查询缓存的原因:
      • 缓存命中率低;
      • 内存占用率高;
      • 增加了查询步骤;
      • 维护成本不下,需要LRU算法淘汰缓存,同时写操作时都需要清空缓存中对应的数据;

存储引擎缓冲区

  1. 虽然MySQL是基于磁盘存储数据的,但每一次操作都需要进行磁盘IO,这样会导致资源开销极大,同时性能也极低,因此几乎所有引擎都在内存中设计了一个缓冲池,用来提升数据库整体的读写性能;

InnoDB的Buffer Poll

结构

结构图

在这里插入图片描述

  1. Data Page:写入缓冲区,主要用来缓冲磁盘的表数据,将写操作转移到内存进行。
  2. Index Page:索引缓冲页,对于所有已创建的索引根节点,都会放入到内存,提升索引效率。
  3. Lock Space:锁空间,主要是存放所有创建出的锁对象。
  4. Dict Info:数据字典,主要用来存储MySQL-InnoDB引擎自带的系统表。
  5. redo_log_bufferredo-log缓冲区,存放写SQL执行时写入的redo记录。
  6. undo_log_bufferundo-log缓冲区,存放写SQL执行时写入的undo记录。
  7. Adaptivity Hash:自适应哈希索引,InnoDB会为热点索引页,创建相应的哈希索引。
  8. Insert Buffer:写入缓冲区,对于insert的数据,会先放在这里,然后定期刷写磁盘。
  9. Lru List:内存淘汰页列表,对于整个缓冲池的内存管理列表。
  10. Free List:空闲内存列表,这里面记录着目前未被使用的内存页。
  11. Flush List:脏页内存列表,这里主要记录未落盘的数据。
内存大小
  1. 可以通过show global variables like "%innodb_buffer_pool_size%";命令查询;Mysql5.6以后版本默认大小为128MB,这是一块连续空间,会在Msql启动时向操作系统生气,一般建议设置为机器内存的60%-80%
数据页Data Page
  1. 定义InnoDB引擎为了读取方便,会将磁盘中的数据划分为一个个的页,每个页默认大小为16kb,然后以页作为内存和磁盘的交互单位,而InnoDB也会以页作为存储单位;所以,当InnoDB拿到申请到的连续内存后,会将整块空间以16kb的尺寸划分成一个个缓冲页;这些空的还未使用的缓冲页称之为空闲页,而已经承载了磁盘数据的缓冲页称之为数据页
  2. 优势
    1. 读数据时:做了一层缓冲,如果所需查询数据在数据页中,就会直接从内存中读取数据并返回;
    2. 写数据时:如果所需修改的数据在数据页中,就会修改数据页数据并标记相应的数据页,然后直接返回,再由后台线程去完成数据的落盘操作;
  3. 存储过程:比如在执行一条查询语句,若内存中不存在数据,因此会走磁盘检索数据,检索数据的过程中,不管此次IO读到的数据是不是目标数据,都会将它们放在内存中;而且如果在内存充足的情况下,InnoDB会试图将所有的表数据全部载入内存;
索引缓冲页Index Page):
  1. mysql在启动时,就会将当前库中所有已经存在的索引的根节点放入到内存缓冲区中,这样对一需要走索引查询的sql就可以通过缓存直接定位到相应的索引根节点,避免了全盘查找索引节点的操作;
  2. Index Page就是专门用来存放载入的索引数据的,存放这个索引数据的数据页称之为索引页;一些访问频率较高的非根节点的索引页也可能会载入Index Page
锁空间Lock Space):
  1. 存储:主要用来存储锁结构的一块内存区域,还会存储一些并发事物链表,如:死锁检测时需要的「事物等待链表、锁的信息链表等」;
  2. 锁空间内存不足时,会导致行锁粗化成表锁,从而来减少锁结构的数量,MySQL 中锁空间大小受 innodb_buffer_pool_size 参数影响;
数据字典dict info):
  1. 用来存储sys_tables、sys_columns、sys_indexes、sys_fields四张系统表数据;
    1. 如我们执行show tables;(查询库中所有表)或者show index feom tableName(查询表中索引)等语句时,其实都是在查询系统表数据;当MySql启动时会将这些表数据放入dict info这块区域中,当我们查询时,就在这块区域中检索数据;也可通过SELECT * FROM information_schema.TABLES命令查看这些表;
    2. sys_tables:存储所有引擎为InnoDB的表信息;
      • ID:一张表的ID号。
      • NAME:一张表的名称。
      • N_COLS:一张表的字段数量。
      • TYPE:一张表所使用的存储引擎、编码格式、压缩算法、排序规则等。
      • SPACE:一张表所位于的表空间。
    3. sys_columns:存储所有用户定义的表字段信息;
      • TABLE_ID:表示一个字段属于那张表;
      • POS:一个字段在一张表中属于第几列;
      • NAME:一个字段的名称;
      • MTYPE:一个字段的数据类型;
      • PRTYPE:一个字段的精度值;
      • LEN:一个字段的存储长度限制;
    4. sys_indexes:存储所有引擎为InnoDB的索引信息;
      • TABLE_ID:表示这个索引属于哪张表;
      • ID:一个索引的ID号;
      • NAME:一个索引的名称;
      • N_FIELDS:一个索引由几个字段组成;
      • TYPE:一个索引的类型,如唯一、联合、全文、主键索引等;
      • SPACE:一个索引的数据所位于的表空间位置;
      • PAGE_NO:这个索引对应的B+Tree根节点位置;
    5. sys_fields:存储所有所有的定义信息;
      • INDEX_ID:当前这个索引字段属于哪个索引;
      • POS:当前这个索引字段,位于索引的第几列;
      • COL_NAME:当前索引字段的名称;
日志缓冲区log buffer
  1. InnoDB中主要存在两个日志缓存区undo_log_buffer、redo_log_buffer,主要的作用就是用来提升日志写入速度;
自适应哈希索引Adaptive Hash Index

可以参考索引中的介绍 【地址】;

写入缓存区change buffer):
  1. 由之前的数据缓存页可以得知,当我们在进行写操作时,如果变更的数据页在缓冲区中存在,则会直接更改缓冲区中的数据并标记,但如果需要变更的数据页不在缓冲区中则任需要去走磁盘操作数据,显然会影响性能;
    而且当我们在进行insert操作时,数据库中不存在这条数据,缓冲区中自然也不存在对应的数据页,按照目前情况插入操作都需要进行磁盘IO;为了解决此问题则出现了写入缓冲;

  2. 写入语句执行流程

    1. 判断要变更的数据是否在数据缓存页中;
    2. 存在则直接更改缓冲区中的数据,完成标记后直接返回;
    3. 不存在,则将需要变更的数据放入到写入缓冲中,然后返回;
  3. 限制:插入的数据字段不能具备唯一约束或唯一索引(只关联自增主键ID除外),原因:一般情况下数据不可能全部载入内存中,所以判断重复值的工作需要依赖磁盘中的表数据来完成;

    1. 自增主键ID会由Mysql-service维护,不会出现重复值,也就不依赖磁盘中的表数据来判断重复值;
  4. 写入缓存区不仅用来存储数据还会用来存储索引;原因是,当我们在执行插入操作时,还需要维护索引;

    由之前索引维护中的介绍可以知道,在执行插入语句时,会先向聚簇索引中插入一条相应的行记录,之后会向非聚簇索引中都插入一个新的索引键,并将值指向聚簇索引中插入的主键值;

    这个过程若不存在缓存,则表中存在多少个非聚簇索引就需要经过多少次写磁盘来维护它们,非常影响性能,所以,InnoDB对于不具备唯一性的索引,都会将要插入的索引键放在写入缓冲区;

  5. 刷入磁盘的时机:采用的是后台线程刷盘操作

    1. 当某条sql需要用到对应的索引键查询数据时;
    2. 当写入缓存区内存不足时;
    3. 距离上次刷盘时间一定的时间间隔后(默认10s);
    4. Mysql-service关闭时;

内存管理

  1. 缓冲页innoDB在启动时,在逻辑上将连续的内存划分为一块块的缓冲页

  2. 缓冲页的控制快

    1. 作用:用于管理缓冲页而设计的一种结构;可以优化在Mysql运行过程中,可用的空闲页变得零散,从而出现的磁盘加载数据时,寻找空闲页的问题;

      在这里插入图片描述

    2. 存储内容:数据页所属的表空间、页好、缓冲页地址、链表节点指针等信息,所有控制块都会放在缓冲池的最前面;

      在这里插入图片描述

    3. 使用InnoDB会为每一个缓冲页都分配一个对应的控制块,后续可以基于控制块去管理每一块缓冲页;

  3. 空闲页管理

    1. InnoDB会以控制块为节点,将所有的空闲缓冲页组成一个空闲链表(Free链表)

      在这里插入图片描述

      头节点的三个值:

      • head:空闲链表的第一个一个控制块;
      • tail:空闲链表的最后一个控制块;
      • count:空闲链表的节点数量;
    2. 当我们需要一块新的缓冲页存储磁盘数据时,不需要去进行遍历操作了,只需要找到空闲链表,然后根据控制块中记录的缓冲页地址,就可以拿到一块空闲缓冲页使用;

  4. 标记页管理

    1. 概念:当某个数据页被修改后,会对这个数据页做一个标记,被标记的数据页称之为标记页也叫脏页;
    2. 与空闲页管理类似,InnoDB也会通过控制块构建一个标记页链表(Flush链表);
    3. 刷盘:当后台线程开始进行刷盘操作时,只需要找到标记页链表,然后将链表节点中的对应缓冲页中的变更数据刷写到磁盘就可以了;
      • 标记页和写入缓冲区的刷盘时间相同,使用当写入缓冲区中也存在需要刷盘的数据时,也会将相应的缓冲页加入Flush链表;
  5. 预读失效问题

    1. 概念:在索引原理那表述过磁盘IO的执行过程,其中利用了局部性原理预读数据的机制,意味着当我们去读取数据时,默认会将其附近的16kb数据(多行数据)一次性载入内存并用一个缓冲页存放,若此时程序只取了这页数据中的一行数据,其他数据并需要读取,这种数据被提前加载进来却并没有被访问的情况称之为预读失效问题

    2. 文件系统的数据读取

      在这里插入图片描述

      当Mysql收到读取请求时,service层会交由引擎层去处理,而引擎层又依赖文件系统提供的I/O读取机制;文件系统中为了保证数据的有序读取,会将请求先放到请求队列中,等数据准备就绪后,会将数据数据放入到响应队列中,最后由相关(Mysql)进程的线程读取数据;

    3. InnoDB的预读机制

      1. 概念InooDB在存储数据时,会以64个数据页作为一个extent;当select操作发生时,一个extent里被读取的数据页达到一定阀值后,会触发InnoDB的预读机制,将剩余的数据页或下一个extenr提前载入到内存中,由后台线程完成;
      2. 两种预读策略
        1. 线性预读:当前extent中的数据页被读取到一定数量时,会触发预读提前读取下一个extent
        2. 随机预读:当前extent中的数据页被大部分载入到内存时,会触发预读将extenr剩下的数据页全部载入内存,默认关闭可通过innodb_random_read_ahead;命令开启;
      3. 阀值:可以通过show variables like 'innodb_read_ahead_threshold';命令查看;默认56,即当一个extent中的数据页被读取56个以上是,线性预读会将下个extent的所有数据页载入内存,而随机预读这是将剩下的8个数据载入内存;
内存淘汰
  1. 概念:内存空间是有限的且成本较高,无法支撑所有数据源源不断的载入内存,所以需要一套淘汰策略来淘汰某些数据页,从而达到频繁访问的数据页可以长期留在内存中,一些很少访问的数据页能够淘汰掉;与空闲页和标记页类似,对于可淘汰的数据页(已使用且未被变更过的缓冲页)也会构成一个LRU淘汰链表,有些数据会在LRUFlush两个链表间来回跳动,数据发生变更LRU -> Flush,变更数据落盘后Flush -> LRU

  2. 末尾淘汰机制:当一个线程来读写数据时,如果命中了缓冲区中的某个数据页,则将该数据页挪到LRU链表的最前面;当需要从磁盘载入数据且内存不足时,则淘汰链表末尾的数据页,并将载入的数据插入到LRU链表的头部;

    1. 存在的问题
      • 利用局部性原理预读失效时,会导致数据页常驻缓冲;
      • 一次查询(扫描)数据量过大时,会导致缓冲区中的热点数据全部被替换,导致缓冲池被污染;
  3. InnoDB的内存淘汰策略:对末尾淘汰策略做了优化;

    1. LRU链表划分为old、young两个区域;占比:young、oldLRU链表中的占比默认为63:37,可以通过innodb_old_blocks_pc这个参数,来手动调整old区在整个LRU链表中的占比;在这里插入图片描述

      从磁盘预读的数据页,只需要加入到old的头部,当这个数据页被访问时,才会将其插入young区,如果预读的页一直没有被访问,就会从old区域移除,这样就不会影响young区域中的热点数据,这样避免了预读失效问题,但还存在缓冲池污染问题;

    2. old区数据并不是访问一次就将其移入young区的,而是经过young区晋升限制,防止old区数据过早的晋升young区,这样就可以避免缓冲池污染问题

      • young区晋升限制:加了一个停留时间,则数据页想要从old区晋升至young区需要在old区存活一定时间,默认为1s,可以通过innodb_old_blocks_time调整;相当于数据页想要晋升需要被访问两次,且两次访问的时间间隔必须大于innodb_old_blocks_time

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

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

相关文章

【Vscode】无法将“python,pip,node,npm等”识别为cmdlet...问题

问题出现场景 新换个电脑,然后重新安装了软件,又复现一次又一次“老生常谈”的问题。 解决方法 网络答案吧五花八门,我采取一个我的场景解决可行的方案, 首先我的场景是,环境变量,配置路径都是没有问题…

抖音视频关键词批量下载工具|视频爬虫采集软件

抖音视频批量提取工具,搜索即下载,轻松获取所需视频! 正文: 想要轻松获取抖音上的精彩视频吗?现在,有了我们的抖音视频批量提取工具,一切变得简单易行!Q:290615413无论是针对特定关…

基于Pytorch+昇腾NPU部署baichuan2-7B大模型

一、模型介绍 Baichuan 2 是百川智能推出的新一代开源大语言模型,采用 2.6 万亿 Tokens 的高质量语料训练。Baichuan 2 在多个权威的中文、英文和多语言的通用、领域 benchmark 上取得同尺寸最佳的效果。 它基于 Transformer 结构,在大约1.2万亿 tokens…

c++20协程详解(一)

前言 本文是c协程第一篇,主要是让大家对协程的定义,以及协程的执行流有一个初步的认识,后面还会出两篇对协程的高阶封装。 在开始正式开始协程之前,请务必记住,c协程 不是挂起当前协程,转而执行其他协程&a…

pygame--坦克大战(二)

加载敌方坦克 敌方坦克的方向是随机的,使用随机数生成。 初始化敌方坦克。 class EnemyTank(Tank):def __init__(self,left,top,speed):self.images {U: pygame.image.load(img/enemy1U.gif),D: pygame.image.load(img/enemy1D.gif),L: pygame.image.load(img/e…

clickhouse sql使用2

1、多条件选择 multiIf(cond_1, then_1, cond_2, then_2, …, else) select multiIf(true,0,1) 当第一条件不成立看第二条件判断 第一个参数条件参数,第二参数条件成立时走 2、clickhouse 在计算时候长出现NaN和Infinity异常处理 isNaN()和isInfinite()处理

免费图片转excel方案大全

随着信息技术的发展,我们经常会遇到需要将图片中的数据转换成Excel表格的情况。这种需求在数据分析、报表制作、信息整理等领域尤为常见。然而,许多人在面对这一任务时感到困惑,不知道如何进行。本文将为大家介绍几种免费的图片转Excel方案&a…

【Qt 学习笔记】如何在Qt中打印日志 | qDebug的使用 | Assistant的使用

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ 如何在Qt中打印日志 | qDebug的使用 文章编号:Qt 学习笔记…

路径规划——搜索算法详解(七):D*lite算法详解与Matlab代码

!!!注意!!! 看本篇之前,一定要先看笔者上一篇的LPA*讲解,笔者统一了符号看起来过渡会更加好理解! 到目前为止,我们学习了广度优先搜索Dijkstra算法、能够计…

基于深度学习的日常场景下的人脸检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要:本文详细介绍基于YOLOv8/v7/v6/v5的日常场景下的人脸检测,核心采用YOLOv8并整合了YOLOv7、YOLOv6、YOLOv5算法,进行性能指标对比;详述了国内外研究现状、数据集处理、算法原理、模型构建与训练代码,及基于Streaml…

AWS-EKS 给其他IAM赋予集群管理权限

AWS EKS 设计了权限管理系统,A用户创建的集群 B用户是看不到并且不能管理和使用kubectl的,所以我们需要共同管理集群时就需要操场共享集群访问给其他IAM用户。 两种方式添加集群控制权限(前提:使用有管理权限的用户操作&#xff…

【c++】类和对象(七)

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章来到类和对象的最后一部分 目录 1.static成员1.1特性 2.友元2.1引入&#xff1a;<<和>>的重载2.2友元函数2.3友元类 3.内部类4.匿名对象5.拷…

聚观早报 | 蔚来推出油车置换补贴;iPhone 16 Pro细节曝光

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 4月02日消息 蔚来推出油车置换补贴 iPhone 16 Pro细节曝光 小米SU7创始版第二轮追加开售 OpenAI将在日本设立办事…

Ollama教程——入门:开启本地大型语言模型开发之旅

Ollama教程——入门&#xff1a;开启本地大型语言模型开发之旅 引言安装ollamamacOSWindows预览版LinuxDocker ollama的库和工具ollama-pythonollama-js 快速开始运行模型访问模型库 自定义模型从GGUF导入模型自定义提示 CLI参考创建模型拉取模型删除模型复制模型多行输入多模态…

ADB 命令之 模拟按键/输入

ADB 命令之 模拟按键/输入 模拟按键/输入 在 ​​adb shell​​​ 里有个很实用的命令叫 ​​input​​&#xff0c;通过它可以做一些有趣的事情。 ​​input​​ 命令的完整 help 信息如下&#xff1a; Usage: input [<source>] <command> [<arg>...] Th…

SV学习笔记(一)

SV&#xff1a;SystemVerilog 开启SV之路 数据类型 內建数据类型 四状态与双状态 &#xff1a; 四状态指0、1、X、Z&#xff0c;包括logic、integer、 reg、 wire。双状态指0、1&#xff0c;包括bit、byte、 shortint、int、longint。 有符号与无符号 &#xff1a; 有符号&am…

云计算对象存储服务

对象存储服务&#xff08;OSS&#xff09;中的存储桶(Bucket)叫做‘OBS桶 存储桶&#xff08;Bucket&#xff09;&#xff1a;存储桶式对象存储服务中用于存储对象的基本容器&#xff0c;类似于文件系统中的文件夹。每个存储桶具有唯一的名称&#xff0c;并且可以在桶中存储任…

理解Three.js的相机

大家都知道我们生活中的相机&#xff0c;可以留下美好瞬间。那Three.js的相机是什么呢&#xff1f;Three.js创建的场景是三维的&#xff0c;而我们使用的显示器显然是二维的&#xff0c;相机就是抽象的定义了三维空间到二维显示器的投影方式。Three.js常见的相机有两类&#xf…

【Java+Springboot】----- 通过Idea快速创建SpringBoot项目操作方法

一、第一步&#xff1a; 点击选择【File】->【New】-> 【Project】 最后弹出[new Project]界面。 二、第二步&#xff1a; 1. 选择【Spring Initializr】 2. 然后选择【Project SDK】的版本 3. 然后 Choose Initializr Service URL 选择默认&#xff08;Default&#x…

华为审核被拒提示: 您的应用存在(最近任务列表隐藏风险活动)的行为,不符合华为应用市场审核标准

应用审核意见&#xff1a; 您的应用存在&#xff08;最近任务列表隐藏风险活动&#xff09;的行为&#xff0c;不符合华为应用市场审核标准。 修改建议&#xff1a;请参考测试结果进行修改。 请参考《审核指南》第2.19相关审核要求&#xff1a;https://developer.huawei.com/c…