IT评测·应用市场-qidao123.com

标题: 【MySQL】一文看懂MySQL所有常见问题 [打印本页]

作者: 守听    时间: 2024-3-11 21:46
标题: 【MySQL】一文看懂MySQL所有常见问题
MySQL作为一款开源关系型数据库,如今绝对是占据关系型数据库的主导地位,不仅是面试中的常客,也是日常工作中最主要接触的数据库。因此,无论是背面试八股,还是工作使用,都是一定要深度掌握的一个知识点。今天就用一篇文章讲清楚MySQL的所有问题
着急的小伙伴可直接跳到最后MySQL常见面试题总结

一、事务

定义:一组操作要么全部成功,要么全部失败,目的是为了保证数据最终的一致性
在MySQL中,提供了一系列事务相关的命令:
事务的ACID

事务的隔离级别

脏读、幻读、不可重复读问题

脏读:读取到其他事务未提交的数据,由于数据还没提交,因此可能产生回滚

幻读:主要针对插入删除操作来说,比如事务A对全部数据的某一字段做了修改并提交,若事务A提交前,事务B插入了一条数据,事务A再次查询会发现存在修改未生效的数据,如同幻觉

不可重复读:多次读取同一数据得到不同结果

区别:
MVCC

MVCC机制的全称为Multi-Version Concurrency Control,即多版本并发控制技术,主要是为了提升数据库并发性能而设计的,其中采用更好的方式处理了读-写并发冲突,做到即使有读写冲突时,也可以不加锁解决,从而确保了任何时刻的读操作都是非阻塞的。
对于使用 InnoDB 存储引擎的数据库表,它的聚簇索引记录中都包含下面两个隐藏列:
InnoDB 里面每个事务有一个唯一的事务 ID,叫作 transaction id。它是在事务开始的时候向 InnoDB 的事务系统申请的,是按申请顺序严格递增的。
MCC的多版本主要依赖Undo-log日志来实现,而并发控制则通过表的隐藏字段+ReadView快照来实现,通过Undo-log日志、隐藏字段、ReadView快照,就实现了MVCC机制
MySQL中的日志

undo日志

undo log 有两个作用:提供回滚和多个行版本控制(MVCC)
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。
redo日志

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

InnoDB 存储引擎为 redo log 的刷盘策略提供了 innodb_flush_log_at_trx_commit 参数(默认1),它支持三种策略
InnoDB 存储引擎有一个后台线程,每隔1秒,就会把 redo log buffer 中的内容写到文件系统缓存(OS Buffer),然后调用 fsync 刷盘。
redo log buffer占用的空间即将达到 innodb_log_buffer_size 一半的时候,后台线程会主动刷盘。
binlog日志

binlog 是归档日志,属于 Server 层的日志,是一个二进制格式的文件,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”。
不管用什么存储引擎,只要发生了表数据更新,都会产生 binlog 日志。它的主要作用就是数据备份、主从复制。
binlog会记录所有涉及更新数据的逻辑操作,属于逻辑日志,并且是顺序写。
binglog格式

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

事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。
因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache。我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap)。
binlog 也提供了 sync_binlog 参数来控制写入 page cache 和磁盘的时机:
relay日志

主从同步使用的中继日志,用于存储从master节点同步过来的binlog日志内容
二、索引

索引能快速定位数据的一种数据结构,其设计思想是以空间换时间

1. B+树索引

衍变过程:


如下图是一个三阶B树,每个节点存两个数据,并存三个寻址地址指向下一个节点

mysql默认文件页大小是16kb,一个寻址数据大概6b,若存储的是bigint,即8b,那么一块文件页能存储 16kb / (8b + 6b) = 1170个索引;那么一棵三阶B+树,能存储 16x1170x1170≈2000万数据
B树与B+树的区别
MySQL中的InnoDB引擎会为每个表创建主键索引,如果表没有明确的主键索引,InnoDB会使用自动生成的隐藏的主键(RowId)来创建索引
2. Hash索引

Hash索引即哈希结构索引,数据结构和Java的HashMap差不多,是数组加链表的形式
InnoDB不支持显示创建Hash索引,只支持自适应Hash索引。仅memory引擎支持hash索引,memory引擎运行于内存中。

• 优点:等值比较效率高
• 缺点:不支持范围查询,也不支持排序,因为索引列无序
3. 聚集索引和非聚集索引

