MySQL进阶学习一(2024.10.07版)

2024-10-06

--------------------------------------------------------------------------------------------------------------------------------

1.一条SQL语句是如何执行的

单进程的多线程模型

MySQL的物理目录

show global variables like "%basedir%";

InnoDB是如何存储表数据的

  • InnoDB其实是使用页为基本单位来管理存储空间的,默认的页大小为16KB。
  • 对于InnoDB存储引擎来说,每个索引都对应着一棵B+树,该B+树的每个节点都是一个数据页,数据页之间不必要是物理连续的,因为数据页之间有双向链表来维护着这些页的顺序
  • InnoDB的聚簇索引的叶子节点存储了完整的用户记录,也就是所谓的索引即数据,数据即索引

系统表空间(system tablespace)
系统表空间可以对应文件系统上一个或多个实际的文件,默认,InnoDB会在数据目录下创建一个名为ibdata
独立表空间(file-per-table tablespace)
在MySQL5.6.6以及之后的版本中,InnoDB默认为每一个表建立一个独立表空间,根据参数innodb_file_per_table控制

客户端与服务端的交互

数据库的核心在于存储引擎

MySQl逻辑架构

向MySQl发送一个请求---连接器

客户端如果长时间没有动静,连接器会将其断开,由wait_timeout控制,默认是8

长期使用长连接会导致内存飙升

向MySQl发送一个请求---查询缓存

将缓存放入一个引用表之中,通过哈希值进行引用

查询缓存时按需使用的,参数querycache type设置成DEMAND(默认不使用查询缓存)
虽然查询缓存有时可以提千系统性能,但也不得不因维护这块缓存而造成一些开销,比如每次都要去查询缓存中检索,查询请求处理完需要更新查询缓存,维护该查询缓存对应的内存区域。从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL8.0中删除。

向MySQl发送一个请求---分析器

向MySQl发送一个请求---优化器

基于成本的查询优化器(Cost-Based Optimizer),IO和CPU

向MySQl发送一个请求---执行引擎

三个阶段的权限判断

各种不同的存储引擎向上边的MySQL服务器层提供统一的调用接口(也就是存储引擎API)包含了几十个底层函数,像"读取索引第一条内容"、"读取索引下一条内容"、"插入记录"等等。

存储引擎

从 MySQL5.5之后,默认的存储引擎是 InnoDB。InnoDB 是一个通用的存储引擎,除非有特殊需求,推荐使用InnoDB.
SHOW ENGINES;

InnoDB体系架构

简要架构

InnoDB整体也分为三层:(多线程模型)

  • 内存结构(In-Memory(1)Structure),这一层在MySQL服务进程内;
  • OS Cache,这一层属于内核态内存;
  • 磁盘结构(On-Disk)这一层在文件系统上;

多线程模型

  • Master Thread:刷新脏页到磁盘,保证数据一致性(10秒操作与1秒操作)
  • I0 Thread:大量使用异步处理写I0请求,包括4类I0 Thread
  • Purge Thread:回收已经使用并分配的undo页
  • Page Cleaner Thread:1.2.X版本以上引入脏页刷新,减轻master的工作,提高性能

管理单位

当我们想从表中获取某些记录时,1noDB存储引擎需要一条一条的把记录从磁盘上读出来么?

InnoDB采取的方式是:

  • 将数据划分为若干个页,以可作为磁盘和内存之间交互的基本单位
  • InnoDB中页的大小一般为16KB,也就是在一般情况下,一次最少从磁盘中读取16 KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中

InnoDB内存架构

InnoDB在内存中主要包括下面几个部分:缓冲池、Change缓冲区、自适应哈希索引、Log缓冲区

缓冲池

Page:为了高效读取,缓冲池划分为页结构组织
LRU:当需求添加新的page时,最近最少使用的page被清除,同时新页面被添加到链表的中间部分
这种中间点插入的策略,把链表分为两个子链表
头部:最近被访问过的“年轻”页
尾部:最近被访问的old page
这样使新子列表中保存更重要的page,旧子列表包含较少使用的这部分page

