面试经典-MySQL篇

news2024/11/24 22:43:54

一、MySQL组成

  • MySQL数据库的连接池:由一个线程来监听一个连接上请求以及读取请求数据,解析出来一条我们发送过去的SQL语句
  • SQL接口:负责处理接收到的SQL语句
  • 查询解析器:让MySQL能看懂SQL语句
  • 查询优化器:选择最优的查询路径
  • 执行器:根据执行计划调用存储引擎的接口
  • 存储引擎接口:真正执行SQL语句

二、InnoDB的数据更新过程

首先InnoDB存储引擎有一个重要内存结构为缓冲池,假设我们执行如下sql:

update users set name='xxx' where id=10

那么底层将有如下几个步骤:

  • 看看“id=10”这一行数据是否在缓冲池里,如果不在的话,直接从磁盘里加载到缓冲池里来
  • 对这行记录加独占锁
  • 假设“id=10”这行数据的name原来是“zhangsan”,现在我们要更新为“xxx”,先把要更新的原来的值“zhangsan”和“id=10”这些信息,写入到undo日志文件中去
  • 更新buffer pool中的缓存数据,现在已经把内存里的数据进行了修改,但是磁盘上的数据还没修改
  • 这个时候,就必须要把对内存所做的修改写入到一个redo日志
  • 提交事务的时候将redo日志写入磁盘中

三、MySQL自己的日志文件(binlog)

  • binlog叫做归档日志,他里面记录的是“对users表中的id=10的一行数据做了更新操作,更新以后的值是什么”
  • 提交事务的时候,同时会写入binlog到磁盘文件中去

四、MySQL核心结构

  • Buffer Pool

Buffer Pool本质其实就是数据库的一个内存组件,默认情况下是128MB,还是有一点偏小了,我们实际生产环境下完全可以对Buffer Pool进行调整。数据库启动时会在Buffer Pool中划分出来一个一个的缓存页,一个缓存页的大小和磁盘上的一个数据页的大小是一一对应起来的,都是16KB,每个数据页中有很多行数据。

  • free链表

他是一个双向链表数据结构,只要你一个缓存页是空闲的, 那么他的描述数据块就会被放入这个free链表中,当你需要把磁盘上的数据页读取到Buffer Pool中的缓存页里去的时候,我们需要从free链表里获取一个描述数据块,然后就可以获取对应的空闲缓存页,接着我们就可以把磁盘上的数据页读取到对应的缓存页里去,最后把那个描述数据块从free链表里去除就可以了。

  • 数据页缓存哈希表

我们在执行增删改查的时候,肯定是先看看这个数据页有没有被缓存,用表空间号+数据页号,作为一个key,然后缓存页的地址作为value。

  • flush链表

凡是被修改过的缓存页,都会把他的描述数据块加入到flush链表中去,flush的意思就是这些都是脏页,后续都是要flush刷新到磁盘上去的。

五、事务

四大事务问题:

  • 脏写:事务B更新好的值被事务A回滚为事务A原先的值。
  • 脏读:事务B去查询了事务A修改过的数据,但是此时事务A还没提交
  • 不可重复读:事务A执行过程中事务B执行并提交,导致事务A两次读到的值不一样
  • 幻读:事务A一开始查出了10条数据,事务B新增了2条数据,并且提交了,此时事务A再查发现查出了12条数据

四大隔离级别:

  • read uncommitted(读未提交):不允许发生脏写的,可能发生脏读,不可重复读,幻读。
  • read committed(读已提交):不会发生脏写和脏读,可能会发生不可重复读和幻读问题
  • repeatable read(可重复读):不会发生脏写和脏读和不可重复读,可能会幻读问题
  • serializable(串行化):不会发生脏写和脏读和不可重复读和幻读

MySQL默认设置的事务隔离级别是可重复读,而且MySQL的可重复读级别是可以避免幻读发生的,原理就是下面的MVCC机制。

六、MVCC机制

Mysql事务通过MVCC机制得以实现,我们每条数据其实都有两个隐藏字段,一个是trx_id,一个是roll_pointer,这个trx_id就是最近一次更新这条数据的事务id,roll_pointer就是指向你了你更新这个事务之前生成的undo log链。
在这里插入图片描述
执行一个事务的时候,就给你生成一个ReadView(视图),ReadView包含以下信息:

  • m_ids:此时有哪些事务在MySQL里执行还没提交的
  • min_trx_id:m_ids里最小的值
  • max_trx_id:mysql下一个要生成的事务id,就是最大事务id
  • creator_trx_id:你这个事务的id

