少女祈祷中...
NEKO
知识库

mysql 存储引擎面试要点

一、总览与对比类

Q1:MySQL 有哪些存储引擎?

  • InnoDB:默认,支持事务、行锁、外键、崩溃恢复。

  • MyISAM:不支持事务和行锁,表锁,查询快,适合读多写少。

  • Memory:内存表,速度快,重启丢失。

  • Archive:高压缩,只支持插入和查询,适合归档。

  • CSV:以 CSV 文件存储。

  • NDB:集群引擎。

  • 面试重点通常是 InnoDB vs MyISAM。

Q2:InnoDB 和 MyISAM 的区别?

维度

InnoDB

MyISAM

事务

支持

不支持

锁粒度

行锁

表锁

外键

支持

不支持

崩溃恢复

支持(redo log)

不支持

索引结构

聚簇索引

非聚簇索引

全文索引

5.6+ 支持

支持

计数

不存总数,要扫

存行数,COUNT 快

适用

写多、需事务

读多、不需事务

Q3:为什么 MySQL 默认用 InnoDB?

  • 支持事务,保证 ACID。

  • 行锁,并发高。

  • 支持崩溃恢复,数据安全。

  • 支持外键、MVCC。

  • 综合能力最强,适合大多数场景。

Q4:MyISAM 还有什么用?

  • 读多写少、不需事务的场景。

  • COUNT(*) 快,因为存了行数。

  • 全文索引较早支持。

  • 现代基本被 InnoDB 取代。

二、InnoDB 内存结构类

Q5:InnoDB 的内存结构有哪些?

  • Buffer Pool:缓冲池,缓存数据页和索引页,最重要。

  • Change Buffer:写缓冲,缓存非唯一二级索引的修改。

  • Log Buffer:redo log 缓冲。

  • Adaptive Hash Index:自适应哈希索引。

  • Double Write Buffer:双写缓冲,防页断裂。

Q6:Buffer Pool 的作用?

  • 缓存磁盘上的数据页,读写先走内存。

  • 减少磁盘 I/O,是 InnoDB 性能核心。

  • 大小由 innodb_buffer_pool_size 控制,通常设物理内存 50%~70%。

Q7:Buffer Pool 的 LRU 有什么改进?

  • 朴素的 LRU 会被全表扫描污染。

  • InnoDB 把 LRU 分成 young 区(5/8)和 old 区(3/8)。

  • 新页先插入 old 区头部,再次访问且超过 innodb_old_blocks_time 才移到 young 区。

  • 防止一次性扫描把热数据挤出去。

Q8:Change Buffer 是什么?

  • 缓存非唯一二级索引的写操作(INSERT、UPDATE、DELETE)。

  • 等页被读入内存时再 merge,减少随机 I/O。

  • 唯一索引不能用它,因为要读盘校验唯一性。

  • 由 innodb_change_buffer_max_size 控制。

Q9:Log Buffer 是什么?

  • redo log 的内存缓冲。

  • 事务提交时先写 Log Buffer,再按策略刷盘。

  • 大小由 innodb_log_buffer_size 控制。

Q10:Double Write 是什么?为什么需要?

  • 刷脏页时先写到 double write buffer,再写数据文件。

  • 防止页断裂(写到一半宕机)。

  • 崩溃恢复时用 double write 修复损坏页。

三、InnoDB 磁盘结构类

Q11:InnoDB 的磁盘结构层次?

  • 表空间(tablespace)→ 段(segment)→ 区(extent)→ 页(page)→ 行(row)。

  • 页默认 16KB,区默认 1MB(64 个页)。

  • 段分数据段、索引段、回滚段。

Q12:什么是表空间?

  • 系统表空间:ibdata1,存数据字典、回滚段等。

  • 独立表空间:innodb_file_per_table=ON,每表一个 .ibd。

  • 通用表空间、undo 表空间、临时表空间。

  • 推荐独立表空间,便于管理和回收。

Q13:InnoDB 的行格式有哪些?

  • COMPACT:5.6 默认,变长字段长度列表 + NULL 标志位。

  • REDUNDANT:旧格式,空间浪费。

  • DYNAMIC:5.7 默认,溢出页存大字段。

  • COMPRESSED:压缩格式。

