MySQL万字面试题汇总

MySQL

目录

1.MySQL中的数据排序是怎么实现的?

2.那怎么去优化ORDER BY呢?

3.MySQL中的Change Buffer是什么?有什么作用?

4.详细描述一下一条SQL语句在MySQL中的执行过程

5.MySQL的存储引擎有哪些?

6.MySQL的索引有哪些?

7.MySQLInnoDB 引擎中的聚集索引和非聚集索引有什么区别?

8.MySQL索引的最左前缀匹配原则是什么?

9.MySQL的覆盖索引是什么?

10.MySQL的索引下推是什么?

11.索引这么好用,那我建一堆索引不好吗?

12.MySQL中使用索引就一定有效吗?

13.请详细描述MySQL中的B+树中查询数据的全过程

14.为什么MySQL选择使用B+树作为索引结构?

15.为什么不使用B树呢?两者的区别在哪?

16.MySQL是如何实现事务的?

17.请你详细聊聊MySQL中的锁?

18.什么是MySQL中的Redo Log?

19.什么是MySQL中的Undo Log?

20.什么是MySQL中的MVCC?

21.如果MySQL中没有MVCC,会有什么影响?

22.MySQL中的事务隔离级别有哪些?

脏读(Dirty Read)

不可重复读(Non-repeatable Read)

幻读(Phantom Read)

23.MySQL默认的事务隔离级别是什么?为什么选择这个级别?

24. MySQL 的乐观锁和悲观锁是什么?

25.MySQL中发生了死锁怎么解决?

26.如何使用 MySQL 的 EXPLAIN 语句进行查询分析?

27.MySQL中 count(*)、count(1)和 count(字段名) 有什么区别?

28.MySQL 中 int(11) 的 11 表示什么?

29.MySQL中 varchar 和 char 有什么区别?

30. MySQL如何对SQL语句进行调优?

31.如何在MySQL中避免单点故障?/如何实现读写分离?

32.如何处理MySQL的主从同步延迟?

33.什么是分库分表?分库分表有哪些策略?

34.对数据库分库分表会产生哪些问题?

35.从 MySQL获取数据,是从磁盘读取的吗?

36.MySQL 的 Doublewrite Buffer 是什么?它有什么作用?

37.什么是MySQL的Log buffer?

38.为什么在数据库中都是不推荐使用多表JOIN?

39.MySQL 中 DELETE、DROP 和 TRUNCATE 的区别是什么?

40.MySQL中INNER JOIN、LEFT JOIN 和 RIGHT JOIN 的区别是什么?

41.数据库的三大范式是什么?

42.MySQL 中 TEXT 类型最大可以存储多长的文本?

43.什么是数据库中的视图?

44.MySQL中 VARCHAR(100)和 VARCHAR(10)的区别是什么?

45.MySQL中的EXISTS和IN的区别是什么?

46.什么是 Write-Ahead Logging (WAL)技术?它的优点是什么?MySQL 中是否用到了WAL?

47.MySQL的数据库的性能优化有哪些办法?

48.什么是数据库的逻辑外键?数据库的物理外键和逻辑外键各有什么优缺点?

49.什么是MySQL数据库中的binlog?和redo log有什么区别?

50.MySQL事务的二阶段提交是什么?

1.MySQL中的数据排序是怎么实现的?

MySQL中的数据排序主要通过ORDER BY子句实现,其底层实现机制主要有两种方式:

使用索引排序:当ORDER BY子句中的列恰好有对应的索引时,MySQL可以直接利用索引来完成排序操作,这是最高效的排序方式。索引本身是有序的,所以MySQL只需要按照索引的顺序扫描即可得到排序后的结果。

文件排序(flesort):当无法使用索引进行排序时,MySQL会使用文件排序。这种方法会将需要排序的数据加载到内存中,然后在内存中进行排序。如果数据量较大,超过了系统变量 sort buffer size 的大小,还会使用临时文件来协助排序。

具体实现如下:

首先,MySQL会检查ORDER BY子句中的列是否有可用的索引,如果有可用的索引,MySQL会直接使用索引进行排序。如果没有可用的索引,MySQL会执行以下步骤: 1.从表中读取满足条件的所有行 2.对于每一行,只保存需要排序的列和可以唯一标识行的列(如主键) 3.使用快速排序算法在内存中对这些数据进行排序 4.如果数据量太大,会使用临时文件来辅助排序 5.根据排序结果回表查询所需的列

