[ 面试-干货 ] MySQL基础到高级面试

681 阅读6分钟

这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战

image.png

微信公众号搜索 程序媛小庄 人生苦短 一起学Python

前情提要

小庄经历了一面之后,被问到了Redis相关的一些问题,终于等到下一位面试官前来,只见一个神采奕奕绝顶聪明的面试官进来,估计会问一些MySQL相关的知识吧?

面试开始...

面试官大佬:上个面试官临时有事,自我介绍就不用了,和前俩面试官大概了解了一下情况,基础还不错,我呢就问一问MySQL相关的知识好吧!

我:好的,您问就好。

面试官大佬:MySQL建立索引的规范晓得不?

我:在创建表的时候一定要有主键列,可以为为经常需要where group by order by操作的字段增加索引,但是尽量不要在经常更新值的列上建索引,可能会引起索引失效,在创建辅助索引的时候需要按照业务需求创建索引并不是索引越多越好,如果冗余索引过多,表数据变化的时候很有可能会导致索引频繁更新,可能会导致很多正常的业务更新的请求。

面试官大佬:(可以呀,小伙子说的不错)既然你说到辅助索引了,那你能大概说说索引的一些你知道的知识吗?

我:索引具体来讲类似于书的目录,能够帮助快速找到所需要行的数据,起到优化查询的功能。一般分为聚簇索引和辅助索引。

聚簇索引属于B树结构,构建聚簇索引时,需要在创建表的时候指定主键列,MySQL的innodb引擎会将主键列作为聚簇索引列,如果建表的时候没有指定主键列,innodb会自动选择唯一键的列,作为聚簇索引列,如果都没有的话innodb会生成隐藏聚簇索引,有了聚簇索引之后,插入的数据行会在同一个区内按照聚簇索引值的顺序有序的在磁盘中存储数据,当使用主键列作为查询条件的时候可以帮助快速的查找数据。

辅助索引,需要人为创建,主要的作用是优化使用非聚簇索引列之外作为条件的查询,是将主键值和辅助索引列值按照辅助索引列值进行排序构建辅助索引B树结构,当使用辅助索引作为查询条件的时候,会首先扫描辅助索引的B树,如果辅助索引不能完全覆盖查询结果就需要进行回表操作。辅助索引有单列索引和联合索引,在创建联合索引的时候,需要遵循最左原则,在构建辅助索引时生成支节点的时候只会将最左列作为支节点,在使用联合索引的时候也需要遵循最左原则,就是辅助索引是什么顺序在使用的时候就必须是什么顺序。在执行计划结果中的key_len可以评估一条语句中联合索引覆盖的长度。

面试官大佬:(不错不错)嗯嗯,说的挺全面的,在MySQL中有事务你知道的吧?简单说说MySQL的事务有什么特性?

我:MySQL中事务有四个特性,ACID,分别是原子性、一致性、隔离性和持久性。

原子性是指在一个事务工作单元中,所有标准的事务语句要么全成功,要么全回滚;

一致性是指事务发生前 发生中 发生后都应该保持数据一致;

隔离性是指MySQL支持多事务并发工作,一个事务工作的时候不能受到其他事务的影响;

持久性是指当事务提交执行成功之后,此次事务操作的所有数据都要永久保存。

面试官大佬:MySQL的事务隔离级别知道吗,简单说说?

我:事务隔离级别有四个级别,分别是读未提交、读已提交、可重复度和串行化。

读未提交是指一个事务可能会读到其他事务未提交的数据,也叫脏读;

读已提交是指同一个事务单元中,两次读取结果不一致,也叫不可重复读,不可重复读解决了脏读的问题,只会读取其他事务已经提交的数据。

可重复度是是MySQL innodb默认的隔离级别,在同一个事务单元中每次读取的结果都一样,解决了不可重复读的问题,但是可能出现幻读,幻读就是在一个事务单元中更新操作没有完成或者没有提交的情况下出现了别的事务插入的数据,为了解决幻读的问题加入了GAP锁和next-lock,GAP锁就是间隙锁,是普通辅助索引的范围锁,对存在的数据行使用行锁,对条件的范围使用间隙锁,比如一个事务执行set test num=20 where num <20没有提交;另一个事务想要插入num<20的数据就会阻塞住。

串行化可以解决上面所有的问题但是不利于事务的并发。

面试官大佬:稍微问一个深一点的问题,不了解也没关系哈,就是MySQL的主从复制有了解过吗

我:(还好准备了下)了解一些不多,主从复制主要是为了做读写分离的,目的就是为了提高数据库的并发性能。我就大概说一下主从复制的原理,如果有不对的地方还请您指正:

首先是从库先执行change master to ....命令,将binlog位置信息写入到master.info中,执行start slave(启动IO SQL线程);

然后从库通过IP PORT连接主库;

主库分配专用线程Dump专门和从库的IO线程进行通信;

从库首先通过mastet.info中获取复制起点,通过IO线程向主库请求新的binlog日志;

主库binlog_dump_thread线程截取日志返回给从库的IO线程,此时主库工作完成;

从库的IO线程将binlog最终写入到relay_log中,并将复制节点更新到master.info中,此时IO线程工作完成;

从库的SQL线程先读取relaylog.info获取上次执行到的位置点;

从库的SQL线程根据节点继续向后执行relay-log,再次更新relay_log.info

面试官大佬:(啥时候招进来这小伙子呢)可以可以,那个我就先问到这,后面可能会有其他的面试,你再准备准备,加油哦!

我:好的!您慢走,再见!