MySQL最全面试八股文

1.Mysql中事务的四大特性:

原子性(Atomicity)、一致性(Consistent)、隔离性(Isalotion)、持久性(Durable),简称为ACID。
​ 原子性:事务的原子性操作,对数据的操作要么全部成功,要么全部失败,实现事务的原子性是基于事务的Redo/Undoh机制。
​ 一致性:执行事务的前后状态一致,理解为数据的一致性。
​ 隔离性:事务之间互相隔离,不受影响,与事务的隔离级别有关。
​ 持久性:事务提交之后,事务的状态会被持久化到数据库中。

2.Redo/Undo机制:

Redo log: 可以用来恢复未写入数据库中但是事务已经成功提交的的数据。(某一时刻,我事务已经提交了,刚要写到数据库,结果数据库挂了,这时候数据库重启的时候就会通过Redo log来进行数据的恢复)
Undo log: 用来记录数据被修改前的值,主要用于事务执行失败后进行回滚。

3.事务的隔离级别:

1.读未提交(READ UNCOMMITTED)、产生脏读问题。
2.读提交 (READ COMMITTED)、解决了脏读的问题,出现了不可重复读,即在一个事务任意时刻读到的数据可能不一样,可能会受到其它事务对数据修改提交后的影响,一般是对于update的操作。
3.可重复读 (REPEATABLE READ)、解决了之前不可重复读和脏读的问题,但是由带来了幻读的问题,幻读一般是针对insert操作。
4.串行化 (SERIALIZABLE)

	#总结
		读未提交:允许读取尚未提交的数据变更。可能会导致脏读、幻读或不可重复读。
		读已提交:允许读取已经提交的数据。可能会导致幻读和不可重复读。
		可重复读:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改。可能会导致幻读。
		可串行化:最高隔离级别

		原子性:通过undolog实现。
		持久性:通过redolog实现。
		隔离性:通过加锁(当前读)&MVCC(快照读)实现。
		一致性:通过undolog、redolog、隔离性共同实现。

脏读问题: 开启一个事物A对数据进行了修改,而此次修改并没有提交到数据库中,这时另一个事务B也访问了这个数据,当且读到事务A修改后未提交的数据,叫做脏读。
不可重复读问题: 指在一个事务内,多次读同一数据,结果不一样。事务A开启了事务读取了一条数据,未提交事务,这时候,事务B也开启了事务,针对一条数据。
​ 并修改了这条数据,然后提交了事务,事务A再次读取这条数据的时候,产生了不一致的结果。

​ 举例:

时间A事务B事务
1开启事务A
2第一次读取一条数据:num=1000
3开启事务B
4读取同一条数据:num=1000,num+100
5num=1100,提交事务B
6第二次读取:num=1100,产生脏读

幻读: 是指当事务不是独立执行时发生的一种现象,例如第一个事务查询某个范围的数据行。同时,第二个事务新增、修改、删除这个范围的数据,导致结果不一致这个表中的数据,针对范围数据。
​ 这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
​ 例如:

时间A事务B事务
1开启事务A
2查询表中age=20的,共1000条:
3开启事务B
4向表中插入一条数据,age=20
5提交事务B
6第二次查询,变成了1001:产生幻读

​ 不可重复读的重点是修改:
​ 同样的条件,你读取过的数据,再次读取出来发现值不一样了
​ 幻读的重点在于新增或者删除:
​ 同样的条件,第 1 次和第 2 次读出来的记录数不一样

第一类丢失更新问题:
​ A事务撤销时,把已经提交的B事务的更新数据覆盖了。

例如:

时间A事务B事务
1开启事务A
2开启事务B
3查询数据num=1000
4查询数据num=1000
5修改:num+100
6num=1100,提交事务B
7修改:num-100
8修改失败,回滚事务。

​ 最终回滚的结果是num=1000,A事务的回滚造成了事务B提交的数据丢失了。

第二类丢失更新问题:
A事务覆盖B事务已经提交的数据,造成B事务所做的操作丢失

时间A事务B事务
1开启事务A
2开启事务B
3查询数据num=1000
4查询数据num=1000
5修改:num+100
6num=1100,提交事务B
7修改:num-100
8提交事务:num=900

​ 最终num的结果为900,A事务的提交覆盖了B事务,造成了B事务的数据丢失

数据库默认隔离级别:可重复读 (REPEATABLE READ)隔离级别越高,并发性越低

隔离级别脏读不可重复读幻读第一类更新丢失第二类更新丢失
读未提交×
读提交××
可重复读××××
串行化×××××
4.Mysql的锁机制:

​ InnoDB:只有行级别的锁和表级别的锁;

