MySQL面试总结

1、MySQL的索引有了解吗?(重点掌握)

索引的核心思想是分治,是对数据库数据排序分页后,存储每页第一个数据部分字段信息一种结构,利用索引可以快速的访问到页面,然后根据页目录找到数据。InnoDB索引的存储数据结构是B+树来实现的。

(1)“为什么底层数据结构使用B+树,而不是B树?”

  • B+树是B树的变种,B+树的非叶子节点只用来保存索引,不存储数据,所有的数据都保存在叶子节点;而B树的非叶子节点也会保存数据。这样就使得B+树的查询效率更加稳定,均为从根节点到叶子节点的路径。
  • B+树的内部结点并没有指向关键字具体信息的指针,因此其内部结点相对B 树更小,同样空间可以读入更多的节点,所以B+树的磁盘读写代价更低

(2)聚簇索引和非聚簇索引有了解吗?
聚簇索引也称为主键索引,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。因为索引(目录)只能按照一种方法进行排序。但是如果没有主键,采用唯一索引,没有唯一会使用row_id

非聚簇索引(普通索引)的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。

(3) 回表

普通索引查询方式,则需要先搜索普通索引树,得到其对应的主键值,再到主键索引树搜索一次。这个过程称为回表。

(4) 覆盖索引

只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。

(5) 索引的最左前缀原则

在联合索引的情况下,不需要索引的全部定义,只要满足最左前缀,就可以利用索引来加快查询速度。这个最左前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符。最左前缀原则的利用也可以显著提高查询效率,是常见的MySQL性能优化手段。

(6) 索引下推

在MySQL5.6之前,只能从根据最左前缀查询到ID开始一个个回表。到主键索引上找出数据行,再对比字段值。MySQL5.6引入的索引下推优化,(联合索引前提)可以在索引遍历过程中,对索引中包含的其余字段先做判断,直接过滤掉不满足条件的记录,减少回表次数,提升查询效率。

(7)“哪些列上适合创建索引?创建索引有哪些开销?”

经常需要作为条件查询的列上适合创建索引,并且该列上也必须有一定的区分度。创建索引需要维护,在插入数据的时候会重新维护各个索引树(数据页的分裂与合并),对性能造成影响。

 

2、MySQL常见的存储引擎有哪些(重点掌握)?

答:MySQL中最常见的存储引擎有InnoDB和MyISAM,它们的主要区别如下:

  • MyISAM不支持事务;InnoDB是事务类型的存储引擎。
  • MyISAM只支持表级锁;InnoDB支持行级锁和表级锁,默认为行级锁。
  • MyISAM引擎不支持外键;InnoDB支持外键。
  • 对于count(*)查询来说MyISAM更有优势,因为其保存了行数。
  • InnoDB是为处理巨大数据量时的最大性能设计的存储引擎。
  • MyISAM支持全文索引(FULLTEXT);InnoDB不支持,5.6之后支持。

应用场景:

MyISAM适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。

InnoDB适合:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且行锁定的机会比较大的情况。

总结:

最主要的区别就是MyISAM表不支持事务、不支持行级锁、不支持外键。 InnoDB表支持事务、支持行级锁、支持外键。
 

解析:

对MySQL的存储引擎的考察也是一个几乎必考的知识点,为了让大家对存储引擎有一个更好的了解,我们先来看下MySQL的基本逻辑架构图,从整体上了解下MySQL包括哪些逻辑架构。

 

由MySQL的逻辑架构图我们可以看出,逻辑架构包括Server层和存储引擎层。其中Server层包括连接器,分析器,优化器以及执行器;存储引擎层包括多种支持的存储引擎。各个逻辑部件的作用如下:

  • 连接器:验证客户端权限,建立和断开MySQL连接
  • 分析器:进行SQL语句的语法分析
  • 优化器:选择索引,生成具体的SQL语句执行计划
  • 执行器:操作存储引擎,执行SQL,返回执行结果
  • 存储引擎层:各个不同的存储引擎都提供了一些读写接口来操作数据库

除了InnoDB以及MyISAM存储引擎外,常见的考察存储引擎还有Memory,使用Memory作为存储引擎的表也可以叫做内存表,将数据存储在了内存中,所以适合做临时表来使用,在索引结构上支持B+树索引和Hash索引。

 

3、MySQL中where、group by、having关键字?

答:这三个MySQL关键字作用可以总结如下:

  • where子句用来筛选from子句中指定的操作所产生的的行
  • group by 子句用来分组where子句的输出
  • having子句用来从分组的结果中筛选行

