文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MySQL连环炮,你抗的住嘛?

2023-08-17 16:20

关注

最近后台好多小伙伴发私信咨询阿Q,问马上就是金九银十的面试黄金期了,该如何在三个月内突击一下,以便更好地通过面试呢?

有想赚点外块|技术交流的朋友,欢迎来撩

阿Q的想法就是需要对自己掌握的知识进行归纳整理,系统的、分类的去复习相关的知识点。这样也能更好的把自己陌生的内容框出来,在暴漏自己短板的同时,更针对性的做准备。

为了节省大家的时间,阿Q决定帮大家先将 MySQL 面试相关的知识进行汇总整理,一改往日知识点东一棒槌西一榔头的问题。那么,你准备好迎接 MySQL 连环炮了嘛?

1、三大范式

1NF(第一范式):属性(对应于表中的字段)不能再被分割,也就是这个字段只能是一个值,不能再分为多个其他的字段了。1NF 是所有关系型数据库的最基本要求 ,也就是说关系型数据库中创建的表一定满足第一范式。

2NF(第二范式):2NF 要求数据库表中的每个实例或行必须可以被惟一地区分,2NF 在 1NF 的基础上增加了一个列,这个列称为主键,非主属性都依赖于主键。

3NF(第三范式):3NF 在 2NF 的基础之上,要求每列都和主键列直接相关,而不是间接相关,即不存在其他表的非主键信息。

在开发过程中,并不一定要满足三大范式,有时候为了提高查询效率,可以在表中冗余其他表的字段。

2、DML 语句和 DDL 语句区别

3、主键和外键的区别

4、drop、delete、truncate 区别

(1)用法不同

(2)属于不同的数据库语言

(3)执行速度不同

一般来说:drop > truncate > delete

5、基础架构

下图是 MySQL 的一个简要架构图,从下图你可以很清晰的看到客户端的一条 SQL 语句在 MySQL 内部是如何执行的。

img

6、MyISAM 和 InnoDB 有什么区别?

MySQL 5.5 之前,MyISAM 引擎是 MySQL 的默认存储引擎,MySQL 5.5 版本之后,InnoDB 是 MySQL 的默认存储引擎。

(1)是否支持行级锁

MyISAM 只有表级锁,而 InnoDB 支持行级锁和表级锁,默认为行级锁。

具体的锁详情请参考阿Q的此篇文章:面试必备常见存储引擎与锁的分类,请查收

(2)是否支持事务

MyISAM 不提供事务支持,InnoDB 提供事务支持,实现了 SQL 标准定义的四个隔离级别,具有提交和回滚事务的能力。

InnoDB 默认使用的 REPEATABLE-READ(可重读)隔离级别是可以解决幻读问题发生的(基于 MVCC 和 Next-Key Lock)。

关于 MySQL 事务以及解决幻读的详细介绍,可以看看阿Q写的这篇文章:InnoDB 解决幻读的方案–LBCC&MVCC

(3)是否支持外键

MyISAM 不支持,而 InnoDB 支持。

(4)是否支持数据库异常崩溃后的安全恢复

MyISAM 不支持,而 InnoDB 支持。使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log

(5)是否支持 MVCC

MyISAM 不支持,而 InnoDB 支持。

(6)索引实现

虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。

(7)性能差别

InnoDB 的性能比 MyISAM 更强大,不管是在读写混合模式下还是只读模式下,随着 CPU 核数的增加,InnoDB 的读写能力呈线性增长。MyISAM 因为读写不能并发,它的处理能力跟核数没关系。

InnoDB 和 MyISAM 性能对比

7、推荐自增id作为主键问题

8、为什么 MySQL 的自增主键不连续

9、redo log 是做什么的?

redo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。

比如 MySQL 实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性。

更新表数据的时候,如果发现 Buffer Pool 里存在要更新的数据,就直接在 Buffer Pool 里更新。然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(redo log buffer)里,接着刷盘到 redo log 文件里。

10、redo log 的刷盘时机

在这里插入图片描述

InnoDB 存储引擎为 redo log 的刷盘策略提供了 innodb_flush_log_at_trx_commit 参数,它支持三种策略

innodb_flush_log_at_trx_commit 参数默认为 1 ,也就是说当事务提交时会调用 fsync(同步操作) 对 redo log 进行刷盘。