粒度划分:行锁、表锁

用法划分:乐观锁、悲观锁

类型/基本模式:排他锁、共享锁、意向锁、自增锁

算法:间隙锁、记录锁、插入意向锁、临键锁

1.共享锁:行锁

多个事务对于一个数据都可以共享同一把锁,都能访问到数据,只能读取,不能修改。
加锁方式
select * from user lock in share mode;
释放:
commit/rollback

2.排他锁:行锁

  又称为写锁,与其他锁不能共存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁,只有获取了排他锁的事务可以对改行数据进行读取和修改。
加锁方式:
自动:delete、update、insert
手动:select * from user where id=1 for update;

3.意向共享锁:表锁

意向锁是由数据引擎自己维护的,用户无法手动加锁。
表示事务正准备给数据加共享锁,也就是说加共享锁之前必须先给表加上意向共享锁。
一个事务想给一张表加表锁成功的前提是:没有其他任何事务锁定该表中的任意一行数据,
如果想给表加锁的话:就要全表扫描数据有没有被加锁,意向锁的出现,我们想给表加上标锁的话直接看这张表有没有意向锁。提高加表锁的效率。

4.意向排他锁:表锁

意向锁是由数据引擎自己维护的,用户无法手动加锁。
表示事务正准备给数据加排他锁,也就是说加排他锁之前必须先给表加上意向排他锁。

5.锁的作用

6.锁到底锁住了什么?

加行锁:没有索引的时候,锁定任何一行数据都会导致锁表。有索引的时候会锁住当前行

通过锁住索引来实现的。不管是通过二级索引加锁还是通过主键索引加锁,最终锁住的都是主键索引。

一张表中不可能没有索引

聚集索引:索引的逻辑顺序决定了数据存储的物理顺序。

1.primary key 优先使用主键索引

2.unique_key --not null 没有主键找一个非空的唯一字段

3._rowid 都不存在使用rowid

聚集索引-主键索引:完整的数据放到了B+树的叶子节点上

二级索引(辅助索引)-非聚集索引:存放的是主键索引的值,根据索引找到主键索引的值,再去主键索引的B+树上找具体数据

所有的辅助索引都要进行回表,二次查询操作。

在这里插入图片描述
7.记录锁、间隙锁、临键锁
N条记录,一定有 N+1个间隙,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
临键锁和共享锁不冲突,可重复获取。
间隙锁解决幻读问题。
临键锁左开右闭

隔离级别与锁
在这里插入图片描述
在这里插入图片描述

普通的select使用mvcc技术读取undolog中的快照数据
可重复读快照建立的时间:第一次读取的时候建立快照
读提交快照建立的时间:当前查询之前建立快照
所以可重复读解决了幻读,而读提交没有解决。

悲观锁:

每次获取到数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁
期间对该数据进行读写的其他线程都会进行等待 
适合写入操作比较频繁的场景

乐观锁:

每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁。
但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新;如果没有被修改,则进行数据更新
适合读取操作比较频繁的场景

5.Mysql的索引:

索引方式
索引MyISAM引擎InnoDB引擎Memory引擎
B-Tree索引支持支持支持
HASH索引不支持不支持支持
R-Tree索引支持不支持不支持
Full-text索引支持暂不支持(现在支持)不支持

1.BTREE:

​ 多路自平衡搜索树:Innodb的存储引擎以page为单位,page是管理磁盘的最小单位,默认16k,一个page中有多个磁盘,如果page中每个数据都有助于定位其它数据的位置,那么将会减少磁盘IO,加快效率,BTREE的出现就解决了这个问题,

2.B+TREE:

​ 对BTREE做了优化,减小了树的深度,减小了检索次数,提升效率,

具体区别不做赘述,可以研究下各种Tree的数据结构,

这个博文讲的BTREE和B+TREE就很详细:传送门

3.HASH :

​ hash是key—>value形式的数据结构,非常适合做索引,hash索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是Hash索引也有缺点。

​ 1.Hash 索引仅仅能满足"=",“IN"和”<=>"查询,不能使用范围查询;Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样。

​ 2.Hash 索引无法被用来避免数据的排序操作;由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;

​ 3.Hash 索引不能利用部分索引键查询;对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。

​ 4.Hash 索引在任何时候都不能避免表扫描;Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。

​ 5.Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高;对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下

4.FULLTEXT:

​ 全文索引的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。

​ 全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。

5.RTREE:

​ RTREE在mysql很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种,相对于BTREE,RTREE的优势在于范围查找

索引类型
  • 普通索引:仅加速查询

  • 唯一索引:加速查询 + 列值唯一(可以有null)

  • 主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个

  • 组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并

  • 全文索引:对文本的内容进行分词,进行搜索