按物理存储方式分类:InnoDB使用聚集索引,MyISAM使用非聚集索引
创建两个测试数据表test_innodb(使用InnoDB引擎)和test_myisam(使用MyISAM引擎),最终在mysql的服务器目录下看到的文件如下:
  1. -rw-r----- 1 mysql mysql  114688 Oct 31 11:30 test_innodb.ibd     
  2. -rw-r----- 1 mysql mysql       0 Oct 31 11:31 test_myisam.MYD     
  3. -rw-r----- 1 mysql mysql    1024 Oct 31 11:31 test_myisam.MYI   
  4. -rw-r----- 1 mysql mysql    1653 Oct 31 11:31 test_myisam_491.sdi  
复制代码
InnoDB仅用一个文件ibd存储了索引和数据
MyISAM分为了三个文件,MYD存储表数据,MYI存储表索引,sdi存储表元数据
MyISAM的叶子节点存储的不是数据,而是数据对应的磁盘指针
InnoDB的主键索引的叶子节点存储的表的所有列,非主键索引的叶子结点存储的表的主键
因此InnoDB是聚集索引,MyISAM是非聚集索引
• 聚集索引优点:因为所有数据都存在B+树的叶子节点,因此可以减少一个数据的查询,提高了查询效率
• 聚集索引缺点:对数据进行修改删除操作时需要更新索引树,增加系统开销,非聚集索引可以避免这个缺陷
4. 二级索引

所有非主键索引均为二级索引,InnoDB中二级索引采用非聚集索引

如上所示,我们对一个age字段进行二级索引,最终得到数据时ID主键,我们需要再根据ID主键去查找数据(回表),这也是非聚集索引
  1. SELECT * FROM `user` WHERE age = 17;
复制代码
比如上面sql,首先会通过age=17这个条件在age的二级索引中找到id7,然后再用id7去ID索引去查找对应的数据
5. 覆盖索引

还是比如上面的sql,若使用select *,那么在通过二级索引找到id后,还需要到id索引找到数据列,假如对上述sql优化如下
  1. SELECT id FROM `user` WHERE age = 17;
复制代码
那么在age的二级索引的数据中,就已经有了id列,不再需要回表查询这个ID对应的所有数据,这种情况叫覆盖索引,即索引结果包含了所有所需的数据。
覆盖索引也是sql优化中的一个手段
6. 索引下推

是MySQL5.6针对扫描二级索引的优化,用于减少范围查询时的回表次数。
  1. SELECT * FROM `user` WHERE age > 10 AND age < 20;
复制代码
比如在这次查询中,我们查到5个人年龄在10到20之间,如果没有索引下推,即会产生5次回表查询来获取所有数据。索引下推即让5次回表合并为一次回表查询。
7. 单列索引和联合索引

• 单列索引:只有一个字段的索引
• 联合索引:有多个字段的索引
在联合索引时,多个字段会存在同一个索引页(B+树节点)中,并且会以优先级按第一个字段,第二个字段,第N字段组合排序

最左前缀原则

在联合索引时,SQL查询需要遵循最左前缀原则,假如建立name和age字段的联合索引。如果我们查询条件只查第二个索引字段age,而不查第一个索引字段name,那么在扫描时,是无序的,只能做全盘扫描,比如以下例子:
以下SQL会执行全盘扫描
  1. SELECT * FROM `user` WHERE age=15;
复制代码
而以下SQL则会快速定位索引
  1. SELECT * FROM `user` WHERE name='张三' AND age=15;
复制代码
联合索引优势

  1. SELECT a,b,c FROM table WHERE a='xxx' AND b='XX';
复制代码
那么MySQL可以通过索引直接得到数据而省略回表操作,提高IO性能
8. 索引优缺点及适合场景

9. 索引优化

可归纳为:保证查询条件的有序性才能让索引生效
  1. SELECT * FROM `user` WHERE left(name,2) = '张三';
复制代码
  1. SELECT * FROM `user` WHERE name = '张三' AND age > 18 AND position = 0;
复制代码
三、SQL优化

1. 避免SELECT星号

2. 小表驱动大表

小表驱动大表指用数据量小、索引完备的表,使用其索引和条件对大表进行数据筛选,从减少数据计算量,提高查询效率。
3. 连接查询代替子查询

4. 提升group by效率

创建group by的字段的索引
5. 批量插入

有多条插入语句时,可通过SQL进行批量插入,减少数据库IO次数
INSERT INTO user(id,name,age) VALUES(1,'张三',18),(1,'李四',20),(1,'王五',25),(1,'赵六',30);
6. 使用limit