change buffer
  • Change Buffer是一种特殊的数据结构,当某些页面不在缓冲池中,缓存会改变二级索引page,这可能会造成insert,update,delete(DML)操作会与其他从缓冲池中的读操作加载的page合并。
  • 为了避免频繁的I0随机读写,当更新和删除操作时,并不会立即写入磁盘,而是会选择系统空闲时定期进行写入磁盘的操作。

落盘机制(redo、change buffer):

  • 定时 master thread 1s or 10s
  • 业务使用(提交或查询)
  • 缓存区达到阀值(1/2)
日志缓冲区

日志缓冲区是保存要写入磁盘上日志文件的数据的内存区域,即redo log buffer。
Write Ahead Log策略:当事务提交时,先写重做日志,然后再择时将脏页写入磁盘【随机写变为顺序写】
日志缓存区大小:由innodb log_buffer_size 变量定义,默认16M, 可以节省磁盘I/0
日志刷新频率:innodb flushlog_at_trx_commit控制如何写入日志缓冲区的内容并刷新到磁盘

行-页-段的过程

分析成本的考量

I/O成本:从磁盘到内存这个加载的过程损耗的时间称之为1/0成本
CPU成本:读取以及检测记录是否满足对应的搜索条件、对结果集进行排序等这些操作损耗的时间称之为CPU成本
页是磁盘和内存之间交互的基本单位,读取一个页面花费的成本默认是1.0,读取以及检测一条记录是否符合搜索条件的成本默认是0.2

步骤:

  1. 根据搜索条件,找出所有可能使用的索引
  2. 计算全表扫描的代价
  3. 计算使用不同索引执行查询的代价
  4. 对比各种执行方案的代价,找出成本最低的那一个

查询:

explain过程进行解释

2.MySQL事务隔离

  • 保证一组数据库操作,要么全部成功,要么全部失败的
  • 事务支持是在引擎层实现
  • MySQL是一个支持多引的系统,但并不是所有的弓擎都支持事务
  • 支持事务是InnoDB引擎的重要特性之一

隔离性

ACID的I:隔离性
(1)脏读(dirtyread):读取创了未提交的脏数据
(2)不可重复读(non-repeatable read):两次读取之间的数据被改变或消失
(3)幻读(phantom read):A事务在更新事务读取的同时B事务更新数据,就会惊奇的发现了这些新数据,貌似之前A读到的数据

隔离级别

(1)读未提交:一个事务还没提交时,它做的变更就能被别的其他他事务看到。
(2)读已提交:一个事务提交之后,它做的变更才会被其
(3)可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。在可重复读隔离级别下,未提交变更对其他事务是不可见的。
(4)串行化:对于同一行记录,读或写都会加锁。当出现锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

读未提交: 2 2 2
读已提交:1 2 2
可重复读:1 1 2(事务A执行期间的数据是一样的)
串行化:1 1 2(事务B执行之后会更新锁住)

实现过程

  • 读未提交:直接返回记录上的最新值,没有视图概念。
  • 读已提交:在每个SOL语句开始执行的时候创建视图。
  • 可重复读:在事务启动时创建视图,整个事务存在期间都用这个视图。
  • 串行化:直接用加锁的方式来避免并行访问。

默认隔离级别参数

3.深入浅出索引

索引是什么东东?

索引是存储引擎用于快速查找记录的一种数据结构

七大查找算法

  • 顺序查找
  • 二分查找
  • 插值查找
  • 斐波那契查找
  • 树表查找
  • 分块查找
  • 哈希查找

索引数据结构

哈希表

适用于等值查询

有序数组

插入和修改成本高

B+树

为什么MySQL用B+树做索引而不用B-树或红黑树

原因:面试的时候背过

表中 R1~R5 的(ID,k)值分别为(100,1)、(200,2)、(300,3)、(500,5)和(600,6)

