MySQL面试

目录

①Mybatis中#{ }和${ }的区别?

②MySQL的事务隔离级别?

③讲讲MySQL的索引?

④InNoDB和MyIsam的区别?

⑤Join和Left Join的区别?

⑥SQL语句的执行流程?

⑦什么是最左前缀原则?

⑦MySQL的慢查询问题?

⑧为什么MySQL要用B+树作为索引?

⑨MySQL有哪些日志,分别有什么作用?

⑩什么是MySQL的ACID?以及ACID是如何保障的?

⑪先写BinLog还是先写RedoLog?什么是两阶段提交?

⑫MySQL中的锁?

⑬MVCC机制---多版本并发控制

⑭MySQL的事务隔离级别以及是如何解决脏读,不可重复读以及幻读的?

⑮MySQL主从集群?


①Mybatis中#{ }和${ }的区别?

答:首先#和$号都是Mybatis进行参数动态传递到Xml中的方式。二者的区别在于使用#号在SQL预编译是会将SQL语句中的参数表示为一个?号,然后进行参数的替换。而$号则不会进行预编译处理而是直接把参数拼接到SQL语句中。使用#号能有效防止SQL注入,即当用户输入密码的时候在后面加一个逻辑上永远为1的表达式,用$号去拼接到SQL语句中就会导致无论输入什么都是成功的,而#号的替换参数则可以防止。

②MySQL的事务隔离级别?

答:说到隔离级别首先要说到事务会发生的三大问题:脏读,不可重复读和幻读

脏读是一个事务读到了另外一个事务修改了但是还没提交的数据。

不可重复读就是一个事务先后读取同一条记录数据不同。

像幻读则是前后统计记录的数量不一样,就像产生了幻觉。

而MySQL为了解决这些并发问题就提出了事务的隔离级别,分为四种:Read Uncommitted(读未提交),Read Committed(读已提交),Repeatable Read(可重复读),Serializable(串行化)。隔离级别越高事务的并发度越低。

像读未提交,即事务还没提交其变更其他事务就可以看到,此隔离级别下三个问题都会发生。

读已提交,即一个事物提交之后其变更才能被其他事物看到,解决了脏读问题,但是还会发生不可重复读和幻读。

可重复读,即一个事物执行过程中看到的数据,一直跟事务启动的时候看到的数据是一致的,也是InNoDB默认的隔离级别解决了脏读和不可重复读的问题,但是还是可能会存在幻读的问题。而串行化就是事务完全是串行操作,就不会出现上面的并发问题,不可以并发修改,只能排队等待。

串行化:所有的事务串行执行,效率非常低。

③讲讲MySQL的索引?

答:首先索引是帮助mysql高效的去磁盘检索数据的一种数据结构。像索引分类的话主要有聚簇索引,非聚簇索引,主键索引,唯一索引和复合索引。像在mysql的InNoDB引擎中是通过B+树实现了索引和数据的存储。而为什么要使用索引主要是因为它大大提升了查询效率。但是索引也不是越多越好,像维护索引就要占用数据库资源以及占用磁盘的空间,而且当字段的重复值很多创建索引反而会降低性能。像使用索引的一些细节,像不满足最左前缀匹配原则,使用select*,索引列使用了函数或者计算,字符串不加引号可以查但是字段类型不同索引也会失效,like左边包含%,使用or关键字以及范围查询都会导致索引失效,所以使用索引的时候还是要注意一写细节问题才能最大程度利用好它。

④InNoDB和MyIsam的区别?

答:①首先就是数据与索引的存放位置不同,InNoDB的话索引和数据是存储在同一个文件中,而MyIsam的话会分成三个部分。

②这就导致MyIsam的根节点存的就是行数据的物理地址,而InNoDB的话又分为聚集索引和非聚集索引,非聚集索引的根节点上存的是主键,聚集索引的根节点上存的就是行数据。

③InNoDB支持事务和外键,MyIsam则不支持。

④InNoDB支持行锁和表锁,而MyIsam则不支持行锁。