延伸→那怎么去优化ORDER BY呢?

2.那怎么去优化ORDER BY呢?

1.根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则 2.尽量使用覆盖索引 3.多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC) 4.如果不可避免的出现file sort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256K) SQL语句:show variables like 'sort_buffer_size';

3.MySQL中的Change Buffer是什么?有什么作用?

Change Buffer ,更改缓冲区(针对于非唯一二级索引页),在执行 DML语句(增删改)时,如果这些数据Page 没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区Change Buffer 中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘中。

至于Buffer Pool是什么?可以去参考我的另一篇文章:MySQL数据表中的InnoDB引擎原理(存储结构+架构+事务原理+MVCC)_mysql innodb存储引擎实现原理-优快云博客

4.详细描述一下一条SQL语句在MySQL中的执行过程

1.当客户端的SQL发送到MySQL时,第一步是来到serve层的连接器,连接器会去验证身份和权限,因为你有连接数据库的权限不代表就有操作数据库的权限;

2.下一步就到了分析器进行SQL语法和词法分析,判断你这条SQL是什么类型的语句以及携带什么样的参数;

3.经过分析器之后就到了优化器,优化器会帮助我们选择使用哪个索引以及如果这条SQL涉及多表查询,优化器还会帮我们选择连表顺序;

4.最后到达执行器,执行器会操作存储引擎提供的接口并执行经过分析器分析以及优化器优化过后的SQL语句,并返回结果。

5.MySQL的存储引擎有哪些?

1.InnoDB:是Mysq!默认的存储引擎,支持事务,表级锁和粒度更小的行级锁,具有事务提交,回滚和数据崩溃恢复的功能

  1. MyISAM: 是之前Mysql默认的存储引擎,不支持事务和行级锁,支持表级锁,锁的粒度较大,更新性能较差,更适合读多写少的场景

    3.Memory:相较于InnoDB和MyISAM,Memroy是存在于内存中的,速度更快,但是不具有持久化的能力,适合临时存储的场景

6.MySQL的索引有哪些?

按索引的存储形式来分:聚集索引和二级索引

按索引的具体类型来分有:主键索引、唯一索引、常规索引、全文索引。

关于索引的其他只是可以参考我其他文章:深度解析MySQL数据库索引是什么?有什么用?怎么用?_mysql索引的使用和原理-优快云博客

7.MySQLInnoDB 引擎中的聚集索引和非聚集索引有什么区别?

聚集索引:索引叶子节点存的是数据行,可以直接访问整条数据,而且一张表只有一个聚集索引,通常是主键索引。

非聚集索引:索引叶子节点存的是主键和对应的索引列,一般走非聚集索引,如果不是覆盖索引还有回去聚集索引再查一次数据,这个过程叫回表查询。

8.MySQL索引的最左前缀匹配原则是什么?

在使用联合索引时,查询条件必须从索引的最左侧开始匹配。如果一个联合索引包含多个列,查询条件必须包含第一个列的条件,然后是第二个列,以此类推。

具体例子可以看以下我的文章:

深度解析MySQL数据库索引是什么?有什么用?怎么用?_mysql索引的使用和原理-优快云博客

9.MySQL的覆盖索引是什么?

MySQL 的覆盖索引(Covering lndex)是指二级索引中包含了查询所需的所有字段,从而使查询可以仅通过访问二级索引而不需要访问实际的表数据(主键索引)。,不需要回表查询,性能就会好很多。

10.MySQL的索引下推是什么?

索引下推是一种减少回表查询,提高查询效率的技术。它允许 MySQL 在使用索引查找数据时,将部分查询条件下推到存储引擎层过滤,从而减少需要从表中读取的数据行,减少了 IO(本该由 Server 层做操作,交由存储引擎层因此叫做“下推”)

简单来说就是:

如果没有索引下推,流程就是通过二级索引查到主键id后回表完再进行where条件过滤

有索引下推,流程就是二级索引查到数据后直接where过滤一遍 再进行回表 减少回表的次数

其实就是回表前再过滤一下,这样子回表查询的时候少查了一些数据,提高效率。

11.索引这么好用,那我建一堆索引不好吗?

1)索引并不是越多越好,索引是会占用空间的,而且每次修改数据的时候还要维护索引的数据,要是建的太多,维护的成本会很高。

2)对于字段的值有大量重复的不要建立索引,例如性别字段,一般只有男或女,0或1,有大量重复的值,因此它的选择性很低,意味着很多行都会匹配到同一个索引值,这样的话建立索引也不能提高检索速度。

