1、MySQL的索引有了解吗?(重点掌握)
索引的核心思想是分治,是对数据库数据排序分页后,存储每页第一个数据部分字段信息一种结构,利用索引可以快速的访问到页面,然后根据页目录找到数据。InnoDB索引的存储数据结构是B+树来实现的。
(1)“为什么底层数据结构使用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适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
InnoDB适合:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且行锁定的机会比较大的情况。
总结:
最主要的区别就是MyISAM表不支持事务、不支持行级锁、不支持外键。 InnoDB表支持事务、支持行级锁、支持外键。
解析:
对MySQL的存储引擎的考察也是一个几乎必考的知识点,为了让大家对存储引擎有一个更好的了解,我们先来看下MySQL的基本逻辑架构图,从整体上了解下MySQL包括哪些逻辑架构。
由MySQL的逻辑架构图我们可以看出,逻辑架构包括Server层和存储引擎层。其中Server层包括连接器,分析器,优化器以及执行器;存储引擎层包括多种支持的存储引擎。各个逻辑部件的作用如下:
除了InnoDB以及MyISAM存储引擎外,常见的考察存储引擎还有Memory,使用Memory作为存储引擎的表也可以叫做内存表,将数据存储在了内存中,所以适合做临时表来使用,在索引结构上支持B+树索引和Hash索引。
3、MySQL中where、group by、having关键字?
答:这三个MySQL关键字作用可以总结如下:
having和where的区别:
当同时含有where子句、group by 子句 、having子句及聚集函数时,执行顺序如下:
4、MySQL的日志模块binlog和redo log有了解吗?
答:在MySQL的使用中,更新操作也是很频繁的,如果每一次更新操作都根据条件找到对应的记录,然后将记录更新,再写回磁盘,那么IO成本以及查找记录的成本都很高。所以,出现了日志模块,即我们的update更新操作是先写日志,在合适的时间才会去写磁盘,日志更新完毕就将执行结果返回给了客户端。
MySQL中的日志模块主要有redo log(重做日志)和binlog(归档日志)。
redo log是InnoDB引擎特有的日志模块,redo log是物理日志,记录了某个数据页上做了哪些修改。InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么redo log总共就可以记录 4GB的操作。从头开始写,写到末尾就又回到开头循环写。
InnoDB的redo log保证了数据库发生异常重启之后,之前提交的记录不会丢失,这个能力称为crash-safe。
binlog是Server层自带的日志模块,binlog是逻辑日志,记录本次修改的原始逻辑,说白了就是SQL语句。binlog是追加写的形式,可以写多个文件,不会覆盖之前的日志。通过mysqlbinlog可以解析查看binlog日志。binlog日志文件的格式:statement,row,mixed。
业界目前推荐使用的是 row 模式,因为很多情况下对准确性的要求是排在第一位的。
解析:
MySQL的日志模块属于有点深度的知识点,在校招面试中考察不深,我们仅仅对这部分知识有个初步的认识和了解,就足以在面试中留下好印象并且获得加分。
在更新数据库的时候,通过redo log和binlog的两阶段提交,可以确保数据库异常崩溃之后数据的正确恢复。
在对数据库误操作之后,可以通过备份库+binlog可以将数据库状态恢复到“任意“时刻。
(1)为什么MySQL会突然变慢一下?
当内存数据页和磁盘数据页内容不一致的时候,这个内存页就是“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,这个时候的内存页就是”干净页“。
前面我们介绍了更新数据库的时候是先写日志,当合适的机会(空闲)出现的时候才会更新磁盘。但是当redo log 写满了,要 flush 脏页,也就是把内存里的数据写入磁盘,会导致MySQL执行速度突然变慢一瞬间。
5、MySQL事务有哪些特性?(重点掌握)
答:事务是单个逻辑工作单元执行的一系列操作,是一个不可分割的工作单位。满足如下的四大特性:
解析:
MySQL事务又是一个几乎必考的MySQL知识点,可以拓展的知识点较多,我们一起来接着看如下的考察点。
(1)“如果不做控制,多个事务并发操作数据库会产生哪些问题吗?“
两个不同事务同时获得相同数据,然后在各自事务中同时修改了该数据,那么先提交的事务更新会被后提交事务的更新给覆盖掉,这种情况先提交的事务所做的更新就被覆盖,导致数据更新丢失。
注意:幻读是指一种结构上的改变,比如说条数发生了改变;不可重复读是指读出的数值发生了改变。
(2)“MySQL数据库事务的隔离级别有哪些?“
为了避免数据库事务操作中的问题,MySQL定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。
事务的隔离级别越高,对数据的完整性和一致性保证越佳,但是对并发操作的影响也越大。MySQL事务默认隔离级别是可重复读。
6、MySQL中的锁机制?(重点掌握)
(1)MySQL中的死锁
MySQL中的死锁主要是多个事务使用行级锁对某行数据加锁造成的,上一小节说了MyISAM不支持行级锁,所以MySQL中的死锁主要是在说InnoDB存储引擎的死锁。
那么MySQL的死锁该如何解决呢?
我们可以在业务上和数据库设置上来解决MySQL死锁。分别介绍如下:
业务逻辑上的死锁解决方案:
数据库的设置来解决死锁:
(2)“行级锁什么时候会锁住整个表?“
InnoDB行级锁是通过锁索引记录实现的,如果更新的列没建索引是会锁住整个表的。
悲观锁与乐观锁:
从程序员的角度看,数据库中的锁又可以分为悲观锁和乐观锁。
悲观锁:利用数据库的锁机制实现,在整个数据处理过程中都加入了锁,以保持排他性。
乐观锁:乐观锁可以利用CAS实现,在操作数据的时候进行一个比较,按照当前事务中的数据和数据库表中的该数据是否一致来决定是否要执行本次操作。
(3)“乐观锁的ABA问题有了解吗?如何解决?“
ABA问题是指在当前事务读取该行数据时是A,经过别的事务修改成B,但是在当前事务要更新数据的时候,该行数据又被别的事务修改为A,事实上数据行是发生过改变的,存在并发问题。
ABA问题可以通过基于数据版本(Version)记录机制来解决。也就是为数据增加一个版本标识。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。根据当前事务的数据版本号和数据库中数据的版本号对比来决定是否更新数据。
与给当前数据增加一个数据版本类似,我们也可以增加基于时间戳机制来解决ABA问题,通过时间戳来记录当前数据行变化。
(4)有SQL优化或者MySQL故障排查经历吗?
一般情况下,我们遇到一个SQL异常的时候,比如说执行时间超时等,可以通过explain查看当前SQL语句的执行情况。explain +SQL语句可以查看当前的SQL语句使用的索引以及其扫描了多少行数据。也可以使用下边的语句来查看数据表的一些信息:
查看了数据表的信息,一般情况下我们可以通过建立索引来提高查询速度,或者修改SQL语句,利用索引下推或者最左前缀原则等来加快查询速度。
7、MySQL建表的约束条件有哪些?
答:约束条件是我们建表的时候对数据库表做的一个限制条件。MySQL建表时候一般有如下的五个约束条件:
8、MySQL其余知识点?
限于文章篇幅,我们一起MySQL中的重要的大块知识点进行了一个交流与学习。还有一个比较细小或者进阶的重要知识点。这里我们做一个简单的罗列吧。常见的MySQL知识点如下: