|
| 1 | +原文链接:https://javaguide.cn/database/mysql/mysql-questions-01.html |
| 2 | + |
| 3 | + |
| 4 | +## [MySQL 存储引擎](#mysql-存储引擎) |
| 5 | + |
| 6 | +MySQL 核心在于存储引擎,想要深入学习 MySQL,必定要深入研究 MySQL 存储引擎。 |
| 7 | + |
| 8 | +### [MySQL 支持哪些存储引擎?默认使用哪个?](#mysql-支持哪些存储引擎-默认使用哪个) |
| 9 | + |
| 10 | +MySQL 支持多种存储引擎,你可以通过 `SHOW ENGINES` 命令来查看 MySQL 支持的所有存储引擎。 |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | +查看 MySQL 提供的所有存储引擎 |
| 15 | + |
| 16 | +从上图我们可以查看出, MySQL 当前默认的存储引擎是 InnoDB。并且,所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。 |
| 17 | + |
| 18 | +我这里使用的 MySQL 版本是 8.x,不同的 MySQL 版本之间可能会有差别。 |
| 19 | + |
| 20 | +MySQL 5.5.5 之前,MyISAM 是 MySQL 的默认存储引擎。5.5.5 版本之后,InnoDB 是 MySQL 的默认存储引擎。 |
| 21 | + |
| 22 | +你可以通过 `SELECT VERSION()` 命令查看你的 MySQL 版本。 |
| 23 | + |
| 24 | + |
| 25 | + |
| 26 | +你也可以通过 `SHOW VARIABLES LIKE '%storage_engine%'` 命令直接查看 MySQL 当前默认的存储引擎。 |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +如果你想要深入了解每个存储引擎以及它们之间的区别,推荐你去阅读以下 MySQL 官方文档对应的介绍(面试不会问这么细,了解即可): |
| 31 | + |
| 32 | +- InnoDB 存储引擎详细介绍:https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html 。 |
| 33 | +- 其他存储引擎详细介绍:https://dev.mysql.com/doc/refman/8.0/en/storage-engines.html 。 |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +### [MySQL 存储引擎架构了解吗?](#mysql-存储引擎架构了解吗) |
| 38 | + |
| 39 | +MySQL 存储引擎采用的是 **插件式架构** ,支持多种存储引擎,我们甚至可以为不同的数据库表设置不同的存储引擎以适应不同场景的需要。**存储引擎是基于表的,而不是数据库。** |
| 40 | + |
| 41 | +下图展示了具有可插拔存储引擎的 MySQL 架构(): |
| 42 | + |
| 43 | + |
| 44 | + |
| 45 | +MySQL architecture diagram showing connectors, interfaces, pluggable storage engines, the file system with files and logs. |
| 46 | + |
| 47 | +你还可以根据 MySQL 定义的存储引擎实现标准接口来编写一个属于自己的存储引擎。这些非官方提供的存储引擎可以称为第三方存储引擎,区别于官方存储引擎。像目前最常用的 InnoDB 其实刚开始就是一个第三方存储引擎,后面由于过于优秀,其被 Oracle 直接收购了。 |
| 48 | + |
| 49 | +MySQL 官方文档也有介绍到如何编写一个自定义存储引擎,地址:https://dev.mysql.com/doc/internals/en/custom-engine.html 。 |
| 50 | + |
| 51 | +### [MyISAM 和 InnoDB 有什么区别?](#myisam-和-innodb-有什么区别) |
| 52 | + |
| 53 | +MySQL 5.5 之前,MyISAM 引擎是 MySQL 的默认存储引擎,可谓是风光一时。 |
| 54 | + |
| 55 | +虽然,MyISAM 的性能还行,各种特性也还不错(比如全文索引、压缩、空间函数等)。但是,MyISAM 不支持事务和行级锁,而且最大的缺陷就是崩溃后无法安全恢复。 |
| 56 | + |
| 57 | +MySQL 5.5 版本之后,InnoDB 是 MySQL 的默认存储引擎。 |
| 58 | + |
| 59 | +言归正传!咱们下面还是来简单对比一下两者: |
| 60 | + |
| 61 | +**1、是否支持行级锁** |
| 62 | + |
| 63 | +MyISAM 只有表级锁(table-level locking),而 InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。 |
| 64 | + |
| 65 | +也就说,MyISAM 一锁就是锁住了整张表,这在并发写的情况下是多么滴憨憨啊!这也是为什么 InnoDB 在并发写的时候,性能更牛皮了! |
| 66 | + |
| 67 | +**2、是否支持事务** |
| 68 | + |
| 69 | +MyISAM 不提供事务支持。 |
| 70 | + |
| 71 | +InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别,具有提交(commit)和回滚(rollback)事务的能力。并且,InnoDB 默认使用的 REPEATABLE-READ(可重读)隔离级别是可以解决幻读问题发生的(基于 MVCC 和 Next-Key Lock)。 |
| 72 | + |
| 73 | +关于 MySQL 事务的详细介绍,可以看看我写的这篇文章:[MySQL 事务隔离级别详解]()。 |
| 74 | + |
| 75 | +**3、是否支持外键** |
| 76 | + |
| 77 | +MyISAM 不支持,而 InnoDB 支持。 |
| 78 | + |
| 79 | +外键对于维护数据一致性非常有帮助,但是对性能有一定的损耗。因此,通常情况下,我们是不建议在实际生产项目中使用外键的,在业务代码中进行约束即可! |
| 80 | + |
| 81 | +阿里的《Java 开发手册》也是明确规定禁止使用外键的。 |
| 82 | + |
| 83 | + |
| 84 | + |
| 85 | +不过,在代码中进行约束的话,对程序员的能力要求更高,具体是否要采用外键还是要根据你的项目实际情况而定。 |
| 86 | + |
| 87 | +总结:一般我们也是不建议在数据库层面使用外键的,应用层面可以解决。不过,这样会对数据的一致性造成威胁。具体要不要使用外键还是要根据你的项目来决定。 |
| 88 | + |
| 89 | +**4、是否支持数据库异常崩溃后的安全恢复** |
| 90 | + |
| 91 | +MyISAM 不支持,而 InnoDB 支持。 |
| 92 | + |
| 93 | +使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 `redo log` 。 |
| 94 | + |
| 95 | +**5、是否支持 MVCC** |
| 96 | + |
| 97 | +MyISAM 不支持,而 InnoDB 支持。 |
| 98 | + |
| 99 | +讲真,这个对比有点废话,毕竟 MyISAM 连行级锁都不支持。MVCC 可以看作是行级锁的一个升级,可以有效减少加锁操作,提高性能。 |
| 100 | + |
| 101 | +**6、索引实现不一样。** |
| 102 | + |
| 103 | +虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。 |
| 104 | + |
| 105 | +InnoDB 引擎中,其数据文件本身就是索引文件。相比 MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按 B+Tree 组织的一个索引结构,树的叶节点 data 域保存了完整的数据记录。 |
| 106 | + |
| 107 | +详细区别,推荐你看看我写的这篇文章:[MySQL 索引详解]()。 |
| 108 | + |
| 109 | +**7、性能有差别。** |
| 110 | + |
| 111 | +InnoDB 的性能比 MyISAM 更强大,不管是在读写混合模式下还是只读模式下,随着 CPU 核数的增加,InnoDB 的读写能力呈线性增长。MyISAM 因为读写不能并发,它的处理能力跟核数没关系。 |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | +InnoDB 和 MyISAM 性能对比 |
| 116 | + |
| 117 | +**8、数据缓存策略和机制实现不同。** |
| 118 | + |
| 119 | +InnoDB 使用缓冲池(Buffer Pool)缓存数据页和索引页,MyISAM 使用键缓存(Key Cache)仅缓存索引页而不缓存数据页。 |
| 120 | + |
| 121 | +**总结**: |
| 122 | + |
| 123 | +- InnoDB 支持行级别的锁粒度,MyISAM 不支持,只支持表级别的锁粒度。 |
| 124 | +- MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别。 |
| 125 | +- MyISAM 不支持外键,而 InnoDB 支持。 |
| 126 | +- MyISAM 不支持 MVCC,而 InnoDB 支持。 |
| 127 | +- 虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。 |
| 128 | +- MyISAM 不支持数据库异常崩溃后的安全恢复,而 InnoDB 支持。 |
| 129 | +- InnoDB 的性能比 MyISAM 更强大。 |
| 130 | + |
| 131 | +最后,再分享一张图片给你,这张图片详细对比了常见的几种 MySQL 存储引擎。 |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | +常见的几种 MySQL 存储引擎对比 |
| 136 | + |
| 137 | +### [MyISAM 和 InnoDB 如何选择?](#myisam-和-innodb-如何选择) |
| 138 | + |
| 139 | +大多数时候我们使用的都是 InnoDB 存储引擎,在某些读密集的情况下,使用 MyISAM 也是合适的。不过,前提是你的项目不介意 MyISAM 不支持事务、崩溃恢复等缺点(可是~我们一般都会介意啊)。 |
| 140 | + |
| 141 | +《MySQL 高性能》上面有一句话这样写到: |
| 142 | + |
| 143 | +> 不要轻易相信“MyISAM 比 InnoDB 快”之类的经验之谈,这个结论往往不是绝对的。在很多我们已知场景中,InnoDB 的速度都可以让 MyISAM 望尘莫及,尤其是用到了聚簇索引,或者需要访问的数据都可以放入内存的应用。 |
| 144 | +
|
| 145 | +因此,对于咱们日常开发的业务系统来说,你几乎找不到什么理由使用 MyISAM 了,老老实实用默认的 InnoDB 就可以了! |
| 146 | + |
| 147 | + |
| 148 | + |
0 commit comments