having和where的区别:

  • 语法类似,where搜索条件在进行分组操作之前应用;having搜索条件在进行分组操作之后应用
  • having可以包含聚合函数sum、avg、max等
  • having子句限制的是组,而不是行

当同时含有where子句、group by 子句 、having子句及聚集函数时,执行顺序如下:

  • 执行where子句查找符合条件的数据
  • 使用group by 子句对数据进行分组
  • 对group by 子句形成的组运行聚集函数计算每一组的值
  • 最后用having 子句去掉不符合条件的组

4、MySQL的日志模块binlog和redo log有了解吗?

答:在MySQL的使用中,更新操作也是很频繁的,如果每一次更新操作都根据条件找到对应的记录,然后将记录更新,再写回磁盘,那么IO成本以及查找记录的成本都很高。所以,出现了日志模块,即我们的update更新操作是先写日志,在合适的时间才会去写磁盘,日志更新完毕就将执行结果返回给了客户端。

MySQL中的日志模块主要有redo log(重做日志)和binlog(归档日志)。

redo log:

redo log是InnoDB引擎特有的日志模块,redo log是物理日志记录了某个数据页上做了哪些修改。InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么redo log总共就可以记录 4GB的操作。从头开始写,写到末尾就又回到开头循环写。

InnoDB的redo log保证了数据库发生异常重启之后,之前提交的记录不会丢失,这个能力称为crash-safe。

binlog:

binlog是Server层自带的日志模块,binlog是逻辑日志,记录本次修改的原始逻辑,说白了就是SQL语句。binlog是追加写的形式,可以写多个文件,不会覆盖之前的日志。通过mysqlbinlog可以解析查看binlog日志。binlog日志文件的格式:statement,row,mixed。

  • statement格式的binlog记录的是完整的SQL语句,优点是日志文件小,性能较好,缺点也很明显,那就是准确性差,遇到SQL语句中有now()等函数会导致不准确
  • row格式的binlog中记录的是数据行的实际数据的变更,优点就是数据记录准确,缺点就是日志文件较大。
  • mixed格式的binlog是前面两者的混合模式

业界目前推荐使用的是 row 模式,因为很多情况下对准确性的要求是排在第一位的。
 

解析:

MySQL的日志模块属于有点深度的知识点,在校招面试中考察不深,我们仅仅对这部分知识有个初步的认识和了解,就足以在面试中留下好印象并且获得加分。

在更新数据库的时候,通过redo log和binlog的两阶段提交,可以确保数据库异常崩溃之后数据的正确恢复。

在对数据库误操作之后,可以通过备份库+binlog可以将数据库状态恢复到“任意“时刻。

(1)为什么MySQL会突然变慢一下?

当内存数据页和磁盘数据页内容不一致的时候,这个内存页就是“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,这个时候的内存页就是”干净页“。

前面我们介绍了更新数据库的时候是先写日志,当合适的机会(空闲)出现的时候才会更新磁盘。但是当redo log 写满了,要 flush 脏页,也就是把内存里的数据写入磁盘,会导致MySQL执行速度突然变慢一瞬间。

5、MySQL事务有哪些特性?(重点掌握)

答:事务是单个逻辑工作单元执行的一系列操作,是一个不可分割的工作单位。满足如下的四大特性:

  • 原子性(Atomicity):事务作为一个整体被执行 ,要么全部执行,要么全部不执行;
  • 一致性(Consistency):保证数据库状态从一个一致状态转变为另一个一致状态;
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行;
  • 持久性(Durability):一个事务一旦提交,对数据库的修改应该永久保存

 

解析:

MySQL事务又是一个几乎必考的MySQL知识点,可以拓展的知识点较多,我们一起来接着看如下的考察点。
 

(1)“如果不做控制,多个事务并发操作数据库会产生哪些问题吗?“

  • 丢失更新:

两个不同事务同时获得相同数据,然后在各自事务中同时修改了该数据,那么先提交的事务更新会被后提交事务的更新给覆盖掉,这种情况先提交的事务所做的更新就被覆盖,导致数据更新丢失。

  • 脏读:
  • 不可重复读:一个事务在自己没有更新数据库数据的情况,同一个查询操作执行两次或多次得到的结果数值不同,因为别的事务更新了该数据,并且提交了事务。
  • 幻读:事务A读的时候读出了N条记录,事务B在事务A执行的过程中增加 了1条,事务A再读的时候就变成了N+1条,这种情况就叫做幻读。innodb使用临界锁解决幻读

注意:幻读是指一种结构上的改变,比如说条数发生了改变;不可重复读是指读出的数值发生了改变。
 