⑤InNoDB必须要主键,而MyIsam就可以不用主键。

⑤Join和Left Join的区别?

答:①像Join的话或者叫Inner Join连接是连接两个表共有的行记录。而Left Join则是取左表全部的行记录去右表查与左表匹配的记录,没有匹配到的就是NULL。

⑥SQL语句的执行流程?

答:首先MySQL执行一条SQL语句需要经过连接器,查询缓存,解析器,预处理器,优化器和执行器六个步骤。

第一步:客户端与连接器建立连接,连接器校验用户名和密码。

第二步:登录成功之后,查询语句首先会去查询缓存,如果有数据命中的话就会直接把结果返回给连接器进而返回给客户端(但是在MySQL_8版本查询缓存已经删掉,因为如果涉及更新比较频繁的表,查询的命中率会很低,因为每次更新都会清空缓存)。

第三步:如果没有数据命中,就会将SQL语句提交给解析器,解析器就会把SQL语句进行词法分析和语法分析并且生成一棵语法树

第四步:之后会交给预处理器,预处理器会进行表名,字段名的校验,还会做一些像把select *的*号替换为字段名。

第五步:预处理之后会交给优化器,优化器会根据根据语法树选择出最优的执行计划然后交给执行。

第六步:执行器会调用相应的API去存储引擎检索数据,然后将查到的数据返回给执行器,执行器再把结果返回给连接器,最后返回给客户端。

⑦什么是最左前缀原则?

答:即当使用一个联合索引时,查询语句中的索引列必须从最左列开始,并且不跳过某一个索引列,如果跳跃了后面字段的索引全部失效。但是当全部列都出现时,并且使用的是=筛选条件时,其顺序可以不做要求,因为SQL的优化器会优化,选择执行效率最高的执行方案。

⑦MySQL的慢查询问题?

答:首先慢查询的话就是一条SQL语句执行的时间很长或者说超过慢查询的设置的阈值,我们通过慢查询日志找到这些语句之后就可以从这几个方面去分析: ①看是否有索引,如果没索引就可以添加索引。

②如果是建立了索引,但是通过explain发现没走索引,就去分析语句中是否某些地方导致索引失效,导致索引失效的场景:不满足最左匹配原则,使用or关键字(不是全部有索引),索引列上使用了计算或者聚合函数,使用了范围查询,使用了模糊查询(%在前面),字段类型不匹配,使用select*等操作。

③除此之外的话,还可以对SQL语句本身就行优化,像插入多条数据时使用批量插入或者大批量的话使用load,减少子查询,像update对索引列更新时where条件中如果没有索引或者索引失效的话,行锁会升级为表锁(会全表扫描)。尽量使用count*等操作进行优化。

⑧为什么MySQL要用B+树作为索引?

答:相比于普通查找树和二叉树的特点:

①B树和B+树都是一种多路平衡树,导致其整体高度比二叉树要矮也就是说的我们说的矮胖矮胖的,矮胖的特点呢就是减少了磁盘IO的次数,因为树是存储在磁盘中的,访问每个节点,都对应一次磁盘 I/O 操作,也就是说树的高度就等于每次查询数据时磁盘 IO 操作的次数,所以树的高度越高,就会影响查询性能。

相比于B树的特点:

②相比于B树在所有结点都存储数据与索引,B+树只在叶子结点才存储数据,非叶子节点只存索引;这样的特点就可以在同一高度下,B+树存储的数据要比B树多,并且非叶子节点只存储索引的结构也会加快查询,删除和新增的效率。

③并且B+树的叶子结点通过指针形成了一条双向链表,更有利用范围查询。而B树只能通过遍历的方式实现范围查询,非常不优雅。

但是也不是说B+树一定是最好的,而是要根据适合的场景去选择最合适的技术方案,像MongoDB中就是采取的就是B树。

⑨MySQL有哪些日志,分别有什么作用?

①错误日志(ErrorLog):记录了mysql中发生的严重错误的相关信息。