基于主键索引和普通索引的查询有什么区别?

主键索引:则只需要接叟索 ID 这棵 B+ 树
普通索引:要先搜索k索引树,得到ID内值为 500,再普通索引查询方式,则需要到 ID 索引树搜索一次。这个过程称为回表.

MyISAM索引实现

  • 叶节点的data域存放的是数据记录的地址
  • 主索引和辅助索引在结构上没有任何区别,只是主索引要求key是唯一的

InnoDB索引实现

InnoDB是进行行锁的,所以MyISAM不如使用InnoDB

--------------------------------------------------------------------------------------------------------------------------------

2024.10.07

4.普通索引和唯一索引的选择

InnoDB体系结构

select id fromT where k=5

  • 条件的第一个记录(5,500)后,需要查找对于普通索引来说,查找到满下一个记录,直到碰到第一个满足 k=5 条件的记录。
  • 对于唯一索引来说,由于索引定义了唯一性,查找到第一个满足条件的记录后,就会停止继续检索。

更新过程

  • 当需要更新一个数据页时,如果类据页在内存中就直接更新,
  • 而如果这个数据页不在内存中的讨舌,在不影响数据一致性的前提下,InnoDB 会将这些更新操作缓存在 change buffer 中,这样就不需要从磁盘中读入这个数据页了。在下次查询需要访问这个类据页的时候,将数据页读入内存,然后执行change buffer 中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。

change buffer的使用场景

  • 对于唯一索引来说,所有的更新桑作都要先判断这个操作是否违反唯一性约束。比如,要插入(4,400)这个记录就要先判断现在表中是否已经存在 k=4 的记录,而这必须要将数据页读入内字才能判断。如果都已经读入到内存了,那直接更新内存会更快,就没必要使用change buffer 了。
  • 因此,唯一索引的更新就不能使,月change buffer,实际上也只有普通索引可以使用。

InnoDB插入数据的流程

第一种情况是,这个记录要更新的目标页在内存中。这时,InnoDB 的处理流程如下:

  • 对于唯一索引,找到3和5之间的位置, 判断到没有冲突,插入这个值,语句执行结束;
  • 对于普通索引,找到3和5之间的位置,插入这个值,语句执行结束.

第二种情况是,这个记录要更新的目标页不在内存中。这时,InnoDB 的处理流程如下:

  • 对于唯一索引,需要将数据页读入内存,判断到没有冲突,插入这个值!
  • 对于普通索引,则是将更新记录在 change buffer.

注意:在change buffer中有此行记录的情况下,再次更改,是增加一条还是原地修改?
增加一条

change buffer的使用场景

普通索引的所有场景,使用 change buffer 都可以起到加速作用吗 ?

  • 因为 merge 的时候是真正进行数据更新的时刻,而 change buffer 的主要目的就是将记录的变更动作缓存下来,所以在一个数据页做 merge 之前,changebuffer 记录的变更越多(也就是这个页面上要更新的次数越多),收益就越大。因此,对于写多读少的业务来说,页面在写完以后马上被访问到的概率比较小,此时 change buffer 的使用效果最好。这种业务模型常见的就是账单类、日志类的系统。
  • 反之,假设一个业务的更新模式是写入之后马上会做查询,那么即使满足了条件将更新先记录在 change buffer,但之后由于马上要访问这个数据页,会立即触发merge 过程。这样随机访问 10 的次数不会减少,反而增加了 change buffer 的维护代价。所以,对于这种业务模式来说,change buffer 反而起到了副作用。

change buffer与redo log在插入过程之中的使用

insert into t(id,k) values(id1,k),(id2,k2):

change buffer与redo log在读取过程之中的使用

select * from t where k in(k1, k2);

  • 读 Page1的时候,直接从内存返回。虽然磁盘上还是之前的数据,但是这里直接从内存返回结果,结果是正确的。
  • 然后应用 change要读 Page 2 的时候,需要把 Page 2 从磁盘读入内存中,buffer 里面的操作日志,生成一个正确的版本并返回结果。

