虾皮面试原题:深入探讨 MySQL 支持的存储引擎及 MyISAM 与 InnoDB 的关键区别与选择建议

今天我们来探讨一次在虾皮面试中遇到的 MySQL 面试问题。以下是面试题的内容:

  1. MySQL 支持哪些存储引擎?如何查看?默认使用哪个?
  2. 存储引擎是基于数据库还是表?
  3. MyISAM 和 InnoDB 之间的区别是什么?如何选择?

为了帮助准备面试以及复习 MySQL 知识点,我花了一个晚上认真解答这些问题,希望对你有所帮助。

随着秋招的临近,我也在不断更新面试真题,希望能为大家提供更多有用的信息。

MySQL 支持的存储引擎及其默认设置

MySQL 支持多种存储引擎,你可以通过执行 show engines 命令来查看 MySQL 当前支持的所有存储引擎。

查看存储引擎

从上图可以看到,MySQL 当前的默认存储引擎是 InnoDB。值得注意的是,在所有存储引擎中,只有 InnoDB 是事务性存储引擎,因此只有它支持事务功能。

我使用的 MySQL 版本是 8.x,注意不同的 MySQL 版本之间可能会存在差异。在 MySQL 5.5.5 之前,MyISAM 是默认存储引擎,而从 5.5.5 版本开始,InnoDB 成为默认选项。

你可以通过运行 select version() 命令来查看当前的 MySQL 版本。

mysql> select version();  
+-----------+  
| version() |  
+-----------+  
| 8.0.27    |  
+-----------+  
1 row in set (0.00 sec)  

此外,还可以执行 show variables like '%storage_engine%' 命令来直接查看 MySQL 当前的默认存储引擎。

查看当前存储引擎

如果你想查看某个特定表所使用的存储引擎,可以使用 show table status from db_name where name='table_name' 命令。

查看表的存储引擎

MySQL 存储引擎架构

MySQL 的存储引擎采用的是插件式架构,这意味着它支持多种存储引擎,并且可以为不同的数据库表指定不同的存储引擎以满足不同的需求。存储引擎是基于表的,而不是数据库的。

此外,用户还可以根据 MySQL 定义的存储引擎标准接口编写自定义的存储引擎。这些非官方的存储引擎被称为第三方存储引擎,而 InnoDB 开始时也是一个第三方存储引擎,后来因其卓越表现而被 Oracle 收购。

MyISAM 与 InnoDB 之间的区别

MyISAM 与 InnoDB 比较

在 MySQL 5.5 之前,MyISAM 是默认的存储引擎,曾经一度风光无限。尽管 MyISAM 的性能表现良好,且拥有不少特性(如全文索引、压缩及空间函数等),但它不支持事务和行级锁,最大缺陷在于异常崩溃后无法安全恢复。

下面是 MyISAM 和 InnoDB 之间的一些关键对比:

1. 行级锁支持

MyISAM 仅支持表级锁,而 InnoDB 则支持行级锁和表级锁,默认使用行级锁,这使得 InnoDB 在并发写入时表现更为出色。

2. 事务支持

MyISAM 不支持事务,而 InnoDB 完全支持事务,实现了 SQL 标准的四个隔离级别,并能进行提交和回滚操作。InnoDB 默认的 REPEATABLE-READ 隔离级别有效防止幻读问题的发生。

3. 外键支持

MyISAM 不支持外键,而 InnoDB 支持。外键在维护数据一致性方面极为重要,但可能会导致性能下降。通常建议在生产项目中尽量不使用外键,而是通过业务代码进行约束。

阿里的《Java 开发手册》明确禁止使用外键。

外键的使用

尽管代码约束对程序员的能力要求更高,但是否使用外键还是要根据实际项目需要做决定。

4. 崩溃后的安全恢复

MyISAM 不支持崩溃后的安全恢复,而 InnoDB 则能在异常崩溃后重新启动时保障数据库恢复到崩溃前的状态,回归这一过程依赖于 redo log

5. MVCC 支持

MyISAM 不支持 MVCC,而 InnoDB 支持。MVCC 可以看作是行级锁的升级版,能够有效减少加锁操作,提高性能。

6. 索引实现的差异

虽然两者都使用 B+Tree 作为索引结构,但实现方式有所不同。InnoDB 的数据文件本身就是索引文件,数据与索引是绑在一起的,而 MyISAM 的索引文件和数据文件是分开的。

如何选择 MyISAM 和 InnoDB?

大部分情况下,我们选择使用 InnoDB 存储引擎。在某些读密集型场景下,MyISAM 可能适合,但前提是项目能够接受 MyISAM 不支持事务和崩溃恢复的缺点。

正如《MySQL 高性能》中所言:“不要轻易相信‘MyISAM 比 InnoDB 快’这样的经验法则,这种结论往往不具绝对性。在许多已知场景中,InnoDB 的速度可以远超 MyISAM,尤其是在使用聚簇索引或所需数据可以放入内存的情况下。”

通常情况下,选择 InnoDB 是合适的。然而,如果项目对可扩展性和并发能力不敏感,同时也不需要事务支持或崩溃恢复,MyISAM 也是一个不错的选择。但在大多数情况下,我们都需要考虑这些因素。

因此,在日常开发的业务系统中,几乎没有理由再选择 MyISAM 作为 MySQL 数据库的存储引擎。