3)对于一些长字段也不应该建立索引,特别是文本字段,建立出来的索引结构特别庞大,而且特别占内存,如果一定要的话,那就要截取字段中的一部分来建索引。

4)当数据库的修改频率远大于查询频率时,也不该建索引,因为建索引是会影响更新操作的,因为每次更新数据同时也要更新索引,因此会很消耗性能。

12.MySQL中使用索引就一定有效吗?

1.查询列未涉及到索引列不会触发索引

2.如果数据表量很小,可能不会走索引,直接全表查询

3.可以使用EXPLAIN命令,得到MySQL的执行计划,其中type表示是否执行了索引,key表示使用了哪个索引

4.如果查询中存在函数或者表达式,索引失效

5.如果查询中涉及<>!=,索引失效

6.如果查询中%Like,索引也会失效,但不是所有的模糊都失效,后模糊不失效

7.如果随便使用or,必须or的两个字段,都有索引,索引才会生效

8.相同字段的类型不相同,会涉及到转换,索引也会失效

9.表中两个不同的字段进行比较,索引会失效

10.使用了is not null,索引会失效

11.使用了order by,索引失效

13.请详细描述MySQL中的B+树中查询数据的全过程

首先从根节点开始,根据键值来判断是左子树还是右子树,逐层搜索,直到找到叶子节点,即对应的数据页。在确定了待查找数据就存在于这个数据页上之后,我们将这个数据页加载到内存,通过页目录做二分查找,定位出一个粗略的记录分组,最后在这个分组里通过链表遍历的方式来找到指定记录。

14.为什么MySQL选择使用B+树作为索引结构?

1.B+树是一种自平衡树,每个叶子节点到根节点的路径长度相同,在插入和删除结点是进行分裂和合并操作,以保持树的平衡,让树的高度不会太高。

2.非叶子节点仅保存主键或索引值的页面指针,使得每一页能容纳更多的记录,因此内存中就能存放更多索引。

3.B+树特别适合范围查询,因为叶子节点通过链表连接,从根节点定位到叶子节点查找到范围的起点之后,只需要顺序扫描链表即可遍历后续的数据,非常高效。

延伸→为什么不使用B树呢?两者的区别在哪?

15.为什么不使用B树呢?两者的区别在哪?

1)B树每个节点都存储了完整的数据,而 B+ 树非叶子节点仅存储 key 和指针,完整数据存储在叶子节点。这使得 B+ 树可以在内存中存放更多索引页,减少磁盘查询次数。 2)B+树叶子组成了链表,便于区间查找,而 B树只能每一层遍历查找。 3)B+ 树查询时间更平均、稳定,都需要从根节点扫描到叶子节点。而 B树则在非叶子节点就可能找到对应的数据返回。

16.MySQL是如何实现事务的?

1.MySQL是通过锁,Redo log,Undo log,MVCC来实现的

2.使用InnoDB锁机制实现数据并发修改的控制,实现事务的隔离性

3.Redo log记录日志修改的数据,在崩溃时恢复未提交的更改,实现事务的持久性

4.Undo log保留历史数据记录,在事务执行失败后,可以进行事务的回滚,实现了原子性和隔离性

5.MVCC(多并发版本控制)满足了非锁定读的需求,支持读未提交,读已提交,可重复读的隔离性

6.一致性是通过AID,隔离性,原子性,持久性实现的

17.请你详细聊聊MySQL中的锁?

MySQL中的锁有全局锁、表级锁、行级锁

  • 其中全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的 DML 的写语句, DDL 语句,已经更新操作的事务提交语句都将被阻塞。

  • 表级锁就是作用在表上的锁,主要分类有表锁、元数据锁、意向锁,

    • 其中表锁又分有表共享读锁和表独占写锁,顾名思义就是作用在这张表上之后,允许有多线程的读操作但只能有单线程的写操作。

    • 元数据锁为了解决在增删改的时候表结构被修改,然后造成前后不一致的情况,是为了确保读写一致的锁。

    • 意向锁是为了解决行锁和表锁的区别,如果没有意向锁,那在加上表锁之前需要逐行的遍历检查是否存在行锁,如果没有就上表锁,这样逐行遍历肯定是会比较消耗性能的。

  • 行级锁分有间隙锁和临键锁,针对两个索引记录之间的空间加锁,防止其他事务在两个间隙之间添加记录。临键锁是行级锁和间隙锁的结合,能够保证一定范围之内不会出现幻读。

