MySQL常见面试概念理解

1. MySQL有哪些引擎?

其实有很多引擎,但是我们平常就知道InnoDB和MyISAM就足够了

1.1 InnoDB和MyISAM的区别

InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据(第一步在辅助索引B+树中检索属性值,到达其叶子节点获取对应的主键;第二步使用主键在主索引B+树种再执行一次B+树检索操作回表】)。因此,主键不应该过大,因为主键太大,其他索引也都会很大。

MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。

下面的图表示一张表中InnoDB和MyISAM的主键索引和辅助索引的结构:

MySQL常见面试概念理解_第1张图片

MySQL常见面试概念理解_第2张图片

1.2 总结

事务、锁、外键支持

  • InnoDB支持事务,MyISAM不支持事务
  • InnoDB的key是索引,value是数据本身,支持表锁和行锁;MyISAM的key值是索引,value是数据的指针,只支持表锁
    • 只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁
  • InnoDB支持外键,MyISAM不支持
    MySQL常见面试概念理解_第3张图片

2.行锁,表锁

InnoDB行锁是通过给索引加锁来实现的,如果没有索引,InnoDB会通过隐藏的聚簇索引来对记录进行加锁(全表扫描,也就是表锁)。

  1. InnoDB 支持表锁和行锁,使用索引作为检索条件修改数据时采用行锁,否则采用表锁。
  2. InnoDB 自动给修改操作加锁,给查询操作不自动加锁
  3. 行锁可能因为未使用索引而升级为表锁,所以除了检查索引是否创建的同时,也需要通过explain执行计划查询索引是否被实际使用。
  4. 行锁相对于表锁来说,优势在于高并发场景下表现更突出,毕竟锁的粒度小。
  5. 当表的大部分数据需要被修改,或者是多表复杂关联查询时,建议使用表锁优于行锁。
  6. 为了保证数据的一致完整性,任何一个数据库都存在锁定机制。锁定机制的优劣直接影响到一个数据库的并发处理能力和性能。

3.事务的4种隔离级别

3.1事务的常见问题

脏读(Dirty Reads)
原因:事务A读取了事务B已经修改但尚未提交的数据。若事务B回滚数据,事务A的数据存在不一致性的问题。

不可重复读(Non-Repeatable Reads)
原因:事务A第一次读取最初数据,第二次读取事务B已经提交的修改或删除数据。导致两次读取数据不一致。不符合事务的隔离性。

幻读(Phantom Reads)
原因:事务A根据相同条件第二次查询到事务B提交的新增数据,两次数据结果集不一致。不符合事务的隔离性。

幻读和脏读有点类似
脏读是事务B里面修改了数据,
幻读是事务B里面新增了数据。

3.2事务的隔离级别

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大。这是因为事务隔离实质上是将事务在一定程度上"串行"进行,这显然与"并发"是矛盾的。根据自己的业务逻辑,权衡能接受的最大副作用。从而平衡了"隔离" 和 "并发"的问题。MySQL默认隔离级别是可重复读。
脏读,不可重复读,幻读,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。

  1. read uncommitted:可以看到未提交的数据(脏读),举个例子:别人说的话你都相信了,但是可能他只是说说,并不实际做。
  2. read committed:读取提交的数据。但是,可能多次读取的数据结果不一致(不可重复读,幻读)。用读写的观点就是:读取的行数据,可以写。
  3. repeatable read(MySQL默认隔离级别):可以重复读取,但有幻读。读写观点:读取的数据行不可写,但是可以往表中新增数据。在MySQL中,其他事务新增的数据,看不到,不会产生幻读。采用多版本并发控制(MVCC)机制解决幻读问题。
  4. serializable:可读,不可写。像java中的锁,写数据必须等待另一个事务结束。
隔离级别 读数据一致性 脏读 不可重复读 幻读
未提交读(Read uncommitted) 最低级别
已提交读(Read committed) 语句级
可重复读(Repeatable read) 事务级
可序列化(Serializable) 最高级别,事务级

3.2InnoDB是如何保持ACID的?

  • Redo Log 实现持久性
  • Undo Log 实现原子性
  • 二阶段提交 实现一致性
  • 二阶段提交 实现一致性