7. union all代替union

如果没有去重需求,直接优化为union,如果有去重需求,尽量再查询条件去重
8. 尽量少join关联表

四、MySQl常见面试题

1. 数据库三大范式

2. DML 语句和 DDL 语句区别

3. drop、delete、truncate 区别

4. MyISAM 和 InnoDB 的区别

区别MyISAMInnoDB最小锁粒度表级锁行级锁外键不支持支持索引B+树非聚集索引B+树聚集索引主键可以没有若没有主键会自动生成隐藏主键Row_id事务不支持支持异常崩溃恢复不支持可根据redo日志在重启后恢复5. 什么是redo日志

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

InnoDB 存储引擎为 redo log 的刷盘策略提供了 innodb_flush_log_at_trx_commit 参数(默认1),它支持三种策略
6. 什么是binlog日志

binlog 是归档日志,属于 Server 层的日志,是一个二进制格式的文件,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”。
不管用什么存储引擎,只要发生了表数据更新,都会产生 binlog 日志。它的主要作用就是数据备份、主从复制。
binlog会记录所有涉及更新数据的逻辑操作,属于逻辑日志,并且是顺序写。
binglog格式

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

事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。
因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache。我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap)。
binlog 也提供了 sync_binlog 参数来控制写入 page cache 和磁盘的时机:
7. binlog和redolog区别

8. 什么是undo日志

MySQL中所有的事务中进行的修改都记录到undo日志,若需要进行回滚,则通过undo日志进行回滚
9. 什么是relay日志

主从同步使用的中继日志,用于存储从master节点同步过来的binlog日志内容
10. 什么是Hash索引

Hash索引即哈希结构索引,数据结构和Java的HashMap差不多,是数组加链表的形式
InnoDB不支持显示创建Hash索引,只支持自适应Hash索引。仅memory引擎支持hash索引,memory引擎运行于内存中。
• 优点:等值比较效率高
• 缺点:不支持范围查询,也不支持排序,因为索引列无序
11. B树和B+树的区别

12. 什么是最左前缀原则

最左前缀原则即在有联合索引的查询中,where条件必须按照联合索引字段的顺序依次查询,才能有效利用索引
13. 什么是聚簇索引和非聚簇索引

聚簇索引即B+树种存储索引和数据
非聚簇索引在B+树种存储索引,而完整数据存在其他地方
MyISAM使用非聚簇索引,InnoDB的主键索引使用聚簇索引,非主键索引使用非聚簇索引
14. 索引失效有哪些情况

15. 什么是索引下推

索引条件下推,是防止明明可以在存储引擎层判断,但还回表查询后拿到server层判断,减少回表次数。它是MySQL的内部优化,将判断where条件从server层下推到存储引擎层,也就是说存储引擎层也会判断查询其他条件
  1. #ON表示已开启
  2. show variables like 'log_bin_trust%';
复制代码
16. mysql索引类型normal,unique,full text的区别是什么?

17. 事务的特性

事务的特性:
A:原子性(Atomicity),原子性是指事务是一个不可分割的工作单位,事务中的操作,要么都发生,要么都不发生。
C:一致性(Consistency),在一个事务中,事务前后数据的完整性必须保持一致。
I:隔离性(Isolation),存在于多个事务中,事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
D:持久性(Durability),持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
18. 事务的隔离级别

为了解决以上隔离性引发的并发问题,数据库提供了事务的隔离机制。
19. 为什么不要使用长事务

20. 查询方法是否需要开启事务

若采用隔离级别是可重复读,如不开启事务,多次sql的查询的时间维度不同,如开启事务则能保证多条sql的结果集处于同一个时间维度。开启不开启具体看业务场景。
21. MySQL中什么情况适合建立索引,什么情况不适合建立索引

22.  为什么不建议使用Select *

23. 说说MySQL InnoDB事务的原理

InnoDB中事务靠ACID特性来保证
并通过四种读未提交、读已提交、可重复读和串行化四种事务隔离级别,来分别解决脏读、幻读、不可重复读问题。四种隔离级别从前往后安全级别越来越高,性能越来越低。
一般情况下,隔离级别采用读已提交(Oracle默认)或可重复读(MySQL默认),具体要根据业务使用场景判断。
关于隔离级别详细信息参考上面原文
24. 一条更新SQL的执行过程

更多技术干货,欢迎关注我!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4