延伸→什么是幻读?

在一个事务中,多次读取同一范围的数据,由于另一个事务的插入操作,导致读取到之前不存在的数据。

18.什么是MySQL中的Redo Log?

重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性

该日志文件由两部分组成:重做日志缓冲( redo log buffer)以及重做日志文件(redo log file) ,前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中 , 用 于在刷新脏页到磁盘 ,发生错误时 , 进行数据恢复使用。

延伸→那Redo log是怎么进行数据恢复使用的呢?

InnoDB的内存结构中有个Buffer Pool,Buffer Pool中存放着数据页,我们的增删改操作会先在Buffer Pool中进行,增删改之后的数据页叫做脏页,脏页会在一定时机之后通过后台线程刷新到磁盘中,redo log是为了保证我们在进行脏页刷新发生错误时进行数据恢复,从而保证事务的持久性。

延伸→具体是怎么的操作呢?

有了redo log(内存中的Redolog Buffer + 磁盘中的redo log file)之后,会先将脏页记录在redo log buffer中,在事务提交时,再将redo log buffer 中的数据刷新到redo log file中(内存到磁盘),当脏页刷新磁盘错误时就可以通过redo log进行数据恢复。

19.什么是MySQL中的Undo Log?

回滚日志,用于记录数据被修改前的信息 , 作用包含两个 : 提供回滚(保证事务的原子性) 和 MVCC(多版本并发控制) 。

undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时, undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

20.什么是MySQL中的MVCC?

建议阅读我的另一篇文章:MySQL数据表中的InnoDB引擎原理(存储结构+架构+事务原理+MVCC)_mysql innodb存储引擎实现原理-优快云博客

21.如果MySQL中没有MVCC,会有什么影响?

如果没有mvcc,并发情况下想保持数据的一致性,无论读写都要对数据进行加锁(串行化隔离级别),大大影响了数据读写的性能。 多个事务之间会频繁的竞争锁资源,事务可能因为等待锁而被组赛,从而延长用户的的响应时间。

最直观的例子就是:目前有两个事务,事务A在修改数据(但还未提交),与此同时事务B想要查询数据,如果没有MVCC,那事务B就会一直等待事务A的锁释放,这样就很影响读写性能。如果有MVCC,那么事务B就能够直接查到修改前的数据,这样就大大提高了事务的并发度,提升MySQL性能。

22.MySQL中的事务隔离级别有哪些?

1.读未提交,事务a可以读取到事务b未提交的数据,会出现脏读现象 2.读已提交,事务a可以读取到事务b已经提交的数据,会出现不可重复读现象,前后多次读取,数据不一致 3.可重复读,事务a可以读取到相同的数据,可能会出现幻读现象,前后多次读取,数据前后总量不一致 4.串行化,最高级别的隔离等级

关于脏读、不可重复读、幻读的例子如下:

脏读(Dirty Read)

脏读是指一个事务读取了另一个事务未提交的数据。例如,在转账操作中:

  1. 事务A开始,查询账户余额为2000元。

  2. 事务B开始,从账户中取款1000元,余额变为1000元,但未提交。

  3. 事务A再次查询账户余额,读到的余额为1000元(脏读),因为事务B还未提交。

  4. 事务B因错误回滚,账户余额恢复为2000元。

  5. 事务A提交,基于错误的脏读数据进行了后续操作,导致错误。

不可重复读(Non-repeatable Read)

不可重复读是指在一个事务中,多次读取同一数据集合时,由于另一个事务的修改,导致读取结果不一致。例如:

  1. 事务A开始,读取小明的年龄为20岁。

  2. 事务B开始,将小明的年龄更改为30岁,并提交。

  3. 事务A再次读取小明的年龄,发现变为30岁,与第一次读取的结果不同。

幻读(Phantom Read)

幻读是指在一个事务中,多次读取同一范围的数据时,由于另一个事务的插入或删除操作,导致读取到的记录数量不一致。例如:

  1. 事务T1查询id大于2的记录,得到5条数据。

  2. 事务T2插入一条新的记录,id为6,并提交。

  3. 事务T1再次查询id大于2的记录,发现现在有6条数据,与第一次查询的结果不同,就像出现了幻觉一样。

我用一套比喻来形容这三种情况 1.脏读是:“被骗了” 2.不可重复读:“谁改我键位了?” 3.幻读:“闹鬼了,出去10个人,回来11个人”。