下面演示一下MVCC机制的执行步骤:

  • 一个是事务A(id=45),一个是事务B(id=59),事务B是要去更新这行数据的,事务A是要去读取这行数据的值
  • 现在事务A直接开启一个ReadView,这个ReadView里的m_ids就包含了事务A和事务B的两个id,45和59,然后min_trx_id就是45,max_trx_id就是60,creator_trx_id就是45,是事务A自己。
  • 这个时候事务A第一次查询这行数据,会走一个判断,就是判断一下当前这行数据的txr_id是否小于ReadView中的min_trx_id,此时发现txr_id=32,是小于ReadView里的min_trx_id就是45的
  • 说明你事务开启之前,修改这行数据的事务早就提交了,所以此时可以查到这行数据
  • 接着事务B开始动手了,他把这行数据的值修改为了值B,然后这行数据的txr_id设置为自己的id,也就是59,同时roll_pointer指向了修改之前生成的一个undo log,接着这个事务B就提交了
  • 这个时候事务A再次查询,此时查询的时候,会发现一个问题,那就是此时数据行里的txr_id=59,那么这个txr_id是大于ReadView里的min_txr_id(45),同时小于ReadView里的max_trx_id(60)的
  • 说明更新这条数据的事务,很可能就跟自己差不多同时开启的,于是会看一下这个txr_id=59,是否在ReadView的m_ids列表里?
  • 果然,在ReadView的m_ids列表里,有45和59两个事务id,直接证实了,这个修改数据的事务是跟自己同一时段并发执行然后提交的,所以对这行数据是不能查询的
  • 顺着这条数据的roll_pointer顺着undo log日志链条往下找,就会找到最近的一条undo log,trx_id是32,此时发现trx_id=32,是小于ReadView里的min_trx_id(45)的
  • 说明这个undo log版本必然是在事务A开启之前就执行且提交的,那么读这条数据就可以了
  • 总结来说:一个事务可以读到事务ID等于自身和比自己事务ID小的事务更新的值,但是也不是所有的事务ID比自己小的事务更新的值都能读到,还不能不在m_ids中

七、锁机制

  • 当有一个事务加了独占锁之后,此时其他事务再要更新这行数据只能生成独占锁在后面等待。
  • 当有人在更新数据的时候,其他的事务可以读取这行数据吗?默认情况下需要加锁吗?不用!因为有人在更新数据的时候,然后你要去读取这行数据,直接默认就是开启mvcc机制的。
  • 那么假设万一要是你在执行查询操作的时候,就是想要加锁呢?那也是ok的,MySQL首先支持一种共享锁,就是S锁,这个共享锁的语法如下:select * from table lock in share mode,如果此时有别的事务在更新这行数据,已经加了独占锁了,此时你的共享锁能加吗?当然不行了,共享锁和独占锁是互斥的!此时你这个查询就只能等着了。
  • 那么如果你先加了共享锁,然后别人来更新要加独占锁行吗?当然不行了,共享锁和独占锁是互斥的!此时你这个查询就只能等着了。
  • 那么如果你在加共享锁的时候,别人也加共享锁呢?此时是可以的,你们俩都是可以加共享锁的,共享锁和共享锁是不会互斥的。

八、索引

MySQL的索引是用B+树来组成的,索引分为两种:

  • 聚簇索引

如果一颗大的B+树索引数据结构里,叶子节点就是数据页自己本身,那么此时我们就可以称这颗B+树索引为聚簇索引!这个聚簇索引默认是按照主键来组织的,所以你在增删改数据的时候,一方面会更新数据页,另一方面其实会给你自动维护B+树结构的聚簇索引。

  • 二级索引

比如你基于name字段建立了一个索引,那么此时你插入数据的时候,就会重新搞一颗B+树,B+树的叶子节点也是数据页,但是这个数据页里仅仅放主键字段和name字段。针对select * from table where name='xx’这样的语句,你先根据name字段值在name字段的索引B+树里找,找到叶子节点也仅仅可以找到对应的主键值,而找不到这行数据完整的所有字段。

索引使用原则:

  • 等值匹配规则

就是你where语句中的几个字段名称和联合索引的字段完全一样,而且都是基于等号的等值匹配,那百分百会用上我们的索引

  • 最左侧列匹配

这个意思就是假设我们联合索引是KEY(class_name, student_name, subject_name),那么不一定必须要在where语句里根据三个字段来查,其实只要根据最左侧的部分字段来查,也是可以的。

  • 最左前缀匹配原则

即如果你要用like语法来查,比如select * from student_score where class_name like ‘1%’,查找所有1打头的班级的分数,那么也是可以用到索引的。

  • 范围查找规则

你的where语句里如果有范围查询,那只有对联合索引里最左侧的列进行范围查询才能用到索引!

  • 等值匹配+范围匹配的规则