Q14:大字段怎么存?

  • 行内放不下时,存到溢出页,行内只留 20 字节指针。

  • DYNAMIC 格式下,大字段完全溢出。

  • COMPACT 下可能留部分前缀。

Q15:页的内部结构?

  • 页头、页目录、用户记录、空闲空间、页尾。

  • 页目录用槽位加速页内查找。

  • 记录按主键有序,用链表连接。

四、索引结构类

Q16:InnoDB 和 MyISAM 的索引结构区别?

  • InnoDB:聚簇索引,主键索引叶子存整行;二级索引叶子存主键值。

  • MyISAM:非聚簇索引,索引叶子存行地址,数据和索引分离。

Q17:什么是聚簇索引?

  • 数据行和主键索引存在一起,叶子节点就是数据页。

  • 一张表只有一个聚簇索引,通常是主键。

  • 没主键时选唯一非空索引,再没有就生成隐藏 row_id。

Q18:为什么推荐自增主键?

  • 顺序插入,减少页分裂和碎片。

  • 主键小,二级索引也小。

  • UUID 随机插入导致页分裂、性能下降。

Q19:回表是什么?

  • 二级索引查到主键值,再回聚簇索引查整行。

  • 覆盖索引可避免回表。

五、事务与锁相关类

Q20:InnoDB 怎么实现事务?

  • 原子性:undo log。

  • 持久性:redo log。

  • 隔离性:锁 + MVCC。

  • 一致性:由以上共同保证。

Q21:InnoDB 的锁有哪些?

  • 行锁:记录锁、间隙锁、临键锁、插入意向锁。

  • 表锁:意向锁、MDL。

  • 默认行锁,无索引时退化为表锁。

Q22:InnoDB 的 MVCC 怎么实现?

  • 隐藏列 DB_TRX_ID、DB_ROLL_PTR。

  • undo log 版本链。

  • ReadView 可见性判断。

六、崩溃恢复与持久化类

Q23:InnoDB 怎么保证崩溃恢复?

  • redo log 重放已提交事务。

  • undo log 回滚未提交事务。

  • double write 修复页断裂。

  • 两阶段提交保证 redo 和 binlog 一致。

Q24:什么是页断裂?

  • 刷 16KB 页时写到一半宕机,页损坏。

  • double write 先写副本,恢复时用副本修复。

Q25:innodb_flush_log_at_trx_commit 怎么影响持久性?

  • =1:每次提交刷盘,不丢。

  • =0:每秒刷,可能丢 1 秒。

  • =2:提交写 OS cache,宕机可能丢。

七、实战与选型类

Q26:什么时候选 MyISAM?

  • 读多写少、不需事务、能接受表锁。

  • 需要快速 COUNT(*)。

  • 现代生产基本不用,除非特殊场景。

Q27:Memory 引擎适用场景?

  • 临时表、缓存、会话数据。

  • 速度快,但重启丢失,不支持大字段。

  • 生产核心数据不用。

Q28:Archive 引擎适用场景?

  • 日志、归档数据。

  • 高压缩,只支持 INSERT 和 SELECT。

  • 不支持索引(除自增主键)。

Q29:怎么查看表的存储引擎?

  • SHOW TABLE STATUS LIKE 't';

  • SHOW CREATE TABLE t;

  • information_schema.TABLES。

Q30:怎么修改存储引擎?

  • ALTER TABLE t ENGINE=InnoDB;

  • 会重建表,大表耗时长,需低峰执行。

八、高频陷阱题

Q31:InnoDB 的 COUNT(*) 为什么慢?

  • 不存总行数,要扫索引统计。

  • MyISAM 存了行数,所以快。

  • 优化:用最小二级索引扫、计数表、缓存。

Q32:InnoDB 支持全文索引吗?

  • MySQL 5.6+ 支持。

  • 早期只有 MyISAM 支持。

Q33:InnoDB 表一定比 MyISAM 慢吗?

  • 不一定。读多写少时 MyISAM 可能略快。

  • 但 InnoDB 行锁、事务、崩溃恢复综合更优。

  • 现代硬件下差距很小。

Q34:Change Buffer 对唯一索引有效吗?

  • 无效。唯一索引要读盘校验唯一性,不能延迟。

  • 只对非唯一二级索引有效。

Q35:Buffer Pool 越大越好吗?

  • 不是。太大会挤占 OS 内存,影响文件和连接。

  • 一般设物理内存 50%~70%。

评论