23.MySQL默认的事务隔离级别是什么?为什么选择这个级别?

默认使用可重复读隔离模式,避免使用读未提交,读已提交隔离导致的幻读和主从数据不一致

24. MySQL 的乐观锁和悲观锁是什么?

悲观锁就是MySQL在操作数据前就对数据加锁,其他事务没有获取锁的话就不能操作数据。

乐观锁就是不会在数据加锁,但每次操作数据会检验前后的版本号或时间戳是否一致,一致的话就说明数据没有被改动,此时可以操作,不一致就说明被改动了,此时不可以操作。

25.MySQL中发生了死锁怎么解决?

MySQL内部有死锁检测机制,检测到死锁就会回滚其中占有资源最少的事务,我们也可以手动kill掉造成死锁的事务。

26.如何使用 MySQL 的 EXPLAIN 语句进行查询分析?

用法就是直接在SQL语句前加上explain关键字,然后主要就是看他的id,type和row

1、id 执行顺序,越大越优先 2、type 执行情况由,好到差是: (1)system/const 通过主键或唯一索引查询,只有一行命中 (2)eq_ref 主键或唯一索引上的join查询,对于前表的每一行后表只有一行命中 (3)ref 非唯一索引的等值匹配,可能有多行命中 (4)range 索引的范围扫描,比如between 大于 小于 (5)index 索引上的全集扫描,比如count (6)al 全表扫描,也是性能最差 3.rows 预估扫描的行数,越小越好

具体用法可以看我的另一篇文章:MySQL中explain关键字的用法以及每个字段的含义-优快云博客

27.MySQL中 count(*)、count(1)和 count(字段名) 有什么区别?

1)count()会统计表中所有行的数量,包括u1值(不会忽略任何一行数据)。由于只是计算行数,不需要对具体的列进行处理,因此性能通常较高。 2)count(1)和 count()几乎没差别,也会统计表中所有行的数量,包括 null值。 3)count(字段名)会统计指定字段不为 null 的行数。这种写法会对指定的字段进行计数,只会统计字段值不为 null 的行。

28.MySQL 中 int(11) 的 11 表示什么?

在MySQL中,int(11)是一种整数类型的数据定义,其中int表示这是一个整数类型的字段,而括号中的数字11代表的是显示宽度,并不会影响该字段实际存储的数值范围。

具体来说,int(11)中的11表示在显示结果时,该字段的值将以11个字符的宽度显示。如果实际值的长度小于11,MySQL会根据需要用空格填充;如果实际值的长度大于11,则显示实际值。这个显示宽度对于存储和计算并没有任何影响,仅在显示查询结果时起到对齐的作用。

例如,如果你插入数字123到一个INT(11) ZEROFILL列中,MySQL可能会将其显示为000000000123。如果没有使用ZEROFILL,数字将按原样显示,不会有额外的零。所以,int(11)实际上可以存储的数值范围是-2,147,483,6482,147,483,647(有符号)或04,294,967,295(无符号),与int类型的最大值相同。

29.MySQL中 varchar 和 char 有什么区别?

  • char 表示的是定长字符串,如果实际存储的字符串小于预定的大小,则会使用空格填充是使达到预定长度

  • varchar 表示可变长度的字符串,实际存储的字符串长度是多少就会占用实际存储的长度+上1--2字节的大小。这1-2个字节是用来记录字符串大小信息的。

一般除非是涉及到身份证号,邮编这种确实格式定了的字符串,都采用varchar比较好

30. MySQL如何对SQL语句进行调优?

SQL优化无非就是三点:命中索引、减少回表

命中索引:

1.联合索引要符合最左匹配原则

2.索引不能进行运算

3.索引不能使用函数

4.对经常出现在where语句后面的字段建立索引

5.对排序的字段建立索引

6.避免使用like %

减少回表:

1.避免使用select * ,select *一般都会走回表

2.使用覆盖索引,即索引中包含select后面所需的所有列,避免回表查询

31.如何在MySQL中避免单点故障?/如何实现读写分离?

一般会使用主从架构的形式,主数据库+从数据库,读操作只在从数据库中读,写操作往主数据库中写,写完之后再数据同步到从数据库,当主数据库崩了之后,就让从数据库顶上来,读写操作都由从数据库承担,等到主数据库恢复了之后,再将从数据库中的数据同步到主数据库并恢复读写分离。