人家菜鸟已经写的很好了,我就不瞎总结了:传送门

6.视图:

​ 视图是一个虚拟表,它可以像表一样进行curd操作,视图是虚拟表,本身不存储数据,而是按照指定的方式进行查询,其本质就是一条有名字的select语句:一到多张表的内容。视图的列来自于一个表或多个表,可以理解为一个复杂查询的sql语句设置了一个别名,所以视图不可以和表名重名,多用作查询,一般不会通过视图去修改数据。

​ 优点:限制数据库的访问,简化查询,数据独立性,对同一数据的不同体现。

创建视图 create view
例如:两个表的关联查询可以创建成一个视图	
create view view_test as(select s.id as id,s.name as name,g.age as age from user s,user_detail g where s.id=g.id);
视图运用
使用视图和使用表完全一样

修改视图 CREATE OR REPLACE VIEW

修改视图:
CREATE OR REPLACE VIEW view_test
AS
SELECT * FROM user_detail
WHERE age >= 18;
视图与数据变更

​ 源表的数据变化,数据中的数据也会变化

可以通过视图插入数据,但是只能基于一个基础表进行插入,不能跨表更新数据,不建议在视图更新数据。

如果在创建视图的时候制定了“WITH CHECK OPTION”,那么更新数据时不能插入或更新不符合视图限制条件的记录。

create view view_test as SELECT * FROM user_detail
WHERE age >= 18 WITH CHECK OPTION;

那么如果在视图中插入一条age=12的数据,会提示错误:CHECK OPTION FAILED,因为视图限制了视图大于等于18。

7.Mysql优化:

MySQL 常用30种SQL查询语句优化方法:

1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。可以在num上设置默认值0,确保表中num列没有null值。

4.尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,可以使用union all。

5.like匹配查询:%放前面会导致索引失效

6.in 和 not in 也要慎用,否则会导致全表扫描,对于连续的数值,能用 between 就不要用 in 了

7.如果在 where 子句中使用参数,也会导致全表扫描。 select id from t where num=@num

可以改为强制查询使用索引,select id from t with(index(索引名)) where num=@num

8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。

9.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

10.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使 用,

并且应尽可能的让字段顺序与索引顺序相一致。

11.很多时候用 exists 代替 in 是一个好的选择:

12.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,

视具体情况而定。一个表的索引数较好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。

13.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

14.避免频繁创建和删除临时表,以减少系统表资源的消耗。

MySQL优化常用方法:

  1. 选取最适用的字段属性
    表中字段的宽度设得尽可能小:char 的上限为 255 字节(固定占用空间),varchar 的上限 65535 字节(实际占用空间),text 的上限为 65535。
    尽量把字段设置为 NOT NULL,执行查询的时候,数据库不用去比较 NULL 值。

  2. 使用联合 (UNION) 来代替手动创建的临时表
    把需要使用临时表的两条或更多的 SELECT 查询合并的一个查询中。

  3. 使用索引
    查询语句当中包含有 MAX (), MIN () 和 ORDERBY 这些命令的时候,性能提高更为明显。
    索引应建立在那些将用于 JOIN, WHERE 判断和 ORDER BY 排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。

8.数据库三范式:

1.拆分到最细:

第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。

2.需要确保数据库表中的每一列都和主键相关,

比如订单表应该维护订单相关信息,商品信息应该是单独的商品信息表,

3.确保每列都和主键列直接相关,而不是间接相关

9.explain 执行计划的运用:

查询结果:
在这里插入图片描述

id:表示select查询的序列号,表示查询中执行select子句或操作表的顺序。
id的三种情况:
	1.id相同:从上到下依次执行
	2.id不同:按照id顺序执行
	3.id相同不同同时存在:

select_type:

SIMPLE:简单的select查询

PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY

SUBQUERY:在SELECTWHERE列表中包含了子查询

DERIVEDFROM列表中包含的子查询被标记为DERIVEDMySQL会递归执行这些子查询,把结果放在临时表中

UNION:若第二个SELECT出现在UNION之后,则被标记为UNION

UNION RESULT:从UNION表获取结果的SELECT

table:当前执行的表

type:type所显示的是查询使用了哪种类型,一般来说,得保证查询至少达到range级别,最好能达到ref

从最好到最差依次是:

system > const > eq_ref > ref > range > index > all

system 表只有一行记录

const 表示通过索引一次就找到了,const用于比较primary key 或者unique索引。因为只匹配一行数据,所以很快。如将主键置于where列表中,MySQL就能将该查询转换为一个常量。

例如:select * from user where id =1;

eq_ref 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。