联合索引是KEY(class_name, student_name, subject_name),如果你要是用select * from student_score where class_name=‘1班’ and student_name>‘’ and subject_name<‘’,首先可以用class_name在索引里精准定位到一波数据,接着这波数据里的student_name都是按照顺序排列的,所以student_name>'‘也会基于索引来查找,但是接下来的subject_name<’'是不能用索引的。为什么呢?因为student_name在不相同的情况下,subject_name是无序的,所以不能走索引,只能全表扫描。

执行计划的几个级别:

  • const

直接就可以通过聚簇索引或者二级索引+聚簇索引回源,轻松查到你要的数据。这里有一个要点,你的二级索引必须是unique key唯一索引,才是属于const方式的

  • ref

select * from table where name=x的语句,name是个普通二级索引,不是唯一索引,如果你用name IS NULL这种语法的话,即使name是主键或者唯一索引,还是只能走ref方式

  • range

select * from table where age>=x and age <=x,假设age就是一个普通索引,此时就必然利用索引来进行范围筛选

  • index

只要遍历二级索引就可以拿到你想要的数据,而不需要回源到聚簇索引的访问方式

  • all

全表扫描

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

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

相关文章

MATLAB环境下基于决策树和随机森林的心力衰竭患者生存情况预测

近年来&#xff0c;随着医学数据的不断积累和计算机技术的快速发展&#xff0c;许多机器学习技术已经被用在医学领域&#xff0c;并取得了不错的效果。与传统的基于医学知识经验的心衰预后评估模型相比&#xff0c;机器学习方法可以快速、高效地从繁杂的、海量的心衰病人数据中…

SQLite数据库使用指南以及相关API编程

SQLite介绍 SQLite是一种基于C语言开发的轻量级、快速、自包含、高可靠性和全功能的SQL数据库引擎。它是全球范围内使用最为广泛的数据库引擎&#xff0c;被嵌入到所有移动设备和大部分计算机中&#xff0c;并且伴随着无数日常使用的应用程序一起提供。SQLite的文件格式具有稳…

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem 从这一章开始讲负反馈Control系统和小信号建模. 13.2 The Feedback Theorem 首先介绍 Middlebrook’s Feedback Theorem 考虑下面负反馈系统 传输函数 Guo/ui G ( s ) u o u i G ∞ T 1 T G…

C/C++火柴棍等式

有n根(n<24)火柴棍&#xff0c;你可以拼出多少个形如“ABC"的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零&#xff0c;则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示: 依次需要用到的火柴棍数目为6 2 5 5 4 5 6 3 7 6 。 如果是初学者可能会这么写。 …

Java多线程学习(一)

多线程学习&#xff08;二&#xff09;&#xff1a;http://t.csdnimg.cn/Q8Koc 目录 1、什么是多线程 2、如何创建多线程&#xff08;多个方法&#xff09; 方法一&#xff1a;继承Thread类创建线程 方法二&#xff1a;实现Runnable接口创建线程 方法三、实现Callable接口…

JDBC编程(Mysql)

目录 1.什么是jdbc 2.使用 2.1下载mysql数据库驱动 2.2导入项目 2.3编写代码 2.3.1数据源 2.3.2和数据库服务器建立连接 2.3.3构建一个操作数据库的sql语句 2.3.4执行sql 2.3.5释放前面创建的各种资源 2.3.6运行java程序 2.4其他操作 2.4.1修改操作 2.4.2删除操作…

微信小程序开发学习笔记——3.11完成form评论案例的实现逻辑

>>跟着b站up主“咸虾米_”学习微信小程序开发中&#xff0c;把学习记录存到这方便后续查找。 课程连接&#xff1a;https://www.bilibili.com/video/BV19G4y1K74d?p25&vd_source9b149469177ab5fdc47515e14cf3cf74 一、javascript参考手册——splice https://www.…

Instagram代运营和自营优缺点比较 CloudNEO:您全球社交媒体代运营的综合解决方案

在社交媒体营销中&#xff0c;Instagram作为一种非常受欢迎的平台&#xff0c;已成为企业推广品牌和吸引客户的重要工具。然而&#xff0c;对于企业来说&#xff0c;是选择代运营还是自营Instagram账号呢&#xff1f;让我们来比较一下它们各自的优缺点&#xff0c;并推荐CloudN…

plt保存PDF矢量文件中嵌入可编辑字体(可illustrator编辑)

背景&#xff1a; 用默认 plt.savefig() 保存图片&#xff0c;图中文字是以瞄点保存&#xff0c;而不是以文字格式。在编辑矢量图中&#xff0c;无法调整文字大小和字体。 方法&#xff1a; import matplotlib.pyplot as plt import numpy as np# ------输出的图片为illustr…

