MySQL面试考点地图:索引、事务、锁与优化全攻略

发布时间:2026/8/30 11:22:09
MySQL面试考点地图:索引、事务、锁与优化全攻略 很多 Java 开发者面试前都会做一件事疯狂刷 MySQL 八股文。索引、事务、MVCC、explain、慢查询……背得滚瓜烂熟结果真到了面试现场面试官换一个问法就答不上来。原因很简单你背的是答案不是解决问题的思路。MySQL 在 Java 技术栈里太重要了。它几乎是国内互联网公司的标配数据库而 Java 面试中 MySQL 相关问题的出现频率常年排在 JVM、并发、Spring 之后的第一梯队。面试官问 MySQL不是在考你记性好不好而是想确认两件事第一你写出来的 SQL 是不是真的能扛住生产环境的并发和压力第二系统出了问题你是两眼一抹黑还是能顺着日志和锁机制快速定位。这篇文章不会把网上能找到的所有 MySQL 面试题都抄一遍。我会从「面试官实际考察点」出发把 MySQL 面试高频考点拆成几个核心模块——存储引擎、索引、事务、锁、日志、SQL 优化、主从复制——每个模块都讲清楚原理、常见问法、容易踩的坑以及面试官期待的回答逻辑。如果你正在准备 Java 面试建议按照文末的 3 天复习路线来规划 MySQL 部分。看完这篇文章你能建立一张完整的 MySQL 考点地图后面再看到任何一道 MySQL 面试题你都能立刻判断它考的是哪个模块、应该从哪些角度回答。1. 面试前的 MySQL 考点地图先知道考什么再决定学什么很多准备面试的人有一个习惯打开搜索框搜「MySQL 面试题」然后照着长篇大论的题库从头刷到尾。这样做的效率极低因为你把时间平均分配给了高频题和冷门题最后记住的反而是最不常考的东西。MySQL 面试题可以按考察频率和重要性分成三层。第一层是必考题。索引的原理和失效场景、事务的 ACID 和隔离级别、MVCC 的实现机制、InnoDB 和 MyISAM 的区别。这四块内容几乎每家公司的面试都会问到而且经常是连环追问。比如面试官先问「为什么 InnoDB 用 B 树」你答完索引结构后他又会追问「那最左前缀原则是怎么回事」「什么情况下索引会失效」「覆盖索引和回表是什么」。这些问题的底层知识是连在一起的。第二层是高概率题。SQL 优化和慢查询排查、行锁与表锁、死锁的原因和排查、redo log 和 binlog 的区别与两阶段提交、主从复制的原理。如果面试的是高级岗位或者面试官想考察你有没有真实项目经验这些内容会很自然地出现在对话里。第三层是加分题。MySQL 8 的新特性、int(5) 的含义、utf8mb4 字符集的选择、连接数、Buffer Pool 等参数调优思路。这些内容不一定每家都问但答好了能明显提升面试官对你的印象。这篇文章的正文就按照这个分层来展开。你现在要做的不是马上开始背答案而是先跟着这篇文章把每个模块的核心原理搞清楚。原理懂了面试现场不管问题怎么变你都能用底层逻辑去回答。2. MySQL 存储引擎为什么 InnoDB 成了事实标准存储引擎几乎是 MySQL 面试的第一个话题因为它是理解后续所有内容的基础。MyISAM 和 InnoDB 的对比是经典送分题但很多人答不完整总是在枚举特性没有讲清楚「为什么」。2.1 MyISAM 和 InnoDB 的核心区别先看一张对比表对比维度MyISAMInnoDB事务支持不支持支持 ACID 事务锁粒度表级锁行级锁 表级锁外键不支持支持索引结构B 树非聚簇聚簇索引 二级索引崩溃恢复恢复能力弱借助 redo log 实现崩溃恢复全文索引支持MySQL 5.6 起支持存储文件.frm .MYD .MYI.frm .ibd或共享表空间光记住这张表还不够。面试官更关注的是你知道这些区别对实际开发有什么影响2.2 面试官追问为什么现在默认用 InnoDB这个问题的标准回答思路是「因为业务场景需要事务和并发控制」。互联网业务的典型场景是用户下单扣库存、转账、订单状态变更这些操作必须保证一致性。以转账为例A 账户扣钱和 B 账户加钱必须同时成功或同时失败。MyISAM 不支持事务一个 UPDATE 执行到一半系统崩溃数据就处于中间状态没有人知道应该回滚还是继续。InnoDB 通过事务和 redo/undo 日志解决了这个问题。并发控制是另一个关键点。MyISAM 使用表级锁意味着对一张表的任何写操作都会锁住整张表。在低并发场景下问题不大但互联网业务动辄上千的 QPS一个 UPDATE 锁住整张表后面所有读写请求都会被阻塞性能会断崖式下降。InnoDB 的行级锁只锁定涉及的行其他行的读写完全不受影响。还有一个隐藏点InnoDB 在崩溃恢复方面远胜于 MyISAM。数据库宕机后InnoDB 可以通过 redo log 重放未完成的事务保证数据不丢失MyISAM 则可能直接出现表损坏需要长时间修复。2.3 MyISAM 还有没有用武之地这个问题属于加分项。MyISAM 在某些场景下仍有一点价值表数据极少、完全只读、不需要事务、并发极低的历史归档表。它的索引结构更简单某些全表扫描场景下可能更快。但从 MySQL 8.0 开始MyISAM 被进一步边缘化官方建议所有新业务都使用 InnoDB。回答时可以说「从技术选型上我不会再选 MyISAM除非是极特殊的历史只读场景。」3. 索引MySQL 面试的半壁江山索引是 MySQL 面试中占比最大、追问最深的一块。如果把 Java 面试比作一场考试索引就是最后的压轴大题前面的基础题答得再好压轴题答崩了照样挂。3.1 为什么是 B 树而不是 B 树、哈希表先想一个问题数据库索引到底要解决什么问题答案是在数据量很大的情况下快速定位数据。磁盘读取很慢一次磁盘 I/O 能读到的数据有限如果每次查找都做很多次随机磁盘 I/O系统性能会废掉。B 树就是为此设计的。B 树和 B 树的区别要从两个维度看。第一B 树的非叶子节点不存储数据只存储键值和指针。这意味着每个非叶子节点能容纳更多的键树的高度更矮。一棵 3 层的 B 树可以存储千万级甚至上亿条数据而查询只需要 3 次左右的磁盘 I/O。B 树的非叶子节点也存数据同样的数据量树会更高I/O 次数更多。第二B 树的所有数据都存储在叶子节点并且叶子节点之间有链表相连天然支持范围查询。WHERE age 20 AND age 30 这样的条件在 B 树上找到一个起点后可以顺着链表依次扫描。B 树的叶子节点没有链表范围查询需要回到树中间做中序遍历性能远不如 B 树。那哈希表呢哈希索引的查找复杂度是 O(1)单行查询非常快但它有两个致命问题不支持范围查询、不支持排序。哈希表是一一映射age 20 这种操作需要把所有数据都哈希一遍完全走不了索引。所以 MySQL 的 InnoDB 引擎在绝大多数场景下都使用 B 树哈希索引只存在于自适应哈希索引这种辅助结构中。3.2 聚簇索引、二级索引和回表这是面试里最容易被问懵的一组概念但它们非常重要因为直接关系到 SQL 的性能。InnoDB 的表数据本身就是索引结构。聚簇索引的叶子节点存储的是完整的行数据所以一个表只能有一个聚簇索引。默认情况下InnoDB 会用主键作为聚簇索引如果表没有主键InnoDB 会选一个非空唯一索引再不行就用隐藏的 rowid 生成一个。二级索引也叫非聚簇索引的叶子节点存储的是索引列的值和主键值。当你要通过二级索引查数据时流程是先查二级索引找到主键再用主键回聚簇索引查完整行数据。这个「用主键再查一次」的过程就叫回表。举个例子-- 表 person主键 id二级索引 idx_name SELECT * FROM person WHERE name 张三;执行过程分两步第一步通过 idx_name 索引找到 name 为「张三」的记录得到主键 id第二步用 id 回到聚簇索引取出完整记录。如果 name 索引覆盖了你要查的所有字段那就不用回表了这就是覆盖索引。覆盖索引是 SQL 优化的常用手段。比如SELECT id, name FROM person WHERE name 张三idx_name 索引里既有 name 又有 id直接查索引导出结果不需要回表。面试官问「怎么优化 SQL」你答一句「用覆盖索引避免回表」他立刻知道你有实战经验。3.3 最左前缀原则联合索引 (a, b, c) 在匹配时会遵守最左前缀原则查询条件必须从最左边的列开始连续匹配。WHERE a 1、WHERE a 1 AND b 2、WHERE a 1 AND b 2 AND c 3都能走索引但WHERE b 2或WHERE c 3走不了。这个原则背后是 B 树的结构决定的。联合索引的排序规则是先按 a 排a 相同再按 b 排b 相同再按 c 排。所以你想直接跳过 a 用 b 查询索引顺序上 b 不是全局有序的没法用二分查找。实际开发中最常见的坑是建了联合索引但查询条件的顺序不对。WHERE b 2 AND a 1其实能走索引因为 MySQL 查询优化器会自动调整条件顺序。真正让索引失效的是WHERE a 1 AND c 3c 跳过了 b只能用 a 来缩小范围c 的筛选就要回表后做了。3.4 索引失效的常见场景面试官问索引失效通常是在考察你写 SQL 时有没有基本意识。高频失效场景包括对索引列使用函数或表达式如WHERE UPPER(name) ZHANG、WHERE age 1 30隐式类型转换如索引列是字符串类型查询条件用数字使用 LIKE 且通配符在开头如WHERE name LIKE %张OR 连接非索引列联合索引不满足最左前缀原则回答时可以补一句「索引失效不是绝对的最终以执行计划为准」然后拿出 explain 来验证。这种回答方式明显比死记硬背更有说服力。4. 事务与隔离级别脏读、不可重复读、幻读的底层逻辑事务是 MySQL 面试必考内容只背四个隔离级别不够要理解每个隔离级别解决的问题以及 InnoDB 是怎么实现隔离的。4.1 ACID 到底在说什么事务有四个特性原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability。面试官喜欢让候选人用自己的话解释这四个概念目标是看你能不能把抽象概念讲得清晰。原子性一个事务里的所有操作要么全部成功要么全部失败不能只做一半。比如转账 100 元A 扣钱成功但 B 加钱失败整个事务就要回滚到转账前状态。一致性事务执行前后数据都处于合法状态。这个特性最抽象底层依赖原子性、隔离性和持久性共同保证。举个例子转账前后A 和 B 的账户余额总和不变。隔离性多个事务并发执行时互相之间不能产生干扰。比如两个人同时改同一条订单记录事务隔离要保证他们看到的数据是合理的。持久性事务提交后修改必须永久保存即使数据库崩溃也不能丢。InnoDB 通过 redo log 实现这一点。4.2 四种隔离级别与三类问题SQL 标准定义了四种隔离级别隔离级别脏读不可重复读幻读读未提交READ UNCOMMITTED可能可能可能读已提交READ COMMITTED不会可能可能可重复读REPEATABLE READ不会不会可能串行化SERIALIZABLE不会不会不会先解释三个问题脏读事务 A 修改了一条数据还没提交事务 B 读到了这条修改后的数据事务 A 回滚事务 B 读到的数据就是脏数据。不可重复读事务 A 先读取 id1 的记录然后事务 B 修改并提交了这条记录事务 A 再读一次发现数据变了。同一个事务内两次读取结果不一致。幻读事务 A 查询某条件下的记录集合事务 B 插入了一条满足该条件的新记录并提交事务 A 再次查询时发现结果集合多了一行像「幻觉」一样。MySQL 默认隔离级别是可重复读REPEATABLE READ。InnoDB 通过 MVCC 和间隙锁在可重复读级别下解决了幻读问题这是它和标准 SQL 术语的一个差异点也是面试中很有含金量的一句话。4.3 MVCC多版本并发控制的核心机制MVCC 全称 Multi-Version Concurrency Control多版本并发控制。它的核心思想是读写不互相阻塞。写事务修改数据时读事务仍然可以读到之前版本的数据前提是隔离级别允许读旧版本。InnoDB 在每行数据后面隐藏了两个字段trx_id最近修改该行的事务 id和 roll_pointer指向 undo log 中的旧版本链。当一个事务要读取某行时它会检查自己的 Read View判断哪些版本对它可见。Read View 是一个事务启动时生成的快照里面记录了系统中活跃事务的 id 列表。判断规则大致是如果行的 trx_id 小于 Read View 中最小活跃事务 id说明这个版本在 Read View 生成前已经提交可见如果 trx_id 大于最大活跃事务 id说明这个版本在 Read View 生成后才创建不可见如果 trx_id 在活跃列表中说明该版本对应的修改事务还未提交不可见需要沿 undo log 找更早的版本。这就是可重复读的实现原理事务在第一次读取时生成 Read View之后每次读取都用同一个 Read View所以同一事务内多次读取结果一致。而读已提交级别每次读取都会生成新的 Read View所以能读到其他事务新提交的数据。回答 MVCC 时能画出 Read View 的判断逻辑就比单纯背诵「MVCC 解决了读写阻塞问题」要高一个档次。5. 锁机制与死锁排查从行锁到间隙锁锁是和事务并发强相关的主题。面试官问锁通常不是要你背锁的类型列表而是考察你在高并发场景下能不能判断出哪一类锁可能导致性能问题、死锁怎么发生、怎么排查。5.1 行锁、表锁、意向锁InnoDB 支持行级锁和表级锁。行级锁粒度小、并发度高但有加锁开销表级锁粒度大、并发度低适合整表操作。InnoDB 默认使用行级锁但某些场景下 MySQL 会升级为表锁比如需要扫描全表才能执行 UPDATE 时。意向锁比较抽象。它的作用是快速判断表里是否有行被锁住。事务要给某行加锁前必须先给表加意向锁。这就避免了另一个事务加表锁时需要逐行扫描看是否有行锁冲突。意向锁之间是兼容的意向锁与表级排他锁冲突。5.2 记录锁、间隙锁、临键锁这部分是 InnoDB 锁的核心细节也是一个比较难讲清楚的知识点。三类行锁对应的场景不同。记录锁Record Lock锁定的是索引记录本身。SELECT * FROM t WHERE id 1 FOR UPDATE会对 id1 的记录加锁其他事务要修改这一行必须等待。间隙锁Gap Lock锁定的是索引记录之间的间隙用于防止其他事务在间隙中插入新记录从而解决幻读问题。比如索引里有 1、3、5 三行间隙锁可能锁住 (1,3) 这个区间其他事务不能插入 id2 的记录。临键锁Next-Key Lock是记录锁和间隙锁的组合锁定的范围包括当前记录以及其前面的间隙。例如 (1,3] 表示锁住 3 这条记录以及 (1,3) 的间隙。InnoDB 在可重复读级别下默认使用临键锁来防止幻读。面试官问死锁时常用场景是两个事务互相持有对方需要的锁。比如事务 A 更新了 id1 的行事务 B 更新了 id2 的行然后 A 请求更新 id2B 请求更新 id1两个事务互相等待死锁就出现了。回答时可以补充一句InnoDB 有死锁检测机制发现死锁后会回滚代价较小的事务让另一个事务继续执行。5.3 死锁排查思路真实项目中死锁不是像上面例子那样刚好反向更新两条记录更多是因为范围锁、间隙锁叠加导致。排查死锁的第一步是查看死锁日志SHOW ENGINE INNODB STATUS;执行后重点看 LATEST DETECTED DEADLOCK 部分里面会显示两个事务各持有什么锁、在等待什么锁。根据这几条信息通常能定位到是哪两个事务发生了互相等待。死锁的预防手段包括所有事务按固定顺序访问资源、尽量缩短事务时间、合理设计索引避免扫描范围过大、用低隔离级别减少间隙锁。6. MySQL 三大日志redo log、undo log、binlog 的配合日志是 MySQL 面试中偏难的一部分因为涉及数据库底层工作机制。很多候选人能背出三个日志的名字但说不清它们各自的职责和协作关系。6.1 三者的核心职责redo log 是重做日志属于 InnoDB 存储引擎层。它的作用是保证事务的持久性。当你执行一条 UPDATE 时InnoDB 不会立刻把数据页刷写到磁盘因为磁盘随机写太慢。它会先把修改记录写到 redo log 中这是顺序写速度快得多。事务提交时只要 redo log 刷到磁盘事务就算持久化了数据页可以以后慢慢刷。如果数据库在数据页刷盘前崩溃重启后 InnoDB 会通过 redo log 重放操作恢复数据。undo log 是回滚日志也属于 InnoDB 存储引擎层。它保存了事务修改前的数据版本用于事务回滚和 MVCC 的多版本链。事务执行中需要回滚时通过 undo log 把数据恢复到修改前状态。同时MVCC 中提到的旧版本读取就是通过 undo log 回溯历史版本实现的。binlog 是二进制日志属于 MySQL Server 层记录的是数据的逻辑变更比如「id1 的行的 age 从 20 改成 30」。binlog 的主要用途有三个主从复制、数据恢复、审计。主从架构中从库通过拉取主库的 binlog 并在本地重放实现与主库数据一致。6.2 为什么需要两阶段提交redo log 和 binlog 是两个独立的日志系统分别记录在当前事务里。问题来了如果 redo log 写了但 binlog 没写或者反过来主库和从库的数据就会不一致。举一个例子事务执行到一半redo log 写入成功并提交但 binlog 还没来得及写数据库在此时崩溃。重启后主库通过 redo log 恢复了更新但从库没有收到 binlog就没有更新。主从数据不一致。为了解决这个问题InnoDB 引入了两阶段提交事务在提交时先写 redo log进入 prepare 状态然后写 binlog最后把 redo log 改为 commit 状态。如果在 prepare 阶段后、binlog 写入前崩溃重启后发现 redo log 是 prepare 但 binlog 未写就会回滚事务如果 binlog 已写、准备提交 redo log 前崩溃重启后会继续提交事务。通过这个机制redo log 和 binlog 的状态始终一致。这部分如果能主动写出「XID 被写入 binlog用于 redo log 和 binlog 的关联」面试官对你的底层理解会非常认可。7. SQL 优化与慢查询排查从 explain 到索引失效SQL 优化是 Java 面试中「实战感」最强的模块。面试官会给你一条慢查询日志或者直接问「线上有个 SQL 跑了 5 秒你怎么排查」7.1 开启慢查询日志首先要能说出慢查询日志怎么配置。MySQL 提供了两个关键参数和一条常用命令-- 查看是否开启慢查询及阈值 SHOW VARIABLES LIKE slow_query_log; SHOW VARIABLES LIKE long_query_time; -- 开启慢查询当前会话/实例生效 SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 1;需要说明的是long_query_time的单位是秒设为 1 意味着执行时间超过 1 秒的 SQL 会被记录到慢查询日志中。生产环境建议设为 1 或更低具体根据业务情况调整。7.2 用 explain 分析执行计划拿到慢查询 SQL 后第一步不是猜而是看执行计划。explain 是 MySQL 用来展示 SQL 执行计划的关键字EXPLAIN SELECT u.id, u.name, o.order_no FROM user u LEFT JOIN orders o ON u.id o.user_id WHERE u.status 1 ORDER BY u.create_time DESC;执行后重点看这几个字段字段关键含义type访问类型system const eq_ref ref range index ALL。看到 ALL 就要警惕全表扫描key实际使用的索引为 NULL 说明没走索引rows预估扫描行数越小越好Extra出现 Using filesort 说明排序没用索引Using temporary 说明使用了临时表Using index 说明覆盖索引生效常见的优化动作包括为 WHERE 条件列建立索引、为 ORDER BY 列建立索引避免 filesort、把 SELECT * 改成只查需要的列、拆分复杂 join 为多次简单查询。7.3 经典索引失效 SQL 示例下面这条 SQL 是在真实项目中非常容易出现的问题类型-- 错误示例对索引列使用函数导致索引失效 SELECT * FROM orders WHERE DATE(create_time) 2026-08-01; -- 正确示例改成范围查询走索引 SELECT * FROM orders WHERE create_time 2026-08-01 00:00:00 AND create_time 2026-08-02 00:00:00;另外一个高频优化点是在深分页场景-- 错误示例深分页扫描大量数据 SELECT * FROM orders ORDER BY id LIMIT 100000, 20; -- 优化示例先通过覆盖索引拿到起始 id再回表查完整数据 SELECT * FROM orders WHERE id (SELECT id FROM orders ORDER BY id LIMIT 100000, 1) ORDER BY id LIMIT 20;面试时能给出这两类案例比单纯说「加索引」「避免 SELECT *」要有说服力得多。8. 主从复制与高可用binlog 到中继日志的传递链路主从复制是分布式系统面试中和 MySQL 关联最深的一块。Java 开发者虽然不一定要部署 MySQL 主从但必须理解读写分离的原理和常见问题。8.1 主从复制原理MySQL 主从复制的过程分为三个步骤主库把数据变更记录写入 binlog。从库的 I/O 线程连接主库请求指定位置的 binlog并把收到的内容写入从库的中继日志relay log。从库的 SQL 线程读取中继日志在本地重放日志事件更新到自身的数据库中。这里有一个细节需要区分从库有一个 I/O 线程负责拉取 binlog有一个 SQL 线程负责执行中继日志。两个线程是异步的所以从库数据通常比主库有延迟这就是主从延迟问题的根源。8.2 binlog 的三种格式面试官问 binlog 格式是想考察你是否清楚主从复制在不同格式下的行为差异。Statement记录的是 SQL 语句本身。优点是日志量小缺点是非确定性函数如 NOW()、UUID() 在主从两端执行结果可能不同导致数据不一致。Row记录的是每行数据的具体变更内容。优点是最精确不受函数影响缺点是日志量大。MixedMySQL 自动判断在可能产生不一致时使用 Row否则使用 Statement。从实践角度看目前主流推荐使用 Row 格式尤其是要求数据强一致的业务场景。8.3 主从延迟的常见原因和应对主从延迟的常见原因有从库硬件性能不如主库、从库同时承担了多份复制任务、主库大事务导致 binlog 积压、从库上执行了耗时的查询或备份任务。应对手段包括提升从库配置、缩短主库大事务、拆分为多个从库分摊读取压力、监控 Seconds_Behind_Master 指标。对于必须实时读到最新数据的业务可以在中间件层面做强制走主库的策略。9. 容易被细问的细节题int(5)、utf8mb4、连接数这类题目不一定每家都问但面试官如果提到通常是在传「你到底是真用过还是只会背概念」的信号。9.1 int(5) 到底是什么意思这是一个非常经典的前后端协作误解。int(5)不是指「这个整数最多只能存 5 位数」。int 类型在 MySQL 中永远占 4 个字节能存储的范围是 -2147483648 到 2147483647约 21 亿。int(5) 中的 5 指的是显示宽度并且只在搭配ZEROFILL时有效。比如INT(5) ZEROFILL存的值为 42查询时会显示 00042。如果没有 ZEROFILLint(5) 和 int(11) 在存储上没有区别。9.2 utf8 和 utf8mb4 的区别MySQL 的 utf8 字符集不是真正的四字节 UTF-8它最多只支持 3 个字节无法存储 emoji 表情和一些生僻汉字。如果业务需要存 emoji 或四字节字符必须使用 utf8mb4并在连接层也指定对应的字符集。MySQL 8.0 的默认字符集已经是 utf8mb4这是一个很大的改进。如果你还在用 MySQL 5.7建议在建库时显式指定CREATE DATABASE demo_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;9.3 max_connections 和连接数问题Java 项目使用连接池连接 MySQL默认连接池大小可能在 10 到 50 之间。但如果存在连接泄漏连接池会不断申请新连接最终把数据库的连接数打满报Too many connections错误。排查思路是先看 MySQL 当前连接数和状态SHOW STATUS LIKE Threads_connected; SHOW GLOBAL VARIABLES LIKE max_connections;查完之后定位到具体业务应用检查连接池是否有正确的归还连接逻辑、连接空闲超时配置是否合理。同时一个数据库实例的连接数不是越大越好每个连接都会消耗线程和内存过大的连接数反而会拖垮数据库。10. Java 面试 MySQL 的 3 天复习路线现在回到文章开头的问题3 天时间怎么最高效地把 MySQL 面试准备到位我不建议你按网上的长题库逐题刷而是按知识模块做「原理 练习 自测」的循环。下面是一套可执行的分配方案。Day 1存储引擎 索引上午把 InnoDB 和 MyISAM 的区别讲清楚重点理解「为什么 InnoDB 用 B 树」和「聚簇索引与回表」。下午做索引实战建一张测试表模拟插入 10 万条数据分别用无索引、单列索引、联合索引执行查询再用 explain 看执行计划的差异。自测题InnoDB 为什么用 B 树而不用 B 树联合索引 (a, b, c)WHERE b 1能不能走索引什么是回表覆盖索引为什么能提升查询性能LIKE %张 为什么会导致索引失效Day 2事务 锁 日志上午整理 ACID、隔离级别、MVCC 的执行流程画出事务读取数据时 Read View 的判断过程。下午研究锁机制重点搞清楚记录锁、间隙锁、临键锁的区别。晚上用 1 小时复习 redo log、undo log、binlog 的职责和两阶段提交。自测题MySQL 默认隔离级别是什么它是怎么避免幻读的MVCC 在可重复读级别的实现和读已提交有什么区别Redo log 和 binlog 为什么需要两阶段提交两个事务互相更新不同行为什么会死锁Day 3SQL 优化 主从复制 综合模拟上午练习慢查询排查流程开启慢查询日志、造一条慢 SQL、解释执行计划、给出优化方案。下午复习主从复制原理、binlog 格式、主从延迟原因。晚上挑 20 道高频 MySQL 面试题不看答案口述回答并录音检查自己能不能把关键逻辑说完整。自测题线上一条 SQL 执行了 2 秒你怎么定位和优化SHOW ENGINE INNODB STATUS 里怎么找死锁信息主从延迟的根本原因是什么业务上如何应对你遇到过 Too many connections 吗怎么排查这套复习路线有一个特点始终把「为什么」放在「怎么回答」前面。你可以在此基础上结合自己的项目经验做补充。比如你处理过一个慢 SQL就在 Day 3 的模拟面试里把它讲出来你在项目里做过读写分离就把主从复制部分讲成自己的实践案例。11. 最后给 Java 面试者的几点提醒MySQL 面试题再多也逃不出存储引擎、索引、事务、锁、日志、优化、复制这几个核心模块。真正拉开差距的从来不在于你背了多少道题而在于你能不能把概念串成一条逻辑链并且用真实场景去解释它们。面试官问索引你不要只回答 B 树而是可以从全表扫描的代价讲到 B 树的层数再讲到聚簇索引和回表最后用 explain 举例。面试官问事务隔离级别你不要只背四种隔离级别而是可以指出 MySQL 默认是可重复读并解释 InnoDB 如何通过 MVCC 和间隙锁解决幻读。这种回答方式会让你的知识体系显得非常完整。准备面试的过程中有一个容易被忽视的点不要脱离 MySQL 实际运行环境去背概念。建议你在自己电脑上装一个 MySQL用几万条测试数据跟着这篇文章的示例跑一遍。亲自看一次创建索引前后执行计划的变化效果比刷 50 道题都管用。另外面试中如果被问到不熟悉的问题不要慌张。面试官更看重的是你能否用已有知识去推理。比如你忘了间隙锁的定义你可以从「可重复读级别要解决幻读」出发推出 InnoDB 需要一个能阻止其他事务插入数据的锁机制自然就能说出间隙锁。答错的成本很低冷场硬编的成本很高。把 MySQL 拿下Java 面试的后端基础环节就稳了一大半。建议把本文收藏起来按照 3 天复习路线逐段消化。面试当天把索引、事务、锁、日志这几个核心模块的重点在脑子里过一遍祝你少走弯路顺利拿到满意的 Offer。