redo log 主要节省的是随机写磁盘的 IO消耗(转成顺序写),而 change buffer主要节省的则是随机读磁盘的 IO 消耗。

5.MySQL词法分析

词法分析概念

词法分析(英语:lexicalanalysis)是计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器也叫扫描器(Scanner)。词法分析器(Lexicalanalyzer.简称Lexer)般以函数的形式存在,供语法分析器调用。

词法解析过程

首先是sql_chars.cc之中的进行状态机

select * from demo1;解析

初始化会获取输入流

接下来进入状态机之中

返回全部的字符串

接下来返回s,求取物理机的内容

进入循环扫描过程

语法解析匹配存在
上述内容对应sql_yacc.cc之中的语法解析部分 SELECT_SYM=748

匹配*

这里的*是匹配的ascll之中的*也就是42

from demo1过程是同上的.
from 对应452  寻找表的过程IDENT_QUDENT 484,还要在语法解析过程继续进行转换.

最终的一个字符串是\0,对应MY_LEX_EOL的状态机,然后在对应MY_LEX_END状态机,如下所示:

show table;解析

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

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

相关文章

LSTM时序预测 | Python实现LSTM长短期记忆神经网络时间序列预测

本文内容:Python实现LSTM长短期记忆神经网络时间序列预测,使用的数据集为AirPassengers 目录 数据集简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 数据集简介 AirPassengers 数据集的来源可以追溯到经典的统计和时间序列分析文献。原始数据集由 Box,…

面向对象特性中 继承详解

目录 概念: 定义: 定义格式 继承关系和访问限定符 基类和派生类对象赋值转换: 继承中的作用域: 派生类的默认成员函数 继承与友元: 继承与静态成员: 复杂的菱形继承及菱形虚拟继承: 虚…

VGG16模型实现MNIST图像分类

MNIST图像数据集 MNIST(Modified National Institute of Standards and Technology)是一个经典的机器学习数据集,常用于训练和测试图像处理和机器学习算法,特别是在数字识别领域。该数据集包含了大约 7 万张手写数字图片&#xf…

喜讯 | 攸信技术入选第六批专精特新“小巨人”企业

日前,根据工信部评审结果,厦门市工业和信息化局公示了第六批专精特新“小巨人”企业和第三批专精特新“小巨人”复核通过企业名单,其中,厦门攸信信息技术有限公司进入第六批专精特新“小巨人”企业培育。 “专精特新”企业是指具有…

图像分割恢复方法

传统的图像分割方法主要依赖于图像的灰度值、纹理、颜色等特征,通过不同的算法将图像分割成多个区域。这些方法通常可以分为以下几类: 1.基于阈值的方法 2.基于边缘的方法 3.基于区域的方法 4.基于聚类的方法 下面详细介绍这些方法及其示例代码。 1. 基…

代码随想录--栈与队列--用栈实现队列

队列是先进先出,栈是先进后出。 如图所示: 题目 使用栈实现队列的下列操作: push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。 示例: MyQueue qu…

draw.io 设置默认字体及添加常用字体

需求描述 draw.io 是一个比较好的开源免费画图软件。但是其添加容器或者文本框时默认的字体是 Helvetica,一般的期刊、会议论文或者学位论文要求的英文字体是 Times New Roman,中文字体是 宋体,所以一般需要在文本字体选项里的下拉列表选择 …

分层解耦-05.IOCDI-DI详解

一.依赖注入的注解 在我们的项目中,EmpService的实现类有两个,分别是EmpServiceA和EmpServiceB。这两个实现类都加上Service注解。我们运行程序,就会报错。 这是因为我们依赖注入的注解Autowired默认是按照类型来寻找bean对象的进行依赖注入…

2-115 基于matlab的瞬态提取变换(TET)时频分析

