MySQL 数据库面试题
一、SQL 语句
SQL 语句的使用需要慢慢积累,遇到不同的场景使用不同的 SQL,积累的多,慢慢就不难了。
1. 查询一个班级里,分数排名的前三位同学的名字和分数。
排序 order by + 分页查询 limit.
二、MySQL 索引
1. 索引是用来干什么的?
① 索引是对数据库表中一列或多列的值进行排序的一种结构。
② 索引可以大大提高的检索速度,也就是增删改查中的 " 查 " 。
③ 如果我们将数据库表比作成字典,将数据比作成字典中的内容,那么 " 索引 " 就是这些内容的 " 目录 "。
2. 索引的优缺点
(1) 索引的优点
① 索引大大减小了服务器需要扫描的数据量,从而加快了数据的查找速度,这也是创建索引的最主要的原因。
② 索引可以帮助服务器避免排序和创建临时表。
(2) 索引的缺点
① 索引需要占物理空间,创建出多个索引就占用了更多的空间。
② 由于索引本身需要维护,所以它拖慢了增、删、改的效率。
3. 索引的适用场合
索引适用于频繁查找数据的场合,不适用于频繁增、删、改的场合。
4. MySQL 背后的数据结构
(1) MySQL 索引的底层数据结构是 B+ 树。
(2) 阐明 B 树 和 B+ 树。
关键点: B+ 树的非叶子节点只存储索引,就像目录一样;其叶子节点只存储数据,就像字典中的内容一样。
① 因为 B+ 树的所有数据均存储在叶子节点,而且数据是按照顺序排列的,所以 B+ 树使得范围查找、区间查找、分组查找变得异常简单。
② B 树由于所有的节点既存放索引,又存放数据,所以使用 B 树查找时,数据可能在树的不同高度被找到,这使得 B 树查找不稳定。然而,B+ 树 所有的查询最终都落在叶子节点中,每次的查询磁盘 IO 次数都是差不多的,查询速度非常稳定。
③ 由于 B+ 树 的非叶子节点只存储了索引 (键值对) 信息,而没有数据,这就使得 B+ 树非叶子节点占用的空间较小,所有它就能够加载更多的索引。这也反应了 B+ 树比 B 树更加的 " 矮胖 ",所以磁盘 I/O 次数更少,查找速度更快。
三、MySQL 事务
1. 事务的基本特性
(1) 原子性 (Atomicity)
原子性又被称为不可分割性。
原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。如果事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。在 MySQL 数据库的操作中表示:要么将这个操作所用到的 SQL 全部执行完,要么一个 SQL 都不执行。
(2) 一致性 (Consistency)
一致性:在事务执行前后,数据库的完整性没有被破坏。这表示事务增删改查的数据必须完全符合所有的预设规则,即数据库中的数据都是合理合法的。
比方说:还是上面的转账的例子,事务需要遵循程序的规则,在不出现意外的情况下,小明给小红转了 200 元,那么小明就只能剩下 300 元,而小红的存款就必须得是 700 元。即事务执行前后,遵循数据严格的传输规则。
(3) 持久性 (Isolation)
持久性:一旦事务执行结束后,那么它对数据的增删改查就是永久的,即便系统故障也不会丢失。
(4) 隔离性 (Durability)
隔离性:数据库允许多个并发事务同时对其数据进行增删改查,隔离性可以防止多个事务并发执行时,而由于交叉执行所导致数据的不一致的情况。事务隔离分为不同级别,包括读未提交、读提交、可重复读和串行化。
2. 并发事务所产生的问题
(1) 脏读
脏读:事务A 读取到了 事务B 未提交保存的数据,之后 事务B 进行了回滚操作,从而导致 事务A 读取了一个不存在的脏数据。
(2) 不可重复读
不可重复读:在同一个事务中,同一个查询操作在不同的时间得到了不同的结果。
举个例子:在同一个事务中,同一个查询操作在 t1时刻、t2 时刻,得到了不同的结果,这是因为在 t1 和 t2 时刻之间,有另一个事务对数据进行了修改。
(3) 幻读
幻读:一个事务执行的过程中进行了多次查询,多次查询的结果都不一样,可能多了一行记录或少了一条记录,这种操作是一种特殊的不可重读读。
虽然幻读和不可重复读很像,但不可重复读侧重于数据修改,两次读取到的同一行数据不一样;而幻读侧重于添加或删除,两次查询的 MySQL 记录行数不同。
3. MySQL中事务的隔离级别
(1) 读未提交 (read uncommitted)
读未提交 (也叫未提交读):在该隔离级别中,事务A 可以读取到事务B 中未提交的数据。鉴于此,若 事务B 未提交的数据发生了回滚操作,那么 事务A 就直接读到了错误的数据,由此产生的问题称之为脏读。
也就是说,读未提交使得事务之间隔离级别最低,所以并发程度最高,但会引入脏读问题。进而引入不可重复读、幻读问题。
(2) 读已提交 (read committed)
读已提交 (也叫提交读):在该隔离级别中,事务能读取到已经提交事务的数据,因此它不会有脏读问题。然而鉴于此,一个事务在不同时间的相同 SQL 查询中,可能会得到数据内容不同的结果,这种问题称之为不可重复读。
也就是说,读已提交使得事务之间隔离级别依旧较低,所以并发程度也就较高,但它解决了脏读问题。引入不可重复读问题,进而引入了幻读问题。
(3) 可重复读 (repeatable read)
可重复读:MySQL 默认的事务隔离级别。 可重复读有效地解决了 " 不可重复读 " 的问题,但还存在幻读的问题。所谓的幻读指的是,在同一事务的不同时间使用相同 SQL 查询时,会产生不同的记录数目。
(3) 串行化 / 序列化 (serializable)
串行化:事务最高隔离级别。它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读和幻读问题。但其执行效率低,所以真正使用的场景并不多。
四、MySQL 存储引擎
InnoDB引擎 与 MyISAM引擎 的区别?
① InnoDB引擎是 MySQL 默认引擎,支持事务,而 MyISAM引擎 不支持。
② InnoDB引擎,支持行锁和表锁,而 MyISAM引擎 仅支持表锁,不支持行锁。
③ InnoDB引擎,支持外键 foreign keys,而 MyISAM引擎 不支持。