(2)“MySQL数据库事务的隔离级别有哪些?“

为了避免数据库事务操作中的问题,MySQL定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。

  • 读未提交(Read Uncommitted):存在脏读、不可重复读、幻读问题
  • 读已提交(Read Committed):存在不可重复读、幻读的问题,不存在脏读
  • 可重复读(Repeatable Read):存在幻读,不存在脏读、不可重复读问题。innodb,不存在幻读。
  • 序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。

事务的隔离级别越高,对数据的完整性和一致性保证越佳,但是对并发操作的影响也越大。MySQL事务默认隔离级别是可重复读。
 

6、MySQL中的锁机制?(重点掌握)

(1)MySQL中的死锁

MySQL中的死锁主要是多个事务使用行级锁对某行数据加锁造成的,上一小节说了MyISAM不支持行级锁,所以MySQL中的死锁主要是在说InnoDB存储引擎的死锁。

那么MySQL的死锁该如何解决呢?

我们可以在业务上和数据库设置上来解决MySQL死锁。分别介绍如下:

业务逻辑上的死锁解决方案:

  • 指定锁的获取顺序
  • 大事务拆分成各个小事务
  • 在同一个事务中,一次锁定尽量多的资源,减少死锁概率
  • 给表建立合适的索引以及降低事务的隔离级别等

数据库的设置来解决死锁:

  • 通过参数 innodb_lock_wait_timeout 根据实际业务场景来设置超时时间,InnoDB引擎默认值是50s。
  • 发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑(默认是开启状态)。

(2)“行级锁什么时候会锁住整个表?“

InnoDB行级锁是通过锁索引记录实现的,如果更新的列没建索引是会锁住整个表的。

悲观锁与乐观锁:

从程序员的角度看,数据库中的锁又可以分为悲观锁和乐观锁。

悲观锁:利用数据库的锁机制实现,在整个数据处理过程中都加入了锁,以保持排他性。

乐观锁:乐观锁可以利用CAS实现,在操作数据的时候进行一个比较,按照当前事务中的数据和数据库表中的该数据是否一致来决定是否要执行本次操作。

(3)“乐观锁的ABA问题有了解吗?如何解决?“

ABA问题是指在当前事务读取该行数据时是A,经过别的事务修改成B,但是在当前事务要更新数据的时候,该行数据又被别的事务修改为A,事实上数据行是发生过改变的,存在并发问题。

ABA问题可以通过基于数据版本(Version)记录机制来解决。也就是为数据增加一个版本标识。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。根据当前事务的数据版本号和数据库中数据的版本号对比来决定是否更新数据。

与给当前数据增加一个数据版本类似,我们也可以增加基于时间戳机制来解决ABA问题,通过时间戳来记录当前数据行变化。

(4)有SQL优化或者MySQL故障排查经历吗?

一般情况下,我们遇到一个SQL异常的时候,比如说执行时间超时等,可以通过explain查看当前SQL语句的执行情况。explain +SQL语句可以查看当前的SQL语句使用的索引以及其扫描了多少行数据。也可以使用下边的语句来查看数据表的一些信息:

  • show create table TableXX;查看当前表TableXX的建表语句
  • show index from TableXX;查看当前表TableXX上的索引

查看了数据表的信息,一般情况下我们可以通过建立索引来提高查询速度,或者修改SQL语句,利用索引下推或者最左前缀原则等来加快查询速度。

7、MySQL建表的约束条件有哪些?

答:约束条件是我们建表的时候对数据库表做的一个限制条件。MySQL建表时候一般有如下的五个约束条件:

  • 主键约束(Primay Key Coustraint) 唯一性,非空性
  • 唯一约束 (Unique Counstraint)唯一性,可以空,但只能有一个
  • 检查约束 (Check Counstraint) 对该列数据的范围、格式的限制
  • 默认约束 (Default Counstraint) 该数据的默认值
  • 外键约束 (Foreign Key Counstraint) 需要建立两表间的关系并引用主表的列

8、MySQL其余知识点?

限于文章篇幅,我们一起MySQL中的重要的大块知识点进行了一个交流与学习。还有一个比较细小或者进阶的重要知识点。这里我们做一个简单的罗列吧。常见的MySQL知识点如下:

  • limit分页查询使用方式
  • 主键自增长设置方式:auto_increment
  • SQL语句的优化有哪些?
  • order by是怎么工作的?
  • MVCC多版本并发控制以及undo log(回滚日志)。(加分项)
  • 分布式事务,两阶段,三阶段提交协议等。(加分项)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值