32.如何处理MySQL的主从同步延迟?

主从同步延迟就是主数据库和从数据库之间的数据同步存在时间差,导致从数据库的数据落后于主数据库。这种延迟是必然存在的,我们无法避免,只能尽量减少。

我能想到比较好的两点方案能够尽量减少主从同步延迟:

  • 第一点就是关键业务的读写都走主数据库,比如用户注册这种比较重要的,这样用户登录进来就不会说账号不存在等问题。

  • 第二点就是设置缓存,在主库写入之后同步到缓存,这样每次查询就先查缓存,缓存没有再查数据库,但是这样又会出现缓存数据不一致的问题。

33.什么是分库分表?分库分表有哪些策略?

什么是分库分表: 将数据进行拆分,放到不同的数据库或者表中

分库分表的类型(策略):水平分表,垂直分表,垂直分库,水平分库

  • 水平分表:将一个表按行进行拆分,分成多行,放到不同的表中(表数据太多了,分一点到其他表)

  • 垂直分表:将一个表按列进行拆分,分成多列,放到不同的表中(表字段太多了,分一点到其他表)

  • 水平分库:不同的库可以具有相同的表结构,只不过每个表里面的数据不一样。

  • 垂直分库:根据功能或者模块进行分库,不同的库存储不同功能或模块的数据,例如用户模块,订单模块,一个搞一个数据库。

水平分库比垂直分库维护起来更加的困难,跨库查询更加的复杂。

为什么要分库分表:业务发展需要,用户以及数据越来越多,单库单表抗不住压力,性能差。分库分表,能够提升性能。

34.对数据库分库分表会产生哪些问题?

1.事务问题。单机事务用不上,得使用分布式事务,而分布式事务大多只能保证数据的最终一致性,所以可能存在数据不一致的场景

2.分库之后,不同库里面的表不能进行ioin查询。一般在应用层进行外理,可以先查出一个表里面的数据,然后根据这些数据做一些处理之后,去查另一个库里面的表,最后进行整合,得到最终结果。还可以在表里面存储一些冗余数据,避免连表查询。

3.主键id重复问题。主键id在分库分表之后,可能存在重复的情况,可以使用雪花算法或者分布式唯一id生成器来生成。

4.order by和count问题。分库分表后,order by,count无法通过数据库直接实现。可以通过应用层代码实现。

这里可能会被问到分布式事务、分布式唯一id生成器等问题

35.从 MySQL获取数据,是从磁盘读取的吗?

并不总是从磁盘读取。

  • mysql8.0之前有查询缓存,会先去查询缓存里面找,如果查询缓存里面有的话,直接返回。

  • 8.0的时候移除了查询缓存,因为命中率低,它是以sql作为key,sql语句要相同,而且表不能发生任何变化,才能命中。

  • 还有个buffer pool,里面存储了一个一个的数据页,mysql会从buffer pool里面找,如果找到的话就会返回。

36.MySQL 的 Doublewrite Buffer 是什么?它有什么作用?

MySQL 的 Doublewrite Bufer 是 InnoDB存储引擎中的一个机制,用于确保数据的安全性和一致性。它的作用是将数据先写入一个内存缓冲区(双写缓冲区),然后再将其写入数据文件。这种方式可以防止在写入过程中因崩溃或故障导致数据损坏,确保数据的一致性和完整性。

工作原理简述:

  • 写入流程:当事务提交时,InnoDB 首先将数据写入 Doublewrite Buffer,再从该缓冲区将数据写入磁盘的实际数据文件。

  • 恢复机制:在崩溃恢复时,InnoDB 会使用 Doublewrite Buffer 中的数据来修复损坏的页,保证教据不丢失。

延伸→那如果在写入Buffer的时候就出问题了怎么办?

这个问题我没深入研究过,我觉得InnoDB引擎在底层应该会对这次操作进行再次执行并重试写入Buffer中。

37.什么是MySQL的Log buffer?

详情请跳转我的另一篇文章:MySQL数据表中的InnoDB引擎原理(存储结构+架构+事务原理+MVCC)_mysql innodb存储引擎实现原理-优快云博客

38.为什么在数据库中都是不推荐使用多表JOIN?

多表 JOIN 可能导致查询性能下降,尤其是在处理大数据集时,JOIN 操作的计算复杂度会显著增加,需要进行大量的数据扫描和匹配,增加了内存和CPU的消耗,导致响应时间变长。数据量小倒数据库往往是我们系统的弱点,很多情况下性能瓶颈都在数据库,因此我们需要尽量避免把压力放在数据库上。