②二进制日志(BinLog):记录了所有的DDL(操作表)和DML(操作数据)语句,但是不包括查询语句。而且提供三种记录方式(Statement(记录SQL语句),Row(记录每一行的数据变更,默认方式),Mixed(混合两种))。主要用于数据恢复以及主从复制。

③中继日志(RelayLog):在从节点中记录同步过来的binlog数据。

④慢查询日志(SlowLog):记录执行时间超过设定时间的SQL语句。

⑤回滚日志(UndoLog):记录了数据的逻辑变化,比如说执行一条insert语句,undolog里就记录一条delete语句。同时也记录了数据的历史版本。主要是用来保证原子性和MVCC机制。

⑥重做日志(RedoLog):记录事务提交时数据页的物理修改。主要是用来保证持久性。

⑩什么是MySQL的ACID?以及ACID是如何保障的?

A:原子性:不可分割的最小操作单元,里面的所有操作要么都成功要么都失败

实现原理:Undolog的回滚实现

I:隔离性:事务在执行时相互隔离,互不干扰

实现原理:锁(写写)+MVCC机制(读写)

D:持久性:事务一旦提交

实现原理:Redolog中记录了数据修改的数据页,当更新数据后,Buffer Pool中的数据页就会被写进磁盘中,当这个过程发生了问题导致刷盘失败的话,此时就可以通过redolog去重新刷盘保证了数据的持久化。

C:一致性:保证了上面三个特性都被保证了之后,最核心的一致性也就达成了,无论事务的操作如何,数据库的所有数据都是一致且稳定的。

⑪先写BinLog还是先写RedoLog?什么是两阶段提交?

答:不管是直接的先写binlog还是先写redolog都是会造成数据不一致的情况发生。

          

两阶段提交:首先将redolog写了,然后将其标为prepare状态。就算binlog没写,数据恢复时检查到redolog的状态为prepare并且在binlog中找不到对应的数据,就会抛弃掉redolog这一条数据。当binlog也写了之后,进行数据恢复时,可以找到binlog中相同的一条数据,把redolog状态改为commit,就都可以进行恢复,这样保证了数据的一致性。

⑫MySQL中的锁?

  答:按照锁的粒度可分为:全局锁(一般用于数据库备份),表级锁,行级锁。

表级锁又可以分为:①表锁(表共享读,表独占写)。②元数据锁,开启事务或者操作数据库时不可以同时允许修改表的结构。③意向锁。

行级锁又可以分为:①行锁(共享锁,排他锁)。②间隙锁。③临键锁

乐观锁:认为操作数据的时候没有并发问题,所以就不加锁,但是在更新数据的时候一般通过CAS的方法去判断一下是否被别的线程修改。适用于写少读多的场景下。

悲观锁:认为操作数据的时候一定会有并发问题,所以就每次操作都会上锁,阻塞其他线程的访问。适用于写多读少的场景下。

⑬MVCC机制---多版本并发控制

答:当前读:select语句后面有for update。读取最新的版本。

快照读:普通的select语句。读取到的不一定是最新的版本。

MVCC基于三大部分:

①隐藏字段(上次事务修改的ID,指向上一版本的指针,隐藏主键)

②undolog,前面说过undolog中不仅存储了相反的SQL语句,还存储了行数据的版本链用于快照读

③ReadView:去决定快照读到底读哪个版本

MVCC工作流程:

在RC隔离级别下:每次快照读都产生一个ReadView,要判断当前事务到底读取哪个版本,就是跟着undolog中的版本链,去逐个把版本链中的事务ID拿出来与Readview中的四条规则去比对,哪个满足规则就是读哪个版本。实际上RC下的MVCC就是去找最近提交事务的那个版本。因此解决了脏读的问题。

在RR隔离级别下:仅在第一次快照读产生一个ReadView,之后都共享这个ReadView。执行流程与RC的一致也是一个个去比较。因此解决了可重复读的问题。

而对于当前读则是采用临键锁(行锁+间隙锁)

⑭MySQL的事务隔离级别以及是如何解决脏读,不可重复读以及幻读的?

⑮MySQL主从集群?

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值