【数据库 面试突击 · 02】大厂高频面试题:从三范式到日志机制全梳理
目录1. 数据库的三范式是什么2. MySQL 支持哪些存储引擎3. MyISAM 和 InnoDB 的区别有哪些4. 超键、候选键、主键、外键分别是什么5. SQL 约束有哪几种6. MySQL 中的 varchar 和 char 有什么区别7. MySQL 中 in 和 exists 区别8. MySQL 是如何保证主从一致的9. redo log 与 binlog 的区别10. 只靠 binlog 可以支持数据库崩溃恢复吗1. 数据库的三范式是什么关键词第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、原子性、依赖关系✅ 标准回答数据库的三范式是设计关系型数据库时需要遵循的三个规范化标准目的是为了减少数据冗余并提高数据一致性。第一范式 (1NF)要求数据库表的每一列都是不可分割的原子数据项。即属性不可再分。第二范式 (2NF)在满足 1NF 的基础上要求表中的非主键字段完全依赖于主键消除部分函数依赖。如果主键是联合主键非主键字段不能只依赖于主键中的一部分。第三范式 (3NF)在满足 2NF 的基础上要求非主键字段之间不存在传递依赖。即非主键字段不能依赖于另一个非主键字段。 加分句“在实际开发中我们通常追求满足第三范式以保证数据的整洁性。但在高并发的互联网场景下为了提升查询性能有时会进行适当的‘反范式’设计通过增加少量的数据冗余来减少多表关联Join的开销这需要在规范性和性能之间做权衡。”2. MySQL 支持哪些存储引擎关键词InnoDB、MyISAM、Memory、Archive、Blackhole✅ 标准回答MySQL 支持多种存储引擎通过SHOW ENGINES;命令可以查看。最常见的包括InnoDBMySQL 5.5.5 版本后的默认引擎。支持事务ACID、行级锁、外键、崩溃恢复和高并发读写。它是目前绝大多数业务场景的首选。MyISAM早期的默认引擎。不支持事务和行级锁只支持表级锁。读取速度快但并发写入性能差。适合以读操作为主、对事务要求不高的场景如日志收集。Memory数据存储在内存中访问速度极快但数据在服务器重启后会丢失。适合存储临时表或缓存数据。Archive仅支持插入和查询不支持索引。压缩率高适合存储归档的大量历史数据。Blackhole接收数据但不存储数据类似黑洞常用于主从复制中的中继服务器。 加分句“虽然 MySQL 支持多种引擎但在现代企业级应用中InnoDB已经占据了绝对主导地位。除非有特殊的性能需求如纯日志记录或内存缓存否则绝大多数场景我都直接选择 InnoDB因为它能提供最可靠的事务支持和数据安全。”3. MyISAM 和 InnoDB 的区别有哪些关键词事务、锁粒度、索引结构、存储文件、崩溃恢复✅ 标准回答这两者是 MySQL 中最重要的两个引擎核心区别如下特性MyISAMInnoDB事务支持不支持支持(ACID)锁粒度表级锁行级锁(并发性能高)外键支持不支持支持索引结构非聚集索引 (索引与数据分离)聚集索引(数据与主键索引在一起)存储文件.frm (表结构)、.MYD (数据)、.MYI (索引).frm (表结构)、.ibd (数据和索引)崩溃恢复差容易损坏强支持崩溃恢复 加分句“最本质的区别在于索引结构。MyISAM 使用的是非聚集索引B树叶子节点存储的是数据的地址而 InnoDB 使用的是聚集索引B树叶子节点直接存储行数据。这也导致了 InnoDB 在主键查询时非常快但二级索引查询需要回表。此外InnoDB 的行级锁是通过索引实现的这在面试中也是一个常考点。”4. 超键、候选键、主键、外键分别是什么关键词超键、候选键、主键、外键、唯一性、非空✅ 标准回答这是数据库设计的基础概念层级关系如下超键 (Super Key)能够唯一标识表中一条记录的属性或属性组。超键可能包含多余的属性。候选键 (Candidate Key)最小化的超键。即从超键中去掉任何一个属性后就不再具有唯一标识的能力。一个表可以有多个候选键。主键 (Primary Key)从候选键中人为选定的一个用于唯一标识表中的每一行。主键不能为 NULL且唯一。外键 (Foreign Key)用于建立和加强两个表数据之间的链接。外键的值必须是另一个表主键的有效值或 NULL用于维护数据的参照完整性。 加分句“简单来说超键是一个大集合候选键是超键的‘最小单元’主键是从候选键中‘选出来’干活的。在设计表结构时我通常会额外添加一个自增的id作为主键而不是使用业务字段如身份证号因为业务字段可能会变更且作为主键索引效率不如自增 ID 稳定。”5. SQL 约束有哪几种关键词主键约束、外键约束、唯一约束、检查约束、非空约束✅ 标准回答SQL 约束用于规定表中的数据规则确保数据的准确性和可靠性。主要有以下五种主键约束 (PRIMARY KEY)唯一标识表中的每一行且非空。外键约束 (FOREIGN KEY)建立表与表之间的联系保证参照完整性。唯一约束 (UNIQUE)确保列或列组合的值唯一但允许有 NULL 值NULL 与 NULL 不相等。非空约束 (NOT NULL)指定列不能存储 NULL 值。检查约束 (CHECK)限制列中的值的范围。例如限制年龄必须大于 0。 加分句“除了这些标准约束很多数据库还支持默认值约束 (DEFAULT)。在实际项目中我会尽量利用数据库层面的约束如非空、唯一、外键来保证数据质量而不是仅仅依赖应用层的代码逻辑因为数据库约束是最后一道防线能有效防止脏数据的产生。”6. MySQL 中的 varchar 和 char 有什么区别关键词变长字符串、定长字符串、存储空间、性能✅ 标准回答CHAR和VARCHAR都是字符串类型但存储方式不同CHAR(n)定长字符串。无论实际存储的数据长度是多少都会占用n个字符的空间。如果数据不足n会用空格填充读取时会自动去除末尾空格。VARCHAR(n)变长字符串。只占用实际数据长度加上 1~2 个字节用于记录长度的空间。 加分句“在性能上CHAR因为定长读取速度更快适合存储长度固定或变化不大的数据如性别、状态码。而VARCHAR更节省空间适合存储长度变化较大的数据如用户名、地址。在 MySQL 5.0 以后VARCHAR的性能已经得到了很大优化通常推荐优先使用VARCHAR。”7. MySQL 中 in 和 exists 区别关键词IN、EXISTS、子查询、驱动表、性能优化✅ 标准回答IN和EXISTS都用于子查询判断但执行逻辑不同IN通常将子查询的结果集计算出来然后将外层表的每一行数据去匹配这个结果集哈希查找。适用于子查询结果集小的情况。EXISTS对外层表进行循环每扫描一行数据就去执行一次子查询判断是否存在。只要子查询返回TRUE就不再继续扫描。适用于外层表小内层表大的情况。 加分句“关于谁快谁慢没有绝对的答案取决于数据量和索引情况。一般的经验法则是如果子查询的结果集非常小比如只有几个 ID用IN如果子查询涉及大数据量表且外层表数据量小用EXISTS。现代数据库优化器通常很智能会自动转换执行计划但在编写复杂 SQL 时我们依然需要了解其原理。”8. MySQL 是如何保证主从一致的关键词主从复制、Binlog、I/O Thread、SQL Thread、半同步复制✅ 标准回答MySQL 主从复制的核心是Binlog (二进制日志)。其基本流程如下主库写入主库上的数据变更操作会记录到 Binlog 文件中。从库连接从库启动 I/O 线程连接到主库请求读取 Binlog 中的事件。日志传输主库启动 Binlog Dump 线程将 Binlog 事件发送给从库的 I/O 线程。写入中继日志从库的 I/O 线程将接收到的 Binlog 事件写入本地的中继日志 (Relay Log)。重放日志从库的 SQL 线程读取 Relay Log重放其中的事件从而实现数据同步。 加分句“默认的异步复制存在延迟和数据丢失的风险。为了保证强一致性可以使用半同步复制 (Semi-Sync)。在这种模式下主库在提交事务时必须等待至少一个从库确认接收到 Binlog 并写入 Relay Log主库才会返回给客户端提交成功。这牺牲了一点性能但极大地提高了数据的安全性。”9. redo log 与 binlog 的区别关键词Redo Log、Binlog、物理日志、逻辑日志、事务持久性、主从复制✅ 标准回答两者都是 MySQL 的日志但作用和层次不同特性Redo Log (重做日志)Binlog (归档日志)所属模块InnoDB 存储引擎层MySQL 服务层日志类型物理日志(记录数据页的修改)逻辑日志(记录 SQL 语句的原始逻辑)主要作用保证事务的持久性崩溃恢复用于主从复制和数据备份/恢复记录时机事务执行过程中不断写入事务提交时才写入文件形式循环写固定大小追加写文件满了切换 加分句“这是 MySQL 两阶段提交 (2PC) 的核心。Redo Log 解决了‘掉电丢失’的问题保证了数据在崩溃后能恢复而 Binlog 解决了‘历史归档’和‘集群同步’的问题。两者的配合确保了 MySQL 在高并发下的数据安全和一致性。”10. 只靠 binlog 可以支持数据库崩溃恢复吗关键词崩溃恢复、Binlog、Redo Log、数据完整性✅ 标准回答不可以。Binlog是逻辑日志且是事务提交后才写入。如果数据库在事务提交前崩溃Binlog 中没有记录这次操作。Redo Log是物理日志记录的是数据页的物理修改。在崩溃重启时InnoDB 会通过 Redo Log 重放未完成的事务保证数据不丢失。 加分句“如果只用 Binlog 进行恢复会丢失最后一次 Binlog 切换之后的数据因为 Binlog 只有在事务提交时才会落盘。而 Redo Log 是在事务执行过程中实时写入的Write-Ahead Logging它能保证即使数据库崩溃只要事务没有提交数据就能恢复到崩溃前的状态。因此崩溃恢复必须依赖 Redo LogBinlog 主要用于归档和复制。”