如果实在要JOIN,尽量值JOIN两张表,三表以上不JOIN,太耗性能了。JOIN的时候尽量小表做驱动表,因为驱动表要全表扫描,被驱动表走索引,整体复杂度是A+2log2B*A(A为驱动表,B为被驱动表),所以尽量让A尽量小。

39.MySQL 中 DELETE、DROP 和 TRUNCATE 的区别是什么?

1.Delete 用于删除行数据,但保留表结构和相关的对象。

2.Drop 用于完全删除数据库表,包括数据和结构。

3.Truncate只删除数据,不会删除表结构和索引等其他结构。

40.MySQL中INNER JOIN、LEFT JOIN 和 RIGHT JOIN 的区别是什么?

  1. inner join 内连接:内连接就是返回两张表都关联上的数据

  2. left join 左连接:返回时保留左表的数据,右表关联不上的会显示null值

  3. right join 右连接:返回时保留右表的数据,左表关联不上的会显示null值

41.数据库的三大范式是什么?

1、数据库的每个字段都是不可再分的属性,不能出现数组集合等数据,保证每个字段的原子性

2、每个字段都是依赖于整个主键而不是主键的一部分,消除部分依赖。

3、每个字段都是直接依赖于主键,而不是间接依赖,消除依赖传递。

42.MySQL 中 TEXT 类型最大可以存储多长的文本?

  1. TINYTEXT:最大长度为 255 字节

  2. TEXT:最大长度为 65,535 字节(约 64 KB)

  3. MEDIUMTEXT:最大长度为16,777,215字节(约16 MB)

  4. LONGTEXT:最大长度为 4,294,967,295 字节(约4 GB)

43.什么是数据库中的视图?

  • 数据库视图是一个虚拟表,它基于一个或多个表的数据,但本身不存储数据。视图简化了数据查询和操作,同时可以提高数据安全性。它只是一种逻辑上的表示,不占用物理空间。

  • 其实就是将表中的列抽象出来形成视图。可以理解成存储起来的sql语句,其它地方可以直接用。

  • 不暴露底层的表结构,有权限控制,所以可以保护一些敏感的、不想让别人看见的列。

  • 视图可以被重复利用,减少代码冗余。

44.MySQL中 VARCHAR(100)和 VARCHAR(10)的区别是什么?

两者的区别就是能存储的字符串长度上限不同,字符数上限是由定义中的括号内的数字决定的。

  • VARCHAR(100)最多可以存储 100 个字符

  • VARCHAR(10)最多可以存储10 个字符

两者存储相同字符串时占用的空间是一样的。除了存储字符本身外,还需要额外的1或 2 个字节来记录字符串的长度。对于长度小于 255 的字符串,使用1个字节;对于长度 255 及以上的字符串,使用 2个字节。 虽然存储的空间一样,但是在查询时,即带上 SORT、ORDER 这些字段时,VARCHAR(100)字段会使得查询所占用的内存空间更多,因为在排序相关内存分配时,它是按照固定大小的内存块进行保存,VARCHAR(100)的内存块会大于 VARCHAR(10)。

45.MySQL中的EXISTS和IN的区别是什么?

  • exist:用于判断子查询是否有返回,一旦查询到匹配的数据立马返回,适合子表数据量比父表大的场景

  • in:用于判断某个值是否在某个集合中,会对子查询进行全表扫描,适用于子表数据量小或简单的静态值集合

46.什么是 Write-Ahead Logging (WAL)技术?它的优点是什么?MySQL 中是否用到了WAL?

WAL (Write-Ahead Logging)技术是一种数据库事务日志管理技术,它确保在修改真正的数据之前,先将修改记录写入日志。这使得即使系统崩溃,通过日志也能恢复数据。保证了数据的持久性和一致性。WAL 它的核心思想就是先写日志,再写数据,大致执行流程如下: 1)当一个事务开始时,所有对数据库的修改都会先记录到一个日志文件中,而不是直接应用到数据库文件,这些日志记录了数据的变更信息,可以用于恢复数据。 2)当日志记录被安全地写入磁盘后,才会将这些修改应用到数据库文件中。

47.MySQL的数据库的性能优化有哪些办法?

主要分SQL优化和库表优化两个方面。

