暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL高频面试题(2)

双非进大厂 2021-07-30
278



MySQL向来是大厂面试的必考题


从索引,到锁,再到主从、容灾,等等


而且挖得很深


让我们走进MySQL的世界


我会带你刷遍MySQL高频面试题


让你在面试中能够侃侃而谈



双非进大厂


EXPERIENCE

事务的特性



ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)



原子性(Atomicity)


原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。



一致性(Consistency)


事务前后数据的完整性必须保持一致。包括但不限于用户自定义完整性(如转账前后,两个账户余额的和应该不变)等



隔离性(Isolation)


事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。



持久性(Durability)


持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。





EXPERIENCE

事务的隔离级别



数据库事务的隔离级别有4种,由低到高分别是:Read uncommitted、Read committed、Repeatablead、Serializable。



事物的并发操作中可能出现脏读、不可重复读、幻读。


下面介绍的是MySQL/InnoDB是如何定义这4种隔离级别的,而不是数据库理论中的。




Read uncommitted


读 未提交,就是一个事务可以读取另一个未提交事务的数据。


e.g.

老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。


分析:

实际程序员这个月工资还是3.6万,但是程序员看到的是3.9万,他看到的是老板没提交事物的数据。就是脏读。


解决方法:Read commited读已提交,能解决脏读问题。



Read committed


读 已提交,就是事务要等另一个事物提交后才能读取数据.


e.g.

程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他买单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…


分析:

这就是读已提交,若有事务对数据进行更新(UPDATE)操作时,读操作事物要等这个更新操作事物提交才能读取数据,可以解决脏读问题。但在这个示例中,出现了一个事物范围内两个相同的查询却返回了不同数据,这就是不可重复读。


解决方法:Repeatable read



Repeatable read


可重复读,就是在开始读取数据(事物开启)时,不再允许修改操作。MySQL是这一级别。


e.g.

程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。


分析:

重复读可以解决不可重复读问题。写到这里,应该明白一点就是,不可重复读对应的是修改 UPDATE操作。但是可能会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。


什么时候出现幻读?


e.g.

程序员某一天消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事物开启),看到确实是花了2千元,就在这个时候,程序员花了1万元买了一台电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子提交事务),发现花了1.2万元,似乎出现了幻读,就是幻读。


解决:Serializable



Serializable序列化


Serializable是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读,不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不用。



如果是找实习,了解到这些就够用了。但如果是校招,面试官有可能会追问,我们使用InnoDB引擎的MySQL,在RR隔离级别下,还会存在幻读么?


其实是不存在的,大致是用间隙锁解决了幻读。


间隙锁的英文名称是GAP锁,锁定一个范围,但不包括记录本身。


GAP锁的目的,是为了防止幻读、防止间隙内有新数据插入、防止已存在的数据更新为间隙内的数据。


我们把间隙锁和行锁合称为Next-Key Lock,锁定一个范围,并且锁定记录本身,用来解决幻读。


我在最早学这里的时候是比较懵逼的,所以我估计大家其实还是没有看懂,所以我再解释一下。


所谓幻读,就是同一个事务,连续做两次当前读(简单解释一下当前读,就是读的是最新版本数据,而不是读快照) 。


例如:select * from t1 where id = 10 for update;


那么这两次当前读返回的是完全相同的记录 (记录数量一致,记录本身也一致),第二次的当前读,不会比第一次返回更多的记录 (幻象)。


如何保证两次当前读返回一致的记录呢,那就需要在第一次当前读与第二次当前读之间,其他的事务不会插入新的满足条件的记录并提交。


举个栗子,delete from t1 where id = 10,且id是非唯一索引。



图中的[6,c]与[10,b]间,[10,b]与[10,d]间,[10,d]与[11,f]间,不会插入新的满足条件的记录。


MySQL选择了用GAP锁,将这三个GAP给锁了起来。






EXPERIENCE

InnoDB和MyISAM的区别



  1. InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;


  2. InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败; 


  3. InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。


  4. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快。


  5. InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。


我们在选择的时候,除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。目前引擎默认是InnoDB,以前是MyISAM。





今天主要介绍了事务的特性和四种隔离方式,其中着重讲了下有助于提升B格的间隙锁。下次会讲一讲索引的各种面试题,瑞思拜~






“2021年会更好的”

“点个关注,为您分享更多的双非进大厂经验”



【文案】:小洋人

【校验】:小雨






点个在看 你最好看




文章转载自双非进大厂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论