另外 InnoDB 存储引擎有一个后台线程,每隔1秒,就会把 redo log buffer 中的内容写到文件系统缓存(page cache),然后调用 fsync 刷盘。

redo log buffer占用的空间即将达到 innodb_log_buffer_size 一半的时候,后台线程会主动刷盘。

11、redo log 是怎么记录日志的

硬盘上存储的 redo log 日志文件不只一个,而是以一个日志文件组的形式出现的,每个的redo日志文件大小都是一样的。

比如可以配置为一组4个文件,每个文件的大小是 1GB,整个 redo log 日志文件组可以记录4G的内容。

它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。

在这里插入图片描述

所以,如果数据写满了但是还没有来得及将数据真正的刷入磁盘当中,那么就会发生**「内存抖动」**现象,从肉眼的角度来观察会发现 mysql 会宕机一会儿,此时就是正在刷盘了。

12、什么是 binlog

binlog 是归档日志,属于 Server 层的日志,是一个二进制格式的文件,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”。

不管用什么存储引擎,只要发生了表数据更新,都会产生 binlog 日志。它的主要作用就是数据备份、主从复制。

binlog会记录所有涉及更新数据的逻辑操作,属于逻辑日志,并且是顺序写。

13、binlog 记录格式

binlog 日志有三种格式,可以通过binlog_format参数指定。

14、binlog 写入机制

事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。

因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache

我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap)。

binlog 也提供了 sync_binlog 参数来控制写入 page cache 和磁盘的时机:

15、redolog 和 binlog 的区别是什么

16、两阶段提交

假设执行 sql 过程中写完 redo log 日志后,binlog 日志写期间发生了异常,会出现什么情况呢?

由于 binlog 没写完就异常,这时候 binlog 里面没有对应的修改记录。因此,之后用 binlog 日志恢复数据时,就会少这一次更新,最终数据不一致

为了解决两份日志之间的逻辑一致问题,InnoDB 存储引擎使用两阶段提交方案。

将 redo log 的写入拆成了两个步骤 prepare 和 commit,这就是两阶段提交。使用两阶段提交后,写入 binlog 时发生异常也不会有影响,因为 MySQL 根据 redo log日志恢复数据时,发现 redo log 还处于 prepare 阶段,并且没有对应 binlog 日志,就会回滚该事务。

再看一个场景,redo log 设置 commit 阶段发生异常,那会不会回滚事务呢?

并不会回滚事务,虽然 redo log 是处于 prepare 阶段,但是能通过事务id找到对应的 binlog 日志,所以 MySQL 认为是完整的,就会提交事务恢复数据。

17、什么是 undo log

我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作(INSERT、DELETE、UPDATE)进行回滚,在 MySQL 中,恢复机制是通过回滚日志(undo log) 实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。

每次对记录进行改动都会记录一条 undo log,每条 undo log 也都有一个DB_ROLL_PTR属性,可以将这些 undo log 都连起来,串成一个链表,形成版本链。

版本链的头节点就是当前记录最新的值。

在这里插入图片描述

18、什么是 relaylog

relaylog 是中继日志,在主从同步的时候使用到,它是一个中介临时的日志文件,用于存储从 master 节点同步过来的 binlog 日志内容。

在这里插入图片描述

master 主节点的 binlog 传到 slave 从节点后,被写入 relay log 里,从节点的 slave sql 线程从 relaylog 里读取日志然后应用到 slave 从节点本地。

从服务器 I/O 线程将主服务器的二进制日志读取过来记录到从服务器本地文件,然后 SQL 线程会读取 relay-log 日志的内容并应用到从服务器,从而使从服务器和主服务器的数据保持一致

19、索引

索引其实是一种数据结构,能够帮助我们快速的检索数据库中的数据。

索引的作用就相当于书的目录。打个比方: 我们在查字典的时候,如果没有目录,那我们就只能一页一页的去找我们需要查的那个字,速度很慢。如果有目录了,我们只需要先去目录里查找字的位置,然后直接翻到那一页就行了。

20、Hash 索引

哈希表是键值对的集合,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。

但是!哈希算法有个 Hash 冲突问题,也就是说多个不同的 key 最后得到的 index 相同。通常情况下,我们常用的解决办法是 链地址法