C#,动态规划问题中基于单词搜索树(Trie Tree)的单词断句分词( Word Breaker)算法与源代码

1 分词 分词是自然语言处理的基础,分词准确度直接决定了后面的词性标注、句法分析、词向量以及文本分析的质量。英文语句使用空格将单词进行分隔,除了某些特定词,如how many,New York等外,大部分情况下不需要考虑分词问题。但有些情况下,没有空格,则需要好的分词算法。…

2024年嵌入式校招

春招指的是一年中的春季招聘季节&#xff0c;即每年的3月份至5月份&#xff0c;是许多公司和组织开始招聘新毕业生或经验较少的求职者的时间。春招通常是大学生或研究生即将毕业&#xff0c;进入社会工作的重要时期。在这个时期&#xff0c;许多公司会举行一系列的宣讲会、招聘…

【原创】java+swing+mysql二手车交易管理系统

前言&#xff1a; 本文主要介绍了二手车交易管理设计与实现。首先&#xff0c;通过市场需求&#xff0c;我们确定了二手车的功能&#xff0c;通常的二手车交易系统都是B/S架构&#xff0c;然而我们今天要用javaswing去开发一个C/S架构的二手车交易管理系统&#xff0c;主要功能…

llinux C语言在网络编程时使用标准IO

目录 fdopen(3)函数 使用标准IO发送数据 使用标准IO接收数据 注意 先看一个简单的TCP客户端程序&#xff1a; #include <stdio.h> #include <arpa/inet.h> #include <sys/socket.h> #include <stdlib.h> #include <string.h> #include <…

【数据结构和算法初阶(C语言)】队列实操(概念实现+oj题目栈和队列的双向实现以及循环链表难点题目详解!)

目录 1. 队列的概念及结构 2.队列结构存在的意义应用 3.队列实现的结构选择 4.队列实现 5.队列对数据的处理 5.1队列初始化 5.2队尾入数据 5.3队头出数据 5.4获取队列尾部元素 5.5获取队列头部元素 5.6获取队列中元素个数 5.7检测队列是否为空 5.8销毁队列 6.循环队列补充 7.使…

C语言之快速排序

目录 一 简介 二 代码实现 快速排序基本原理&#xff1a; C语言实现快速排序的核心函数&#xff1a; 三 时空复杂度 A.时间复杂度 B.空间复杂度 C.总结&#xff1a; 一 简介 快速排序是一种高效的、基于分治策略的比较排序算法&#xff0c;由英国计算机科学家C.A.R. H…

矩阵中移动的最大次数

文章目录 所属专栏:BFS算法 题目链接 思路如下&#xff1a; 1.首先我们需要从第一列开始遍历&#xff0c;寻找每一个都能够满足条件的位置&#xff0c;将它插入到数组里面 2.第一列遍历完了后我们先判断第一列的数是否都满足条件插入到数组里面&#xff0c;如果数组为空&#…

03.事件进阶

一、事件流 事件流是对事件执行过程的描述&#xff0c;了解事件的执行过程有助于加深对事件的理解&#xff0c;提升开发实践中对事件运用的灵活度。 如上图所示&#xff0c;任意事件被触发时总会经历两个阶段&#xff1a;【捕获阶段】和【冒泡阶段】。 简言之&#xff0c;捕获…

肝了三天,完成了AIGC工具网站大全,建议收藏再看

说是肝了三天&#xff0c;其实远远不止&#xff0c;前前后后&#xff0c;从资料搜集到最后整理成文&#xff0c;有近一个月了&#xff0c;大家看在整理不易的份上&#xff0c;给点个赞吧&#xff0c;不要光顾着收藏呀&#xff01; 国内网站 AIGC 导航 https://www.aigc.cn 网…

wayland(xdg_wm_base) + egl + opengles 渲染使用纹理贴图的旋转 3D 立方体实例(十三)

文章目录 前言一、使用 stb_image 库加载纹理图片1. 获取 stb_image.h 头文件2. 使用 stb_image.h 中的相关接口加载纹理图片3. 纹理图片——cordeBouee4.jpg二、渲染使用纹理贴图的旋转 3D 立方体1. egl_wayland_texture_cube.c2. Matrix.h 和 Matrix.c3. xdg-shell-client-pr…

使用 pnpm 搭建 monorepo 项目

引言 在我之前的开发经历中&#xff0c;并没有实际使用过 Monorepo 管理项目&#xff0c;尽管之前对此有所了解&#xff0c;但并未深入探究。然而&#xff0c;如今许多开源项目都采纳了 Monorepo 方式&#xff0c;对于不熟悉它的开发者来说&#xff0c;阅读和理解这些项目的源…