SQL 优化(用上索引+减少回表) 根据慢 SQL 日志,找出需要优化的一些语句。 常见优化方向: 1)避免 SELECT*,只查询必要的字段 2)避免在 SQL 中进行函数计算等操作,使得无法命中索引 3)避免使用 %LIKE,导致全表扫描 4)注意联合索引需满足最左匹配原则 5)不要对无索引字段进行排序操作 6)连表查询需要注意不同字段的字符集是否一致,否则也会导致全表扫描

库表设计优化 1)合理的表结构:比如选择合适的数据类型,例如能用 int 的不要用 bigint,还有 varchar 和 char 的选择等等。 2)合理冗余字段:在适当的情况下进行反规范化设计,冗余部分数据,减少关联查询。 3)索引优化:根据查询频率和条件,创建合适的索引,删除不必要的索引,因为索引的维护也是需要成本的。建议使用 EXPLAIN 分析查询执行计划,确认是否用上索引,是否用对索引。 4)分库分表:对于超大规模的数据库系统,可以采用分库分表策略,将数据拆分到多个数据库或表中,提高读写性能和扩展性。

48.什么是数据库的逻辑外键?数据库的物理外键和逻辑外键各有什么优缺点?

逻辑外键不是外键,是一个字段,但是这个字段可以在应用层使用代码来维护表之间的关系。 逻辑外键需要自己手动维护,增加代码量,但是比较灵活,物理外键是由mysql自己维护,方便维护,但是是一种强阻塞,性能差 在并发场景下可能出发级联更新引发数据更新的问题。

延伸→为什么不推荐使用数据库中的外键?

不得使用外键与级联,一切外键概念必须在应用层解决。说明:学生表中的student id 是主键,那么成绩表中的 student id 则为外键。如果更新学生表中的student id,同时触发成绩表中的 student id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式高并发集群:级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

49.什么是MySQL数据库中的binlog?和redo log有什么区别?

MySQL中的binlog(二进制日志)和redo log(重做日志)是两种不同的日志,它们在数据库中扮演着不同的角色,以下是它们的主要区别:

  1. 存储引擎层面

    • redo log 是InnoDB存储引擎特有的日志,只记录数据页的物理修改。

    • binlog 是MySQL服务器层面的日志,记录所有数据库表的修改,包括增删改操作(DML)和表结构的修改(DDL)。

  2. 记录内容

    • redo log 是物理日志,记录数据页的物理修改,关注的是对页的修改。

    • binlog 是逻辑日志,记录的是语句的原始逻辑,类似于“给ID=2这一行的c字段加1”。

  3. 记录时机

    • redo log 在事务提交时记录。

    • binlog 在语句执行时记录。

  4. 使用场景

    • redo log 主要用于恢复数据库,确保事务的原子性和一致性。

    • binlog 用于数据复制、数据恢复、增量备份等高级功能。

50.MySQL事务的二阶段提交是什么?

二阶段提交是mysql为了保证redo log和binlog一致性使用的一种机制。可以在崩溃恢复时保证数据的一致性。

分为两个阶段:准备阶段 +提交阶段 1.准备阶段:InnoDB引擎会先写redo log,并且将其标记为prepare阶段,表示事务已经准备提交但是还没有完成; 2.提交阶段:当redo log变成prepare阶段之后,mysql server层会写binlog,binlog写完之后,会通知InnoDB引擎,将redo log标记成commit状态。表示事务完成。

redo log:记录修改了某个数据页的哪些位置。用于崩溃恢复。 binlog:记录的是sql语句的原始逻辑,例如如“给id=1这一行的age字段加1”,就类似一条sql语句,主要用于主从复制。

为什么需要二阶段提交: 如果没有二阶段提交,可能会出现redo log 和binlog两个日志的不一致,只有出现不一致,在后续的数据恢复中都会导致数据不一致。

阶段提交是如何保证崩溃恢复时的数据一致性:通过对比XID, 1.redo log处于prepare阶段,binlog还没写入,mysql挂了事务还没有提交,binlog里面还没有,所以只要redolog的不做数,数据就是一致的。 2.redo log处于prepare阶段,binlog写入了,mysql挂了对比redo log和binlog是否一致,一致的话,则提交事务,不一致就回滚,也能保证数据一致。

如何对比redolog和binlog:XID(事务ID) 扫描redo log,如果发现有prepare状态的redolog,则拿XID去binlog里面找,如果找到了具有相同XID的事务记录,说明数据已经保存好了,当前这个事务可以直接提交,否则回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值