MySQL的一些高频面试题汇总(持续补充)

1.事务4大特性

事务4大特性:原子性、一致性、隔离性、持久性

  •  原⼦性:事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么全不执行

  • 一致性:执⾏事务前后,数据保持⼀致,多个事务对同⼀个数据读取的结果是相同的;

  • 隔离性:并发访问数据库时,⼀个⽤户的事务不被其他事务所⼲扰,各并发事务之间数据库是独⽴的;

  • 持久性:⼀个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发⽣故障也不应该对其有任何影响。

实现原理: MySQL的存储引擎InnoDB使用重做日志保证一致性与持久性,回滚日志保证原子性,使用各种锁来保证隔离性。

2.事务隔离级别

  • 读未提交:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。

  • 读已提交:允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣。

  • 可重复读:同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修改,可以阻⽌脏读和不可重复读,会有幻读。

  • 串行化:最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产生干扰。

实现原理 对于「读提交」和「可重复读」隔离级别的事务来说,它们是通过MVCC中的Read View 来实现的,它们的区别在于创建 Read View 的时机不同,大家可以把 Read View 理解成一个数据快照,就像相机拍照那样,定格某一时刻的风景。「读提交」隔离级别是在「每个语句执行前」都会重新生成一个 Read View,而「可重复读」隔离级别是「启动事务时」生成一个 Read View,然后整个事务期间都在用这个 Read View。

可重复读为什么没有解决幻读问题?

  • 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。

  • 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。但是没有完全避免幻读的问题,在某些场景下,同一个事务中有一个更新操作时,会修改read view中的trx_id列表倒是幻读;

 3.MySQL锁

InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁。

InnoDB按照不同的分类的锁:

  • 共享/排它锁(Shared and Exclusive Locks):行级别锁,

  • 意向锁(Intention Locks),表级别锁

  • 间隙锁(Gap Locks),锁定一个区间

  • 记录锁(Record Locks),锁定一个行记录

表级锁:(串行化) Mysql中锁定 粒度最大的一种锁,对当前操作的整张表加锁,实现简单 ,资源消耗也比较少,加锁快,不会出现死锁 。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。

行级锁:(RR、RC) Mysql中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。InnoDB支持的行级锁,包括如下几种:

  • 记录锁(Record Lock): 对索引项加锁,锁定符合条件的行。其他事务不能修改和删除加锁项;

  • 间隙锁(Gap Lock): 对索引项之间的“间隙”加锁,锁定记录的范围,不包含索引项本身,其他事务不能在锁范围内插入数据。

  • Next-key Lock:锁定索引项本身和索引范围。即Record Lock和Gap Lock的结合。可解决幻读问题。

InnoDB 支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,而意向锁就是其中的一种表锁。

  • 共享锁( shared lock, S )锁允许持有锁读取行的事务。加锁时将自己和子节点全加S锁,父节点直到表头全加IS锁

  • 排他锁( exclusive lock, X )锁允许持有锁修改行的事务。加锁时将自己和子节点全加X锁,父节点直到表头全加IX锁

  • 意向共享锁(intention shared lock, IS):事务有意向对表中的某些行加共享锁(S锁)

  • 意向排他锁(intention exclusive lock, IX):事务有意向对表中的某些行加排他锁(X锁)

 4.MVCC多版本并发控制

MVCC是一种多版本并发控制机制,通过事务的可见性看到自己预期的数据,能降低其系统开销。(RC和RR级别工作) InnoDB的MVCC,是通过在每行记录后面保存系统版本号(可以理解为事务的ID),每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID。这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的,防止幻读的产生。

1.MVCC手段只适用于Msyql隔离级别中的读已提交(Read committed)和可重复读(Repeatable Read).

2.Read uncommitted由于存在脏读,即能读到未提交事务的数据行,所以不适用MVCC.

3. 简单的select快照度不会加锁,删改及select for update等需要当前读的场景会加锁 原因是MVCC的创建版本和删除版本只要在事务提交后才会产生。客观上,mysql使用的是乐观锁的一整实现方式,就是每行都有版本号,保存时根据版本号决定是否成功。Innodb的MVCC使用到的快照存储在Undo日志中,该日志通过回滚指针把一个数据行所有快照连接起来。

5.索引为什么使用B+树

B+树的磁盘读写代价低,更少的查询次数,查询效率更加稳定,有利于对数据库的扫描

B+树是B树的升级版,B+树只有叶节点存放数据,其余节点用来索引。索引节点可以全部加入内存,增加查询效率,叶子节点可以做双向链表,从而提高范围查找的效率,增加的索引的范围。在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况。

所以,只要我们通过某种较好的树结构减少树的结构尽量减少树的高度,B树与B+树可以有多个子女,从几十到上千,可以降低树的高度。

6.聚簇索引和非聚簇索引 

  • 聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据(主键索引)

  • 非聚簇索引:将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置(辅助索引) 聚簇索引的叶子节点就是数据节点,而非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。

7.最左前缀问题

      最左前缀原则主要使用在联合索引中,联合索引的B+Tree是按照第一个关键字进行索引排列的。联合索引的底层是一颗B+树,只不过联合索引的B+树节点中存储的是键值。由于构建一棵B+树只能根据一个值来确定索引关系,所以数据库依赖联合索引最左的字段来构建。采用>、<等进行匹配都会导致后面的列无法走索引,因为通过以上方式匹配到的数据是不可知的。

8.回表查询和覆盖索引

普通索引(唯一索引+联合索引+全文索引)需要扫描两遍索引树

1.先通过普通索引定位到主键值id=5;

2.在通过聚集索引定位到行记录;这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。覆盖索引:如果where条件的列和返回的数据在一个索引中,那么不需要回查表,那么就叫覆盖索引。实现覆盖索引:常见的方法是,将被查询的字段,建立到联合索引里去。

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值