ref 非唯一性索引扫描,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。

range 只检索给定范围的行,使用一个索引来选择行,key列显示使用了哪个索引,一般就是在你的where语句中出现between、<>、in等的查询,

这种范围扫描索引比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。

index Full Index ScanIndexAll区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据文件小。

(也就是说虽然all和Index都是读全表,但index是从索引中读取的,而all是从硬盘读取的)

all Full Table Scan 将遍历全表以找到匹配的行

possible_keys: 显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。

key: 实际使用的索引,如果为NULL,则没有使用索引。(可能原因包括没有建立索引或索引失效)。

key_len: 表示所引出长度,越短越好,该字段表示索引可能的最大长度,并不表示实际长度,key_len是根据表定义得出的,不是根据表内检索得出的。

ref: 显示索引的那一列呗使用了。

rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数,越少越好。

Extra:包含不适合在其他列中显式但十分重要的额外信息

Using filesort:mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索引完成的排序操作称为“文件排序”。

Using temporary:使用了用临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。

Using index:表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率不错。如果同时出现using where,表明索引被用来执行索引键值的查找;

如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。

Using where:表明使用了where过滤

Using join buffer: 表明使用了连接缓存,比如说在查询的时候,多表join的次数非常多,那么将配置文件中的缓冲区的join buffer调大一些。

impossible where: where子句的值总是false,不能用来获取任何元组

select tables optimized away:在没有GROUPBY子句的情况下,基于索引优化MIN/MAX操作或者对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,

查询执行计划生成的阶段即完成优化。

distinct:优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作

10.MyISAM与InnoDB 的区别:

1.InnoDB支持事务,MyISAM不支持。

2.InnoDB支持外键,MyISAM不支持,

3.InnoDB是簇聚索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的,MyISAM是非簇聚索引,也是用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。

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

5.Innodb不支持全文索引,而MyISAM支持全文索引,在涉及全文索引领域的查询效率上MyISAM速度更快高;PS5.7以后的InnoDB支持全文索引了.

6.MyISAM表格可以被压缩后进行查询操作.

7.InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁

8.InnoDB表必须有唯一索引(如主键)(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键),而Myisam可以没有

9.Innodb存储文件有frm、ibd,而Myisam是frm、MYDMYI

Innodb:frm是表定义文件,ibd是数据文件

Myisam:frm是表定义文件,myd是数据文件,myi是索引文件

  • 11
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面试官提出关于MySQL的问题时,你可以参考以下八股文回答: 1. MySQL是什么?有哪些特点? MySQL是一种开源的关系型数据库管理系统,具有以下特点:可靠性高、性能优秀、易于使用、跨平台、支持多种编程语言等。 2. 什么是数据库事务? 数据库事务是由一系列数据库操作组成的逻辑单位,它要么全部执行成功,要么全部失败回滚,以保证数据的一致性和完整性。 3. 请解释ACID是什么意思? ACID是数据库事务的四个特性: - 原子性(Atomicity):事务中的所有操作要么全部成功执行,要么全部回滚。 - 一致性(Consistency):事务执行前后,数据库从一个一致性状态转换到另一个一致性状态。 - 隔离性(Isolation):事务之间互不干扰,每个事务都感觉不到其他事务的存在。 - 持久性(Durability):事务成功提交后,对数据的修改将永久保存在数据库中。 4. 请解释索引在MySQL中的作用? 索引是一种数据结构,用于加速数据库的查询操作。它可以提高数据检索的效率,减少数据库的IO操作。 5. 请解释什么是主键、外键和唯一键? - 主键(Primary Key):用于唯一标识表中的每一行数据,不允许重复和NULL值。 - 外键(Foreign Key):用于建立表与表之间的关系,指向其他表的主键。 - 唯一键(Unique Key):保证该列的值在表中是唯一的,允许NULL值。 6. 请解释什么是数据库的范式? 数据库的范式是设计数据库时遵循的一组规范,用来减少冗余数据并提高数据的完整性。常见的范式有1NF、2NF、3NF等。 7. 请解释什么是数据库的连接(Join)操作? 连接操作用于将多个表中相关联的数据进行组合查询。常见的连接操作有内连接、外连接和交叉连接。 8. 请解释什么是数据库的备份和恢复? 数据库备份是指将数据库的数据和结构以某种方式复制到其他介质上,以便在数据丢失或损坏时进行恢复。数据库恢复是指在数据丢失或损坏后,通过备份文件中的数据恢复到原始状态。 以上是MySQL面试八股文的常见问题和回答。在面试中,除了准备这些基础知识外,还应该根据实际经验和项目经历进行深入的思考和回答。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值