链地址法就是将哈希冲突数据存放在链表中。就比如 JDK1.8 之前 HashMap 就是通过链地址法来解决哈希冲突的。不过,JDK1.8 以后 HashMap 为了减少链表过长的时候搜索时间过长引入了红黑树。

为了减少 Hash 冲突的发生,一个好的哈希函数应该“均匀地”将数据分布在整个可能的哈希值集合中。

既然哈希表这么快,为什么 MySQL 没有使用其作为索引的数据结构呢? 主要是因为 Hash 索引不支持顺序和范围查询。假如我们要对表中的数据进行排序或者进行范围查询,那 Hash 索引可就不行了,并且每次 IO 只能取一个。

21、B树和B+ 树

22、主键索引

数据表的主键列使用的就是主键索引,一种特殊的唯一索引。

在 MySQL 的 InnoDB 的表中,当没有显示的指定表的主键时,InnoDB 会自动先检查表中是否有唯一索引且不允许存在 null 值的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。

23、二级索引

二级索引又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置。

唯一索引,普通索引,前缀索引等索引属于二级索引。

MySQL 中的全文索引,有两个变量,最小搜索长度和最大搜索长度,对于长度小于最小搜索长度和大于最大搜索长度的词语,都不会被索引。

24、聚簇索引与非聚簇索引

聚簇索引即索引结构和数据一起存放的索引,并不是一种单独的索引类型。InnoDB 的主键索引的叶子节点中存放的就是数据行,所以它属于聚簇索引。