3.3Redo Log和Undo Log

4.MySQL的索引

4.1类型

MySQL常见面试概念理解_第4张图片

  • 主键索引:主键是一种唯一性索引,每个表只能有一个主键,在单表查询中,PRIMARY主键索引UNIQUE唯一索引的检索效率并没有多大的区别,但在关联查询中,PRIMARY主键索引的检索速度要高于UNIQUE唯一索引。
  • 普通索引:这是最基本的索引类型,而且它没有唯一性之类的限制。
  • 唯一索引:这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一
  • 全文索引:
    • MySql从3.23版开始支持全文索引和全文检索。全文索引只可以在VARCHAR或者TEXT类型的列上创建
    • 对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。
  • 组合索引:在索引的创建中,有两种场景,即为单列索引和多列索引

4.2聚簇索引和非聚簇索引

InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,聚簇索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,也将聚集索引的叶子节点称为数据页。这个特性决定了索引组织表中数据也是索引的一部分

一般建表会用一个自增主键做聚簇索引,没有的话MySQL会默认创建,但是这个主键如果更改代价较高,故建表时要考虑自增ID不能频繁update这点

我们日常工作中,根据实际情况自行添加的索引都是辅助索引,辅助索引就是一个为了需找主键索引的二级索引,现在找到主键索引再通过主键索引找数据(简称回表);

4.3提到回表,怎么避免回表?

可以用索引覆盖来避免回表的发生

我们知道MySQL的B+Tree索引是用我们字段的数据来建立索引的,比如说我们的主键id字段,就是用所有的id来组织这颗索引树,如果我们再对name字段建立索引的话,这个二级索引就是用name字段的数据来组织这颗索引树。那么问题就来了,我们知道对于二级索引而言他的叶子节点存储了对应数据行的id,也就是说最后我们的查询还是要通过主键id来进行查询获取数据。如果我们只需要name这个字段呢?比如说 select name from table where name>‘aaa’; 我们这个二级索引上保存了的name字段的所有数据,那么就没有必要再通过id去访问数据行了,直接从索引上获取数据即可。称之为覆盖索引,有的也翻译为索引覆盖。

explain判断是否覆盖索引

我们可以通过expalin来判断查询是否覆盖索引,主要看extra字段是否有 using index 。

4.4扩展阅读——索引下推

索引下推主要针对联合索引

对于user_table表,我们现在有(username,age)联合索引
如果现在有一个需求,查出名称中以“张”开头且年龄小于等于10的用户信息,语句C如下:"select * from user_table where username like '张%' and age > 10"
语句C有两种执行可能:
1、根据(username,age)联合索引查询所有满足名称以“张”开头的索引,然后回表查询出相应的全行数据,然后再筛选出满足年龄小于等于10的用户数据。过程如下图。

MySQL常见面试概念理解_第5张图片

2、根据(username,age)联合索引查询所有满足名称以“张”开头的索引,然后直接再筛选出年龄小于等于10的索引,之后再回表查询全行数据。过程如下图。

MySQL常见面试概念理解_第6张图片

明显的,第二种方式需要回表查询的全行数据比较少,这就是mysql的索引下推。mysql默认启用索引下推,我们也可以通过修改系统变量optimizer_switch的index_condition_pushdown标志来控制

SET optimizer_switch = 'index_condition_pushdown=off';
  1. innodb引擎的表,索引下推只能用于二级索引。
  2. 索引下推一般可用于所求查询字段(select列)不是/不全是联合索引的字段,查询条件为多条件查询且查询条件子句(where/order by)字段全是联合索引。

4.5最左匹配原则

联合索引遵从最左匹配原则,既对a,b,c3列做联合索引,对它进行select语句的时候,如果条件是a,a|b,a|b|c,a|c的话,才会使用这个联合索引进行匹配,否则,会按照无索引或其他的索引进行匹配

引用

MySQL 表锁和行锁机制
查询mysql事务隔离级别
MySQL行锁和表锁的含义及区别
MySQL系列-优化之覆盖索引
mysql索引篇之覆盖索引、联合索引、索引下推
mysql索引最左匹配原则的理解
MyISAM与InnoDB 的区别(9个不同点)

你可能感兴趣的:(面试专题,SQL)