基于matlab的瞬态提取变换(TET)时频分析,瞬态提取变换是一种比较新的TFA方法。该方法的分辨率较高,能够较好地提取出故障的瞬态特征,用于故障诊断领域。通过对原始振动信号设置不同信噪比噪声,对该方法的抗…

关于一个模仿qq通信程序

7月份的时候还在学校那个时候想要学习嵌入式Linux,但是还没有买开发板来玩,再学linux系统编程,网络编程,Linux系统的文件IO,于是学完之后想做一个模仿qq的通信程序于是就有了这个“ailun.exe”,因为暑假去打…

【数据结构与算法】线性表

文章目录 一.什么是线性表?二.线性表如何存储?三.线性表的类型 我们知道从应用中抽象出共性的逻辑结构和基本操作就是抽象数据类型,然后实现其存储结构和基本操作。下面我们依然按这个思路来认识线性表 一.什么是线性表? 定义 线性…

TryHackMe 第7天 | Web Fundamentals (二)

继续介绍一些 Web hacking 相关的漏洞。 IDOR IDOR (Insecure direct object reference),不安全的对象直接引用,这是一种访问控制漏洞。 当 Web 服务器接收到用户提供的输入来检索对象时 (包括文件、数据、文档),如果对用户输入数据过于信…

【springboot】使用代码生成器快速开发

接上一项目&#xff0c;使用mybatis-plus-generator实现简易代码文件生成 在fast-demo-web模块中的pom.xml中添加mybatis-plus-generator、freemarker和Lombok依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator&…

Python | 由高程计算坡度和坡向

写在前面 之前参加一个比赛&#xff0c;提供了中国的高程数据&#xff0c;可以基于该数据进一步计算坡度和坡向进行相关分析。 对于坡度和坡向&#xff0c;这里分享一个找到的库&#xff0c;可以方便快捷的计算。这个库为&#xff1a;RichDEM&#xff0c;官网地址如下 https…

SAP学习笔记 - 豆知识11 - 如何查询某个字段/DataElement/Domain在哪个表里使用?

大家知道SAP的表有10几万个&#xff08;也有说30多万个的&#xff0c;总之很多就是了&#xff09;&#xff0c;而且不断增多&#xff0c;那么当想知道一个字段在哪个表里使用的时候该怎么办呢&#xff1f; 思路就是SAP的表其实也是存在表里的&#xff1a;&#xff09;&#xf…

【Git】TortoiseGitPlink提示输入密码解决方法

问题 克隆仓库&#xff0c;TortoiseGitPlink提示输入密码 解法 1、打开TortoiseGit 下的puttygen工具 位置&#xff1a;C:\Program Files\TortoiseGit\bin\ 2、点击【Load】按钮&#xff0c;载入 C:\Users\Administrator\.ssh\ 文件夹下的id_rsa文件。 3、点击save private …

qt_c++_xml存这种复杂类型

demo&#xff0c;迅雷链接。或者我主页上传的资源 链接&#xff1a;https://pan.xunlei.com/s/VO8bIvYFfhmcrwF-7wmcPW1SA1?pwdnrp4# 复制这段内容后打开手机迅雷App&#xff0c;查看更方便 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>#include…

请散户股民看过来,密切关注两件大事

明天股市要开市&#xff0c;不仅散户股民期盼节后股市大涨&#xff0c;上面也同样想在节后来上一个“开门红”。 为此&#xff0c;上面没休假&#xff0c;关起门来办了两件大事&#xff0c;这两天发布消息已提前预热了。 两件大事如下&#xff1a; 一是&#xff0c;上交所10…

什么是 JavaScript 的数组空槽

JavaScript 中的数组空槽一直是一个非常有趣且颇具争议的话题。我们可能对它的实际意义、历史以及现今的新版本中对它的处理方式有所疑问。数组空槽的存在最早可以追溯到 JavaScript 的诞生之初&#xff0c;当时的设计决定让它成为了现代 JavaScript 开发中的一种特别的现象。 …

大数据新视界 --大数据大厂之数据血缘追踪与治理:确保数据可追溯性

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…