在 MySQL 中,InnoDB 引擎的表的 .ibd 文件就包含了该表的索引和数据,对于 InnoDB 引擎表来说,该表的索引(B+树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据。

非聚簇索引即索引结构和数据分开存放的索引,并不是一种单独的索引类型。二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。

辅助索引是我们人为创建的索引,它的叶子节点中存放的是主键,当我们通过辅助索引查找到主键之后,再通过查找的主键去回表查找主键索引。

25、回表

回表就是先通过数据库索引扫描出该索引树中数据所在的行,取到主键 id,再通过主键 id 取出主键索引数中的数据,即基于非主键索引的查询需要多扫描一棵索引树。

26、覆盖索引和联合索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。指的是通过索引就能查询到我们所需要的数据,而不需要根据索引再去查询数据表中的数据( 回表),这样就减少了数据库的 io 操作,提高查询效率。

使用表中的多个字段创建索引,就是联合索引,也叫组合索引或复合索引。

27、最左前缀匹配原则

最左前缀匹配原则指的是在使用联合索引时,MySQL 会根据联合索引中的字段顺序,从左到右依次到查询条件中去匹配,如果查询条件中存在与联合索引中最左侧字段相匹配的字段,则就会使用该字段过滤一批数据,直至联合索引中全部字段匹配完成,或者在执行过程中遇到范围查询,如 >、<、between 和 以%开头的like查询 等条件,才会停止匹配。

所以,我们在使用联合索引时,可以将区分度高的字段放在最左边,这也可以过滤更多数据。

28、索引下推

索引下推(Index Condition Pushdown) 是 MySQL 5.6 版本中提供的一项索引优化功能,可以在非聚簇索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表次数。

29、隐式转换

当操作符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。某些转换是隐式发生的。例如,MySQL 会根据需要自动将字符串转换为数字,反之亦然。以下规则描述了比较操作的转换方式:

  1. 两个参数至少有一个是NULL时,比较的结果也是NULL,特殊的情况是使用<=>对两个NULL做比较时会返回1,这两种情况都不需要做类型转换;
  2. 两个参数都是字符串,会按照字符串来比较,不做类型转换;
  3. 两个参数都是整数,按照整数来比较,不做类型转换;
  4. 十六进制的值和非数字做比较时,会被当做二进制串;
  5. 有一个参数是TIMESTAMP或DATETIME,并且另外一个参数是常量,常量会被转换为timestamp;
  6. 有一个参数是decimal类型,如果另外一个参数是decimal或者整数,会将整数转换为decimal后进行比较,如果另外一个参数是浮点数,则会把decimal转换为浮点数进行比较;
  7. 所有其他情况下,两个参数都会被转换为浮点数再进行比较;

30、普通索引和唯一索引该怎么选择?

所以唯一索引更加适合查询的场景,普通索引更适合插入的场景。

31、避免索引失效

索引失效也是慢查询的主要原因之一,常见的导致索引失效的情况有下面这些:

32、建立索引的规则

33、事务极其特性

一个事情由n个单元组成,这n个单元在执行过程中,要么同时成功,要么同时失败,这就把n个单元放在了一个事务之中。举个简单的例子:在不考虑试题正确与否的前提下,一张试卷由多个题目构成,当你答完题交给老师的时候是将一整张试卷交给老师,而不是将每道题单独交给老师,在这里试卷就可以理解成一个事务。

事务的特性:

34、并发事务带来的问题

35、事务的隔离级别

为了解决以上隔离性引发的并发问题,数据库提供了事务的隔离机制。

虽然 serializable 级别可以解决所有的数据库并发问题,但是它会在读取的每一行数据上都加锁,这就可能导致大量的超时和锁竞争问题,从而导致效率下降。所以我们在实际应用中也很少使用 serializable,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

36、MVCC

锁的粒度过大会导致性能的下降, MySQL 的 InnoDB 引擎下存在一种性能更优越的 MVCC 方法。

MVCC 是 Multi-Version Concurremt Control 的简称,意思是基于多版本的并发控制协议,通过版本号避免同一数据在不同事务间的竞争。它主要是为了提高数据库的并发读写性能,不用加锁就能让多个事务并发读写。

MVCC 的实现依赖于隐藏列、Undo log、 Read View

从上面对 SQL 标准定义了四个隔离级别的介绍可以看出,标准的 SQL 隔离级别定义里,REPEATABLE-READ(可重复读)是不可以防止幻读的

但是 InnoDB 实现的 REPEATABLE-READ 隔离级别其实是可以解决幻读问题发生的,主要有下面两种情况:

InnoDB 存储引擎在分布式事务的情况下一般会用到 SERIALIZABLE 隔离级别。

关于 MySQL 事务以及解决幻读的详细介绍,可以看看阿Q写的这篇文章:InnoDB 解决幻读的方案–LBCC&MVCC

37、Mysql 中的锁

具体的锁详情请参考阿Q的此篇文章:面试必备常见存储引擎与锁的分类,请查收

38、查询语句执行过程

select * from tb_student  s where s.age='18' and s.name=' 张三 ';

查询语句的执行流程如下:权限校验(如果命中缓存)—>查询缓存—>分析器—>优化器—>权限校验—>执行器—>引擎

39、更新语句执行过程

update tb_student A set A.age='19' where A.name=' 张三 ';

这条语句基本上也会沿着上一个查询的流程走,只不过执行更新的时候要记录日志,这就会引入日志模块了,MySQL 自带的日志模块是 binlog(归档日志) ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 redo log(重做日志),我们就以 InnoDB 模式下来探讨这个语句的执行流程。

更新语句执行流程如下:分析器---->权限校验---->执行器—>引擎—redo log(prepare 状态)—> binlog —>redo log(commit状态)

40、sql 优化

  1. 应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引;
  2. 应尽量避免在 where 子句中使用以下语句,否则将导致引擎放弃使用索引而进行全表扫描;
    • 对字段进行 null 值判断,
    • 使用!=或<>
    • or 来连接条件(使用union all代替)
    • in 和 not in 也要慎用
    • 不要使用模糊查询(可用全文索引)
    • 减少表达式操作
    • 函数操作
  3. 任何地方都不要使用 select * from t ,用具体的字段列表代替“* ”,不要返回用不到的任何字段;
  4. 一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要;
  5. 很多时候用 exists 代替 in 是一个好的选择;
  6. 尽量减少多表联合查询;
  7. 分页优化;
  8. 正确使用索引;

41、主从同步数据

在这里插入图片描述

同步策略

42、主从延迟要怎么解决

43、为什么不要使用长事务

今天的内容到这里就结束了,跪求一键三连,期望靓仔在评论区打出老铁666,鼓励一下阿Q。

好看的皮囊千篇一律,有趣的灵魂万里挑一,让我们在冷漠的城市里相互温暖,我是阿Q,我们下期再见!

来源地址:https://blog.csdn.net/Qingai521/article/details/131056168

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