MySQL面试 八股文20道
可能部分问题有些过于简单了,我只简单写了些核心,方便记忆理解,如果不懂可以单独 针对某一点去查资料。
1. MySQL 架构:4 层分层设计,为什么这样?
MySQL 架构是分层插件式,客户端请求从上到下流水线处理。
解释:连接层管门、服务层管脑、引擎层管活、物理层管存。模块化设计,让引擎可换(InnoDB/MyISAM)。
细节:连接层(连接池 + 权限验证);服务层(解析器 + 优化器 + 缓存,8.0 移除查询缓存);引擎层(InnoDB 默认,支持事务);物理层(数据/日志文件)。
好处:灵活高性能,OLTP 用 InnoDB(事务安全),读多场景换 MyISAM。
场景:电商订单表用 InnoDB(高并发写),日志表用 MyISAM(读快)。
2. 聚簇索引 vs 普通索引(二级索引):叶子节点藏着啥秘密?
InnoDB 每表必有一棵聚簇索引(主键),普通索引是辅助。
解释:聚簇叶子存整行数据(所有列);普通叶子只存"索引列 + 主键 id",查全行需回表。
细节:聚簇按主键排序,整表数据只存这儿;普通如 idx_name,叶子:[name='蕾姆', id=1]。
好处:聚簇避免多树存数据,节省空间;普通加速单列查询。
场景:主键 id 查询全行(走聚簇);name 模糊查(走普通,回表)。
3. 覆盖索引:为什么它能让查询飞起?
覆盖索引 = 查询全列都在索引叶子里拿,不用回表。
解释:联合索引 (name, age) + select name, age where name='蕾姆',叶子直接有 age,不回聚簇。
细节:单列/联合都行,只要 select 字段 ⊆ 索引列 + id;单列 idx_name + select name, id 也覆盖。
好处:IO 从 O(n) 降 O(1),QPS 翻倍。
场景:用户列表页,只查 id + name(覆盖),避开 select * 回表。
4. 最左前缀原则:联合索引的"铁律"
联合索引 (a,b,c) 必须从左连续匹配。
解释:where a=1 / (a=1 and b=2) / (a=1,b=2,c=3) 命中;where b=2 或 (a=1 and c=3) 失效。
细节:优化器从最左走,断了就全废;B+树按 (a,b,c) 序存。
好处:树矮扫描快,范围查询高效。
场景:订单表 idx_status_create_time,先 status(低区分)放右,高区分 create_time 放左?错!放左才秒扫。
5. 索引失效 6 大场景:一断全废的坑
索引失效 = 优化器放弃索引,全表扫(explain type=ALL)。
解释:口诀:函数、模糊左、转换、or、负向、最左断。
细节:
- ① like '%蕾姆':左 % 无法范围扫。
- ② 函数 substr(name,1,3)='蕾':变列值,索引失效。
- ③ 隐式转换:varchar name=123(转字符串)。
- ④ or 至少一边无索引:全 or 走索引才合并。
- ⑤ != / not in / <>:不确定范围。
- ⑥ 违反最左:(a,b) where b=1。
好处:避坑后,rows 降 90%,查询 <1ms。
场景:搜索页 where name like '%蕾%',改业务逻辑用 Elasticsearch。
6. ICP(索引下推):5.6+ 的回表杀手
ICP 把 where 过滤下沉到引擎层,省回表。
解释:联合 (name,age) + where name='蕾%' and age=17,先引擎过滤 age,只回符合的。
细节:老版全回表再 Server 滤;新版引擎层用索引 age 值扔不符合。explain Extra: Using index condition。
好处:回表 1000→10 次,性能 100 倍。
场景:用户过滤 where city='西安' and age=20-30,联合索引下推省 IO。
7. explain:SQL 执行计划的"透视仪"
explain 预览 MySQL 如何跑 SQL,不真执行。
解释:加 explain 前,输出表:type(访问型)、key(用索引)、rows(估扫行)、Extra(额外细节)。
细节:type 好序:ref > range > index > ALL(全扫报警);Extra: Using index(覆盖)/ Using where(Server 滤,回表)/ Using index condition(ICP)。
好处:优化前看 plan,改 SQL 避坑。
场景:慢查询日志,explain 见 type=ALL,加索引改 range。
8. select * 为什么是雷区?三重杀伤
线上禁 select *,改具体列。
解释:浪费带宽、破覆盖、毁缓存。
细节:
- ① 传多列:20 列表,只用 2 列,网络 IO 翻倍。
- ② 破覆盖:select * 瞬间回表。
- ③ 8.0 前缓存失效:SQL 变,key 变,重算。
好处:QPS 升 50%,带宽省 80%。
场景:API 返回用户列表,只 select id,name,age。
9. 自增 ID 为什么最好,UUID/雪花 ID 最烂?
主键用自增,避随机 ID。
解释:自增顺序追加,无页分裂;UUID 随机插队,树碎。
细节:InnoDB 页 16KB,上千条/页;自增连续 IO;UUID 页分裂,利用率 50%,写放大 2-3 倍。
好处:写 QPS 稳定,高并发插 10w/s。
场景:订单表日活 10w,用自增 id;分布式雪花别做聚簇主键。
10. 深分页优化:limit 999999,10 别硬扛
offset 越大越慢,先扫全丢前面的。
解释:改书签法或子查询覆盖。
细节:
- 方案 A:where id > 999999 order by id limit 10(自增 id 范围)。
- 方案 B:外层 where id in (内层 select id limit 999999,10)(内覆盖,只回 id)。
好处:从 10s 降 100ms,QPS 不崩。
场景:电商商品页,第 1000 页,书签法 + 覆盖索引。
11. 索引优化三句口头禅:实战铁律
写 SQL 前默念三句,避 80% 坑。
解释:① 区分高列左;② 覆盖频繁查列;③ 左连小驱动大。
细节:
- ① (user_id, status):user_id 唯一左,status 低右。
- ② select name,age where name=?:建 (name,age) 覆盖。
- ③ user 左 join order on id=user_id:order.user_id 索引,小表 user 驱动。
好处:查询 <1ms,维护简单。
场景:关联查询,user (1w) 左连 order (100w),加右索引。
12. InnoDB vs MyISAM:三句话分清
InnoDB 默认全能,MyISAM 读快粗糙。
解释:InnoDB 事务/行锁/聚簇;MyISAM 无事务/表锁/非聚簇。
细节:
- ① InnoDB ACID + 崩溃恢复;MyISAM 丢数据风险。
- ② InnoDB 数据+主键一起;MyISAM 地址分开。
- ③ InnoDB 写多;MyISAM 读多。
好处:InnoDB 99% 线上用,安全高并。
场景:银行转账 InnoDB;论坛日志 MyISAM。
13. 事务 ACID:怎么保证的?
事务 = 原子操作组,全成或全败。
解释:A 原子(undo log 回滚);C 一致(A+I+D);I 隔离(MVCC+锁);D 持久(redo log)。
细节:undo 存旧版(MVCC);redo WAL 先日志后盘。
好处:转账不丢钱,崩溃重启恢复。
场景:电商扣库存 + 加订单,一组 SQL。
14. 隔离级别 4 种:MySQL 默认 RR
从低到高:读未提交 > 读已提交 > 可重复读 > 串行化。
解释:未提交(脏读);已提交(不可重复);RR(幻读,MySQL 默认);串行(全锁)。
细节:RR 用 MVCC 读快照 + 间隙锁防幻;查 @@transaction_isolation。
好处:RR 平衡并发+安全,Oracle 默认已提交。
场景:读余额 RR(稳定);报告串行(全准)。
15. 脏读/不可重复/幻读:三坑分清
并发问题,隔离级别防。
解释:脏=读未提交假数据;重复=同一行变;幻=结果集行数变。
细节:脏 A 改未提交 B 读,回滚假;重复 A 读两次 B 中改;幻 A 查 count>1000,两次变行数。
好处:RR 基本全防,MVCC 旧版 + 间隙锁。
场景:转账脏读坑钱;库存幻读多卖。
16. MVCC:RR 隔离的"时间机器"
多版本并发控制,读旧版不锁。
解释:每行加隐藏列(事务 ID + 删除指针),改生成新版 undo log。
细节:读可见版本快照(根据事务 ID);当前读锁写。
好处:读写不互等,并发高。
场景:高读表,MVCC 0 锁读余额。
17. 锁分类:S/X + 行/表
共享 S(读,多人);排他 X(写,独占)。
解释:行锁 InnoDB(并发高);表锁 MyISAM(低)。
细节:S 兼容 S,不兼容 X;Next-Key = 行+间隙防幻。
好处:行锁 10 人并发改行互不等。
场景:更新库存行锁;清表锁。
18. 死锁:互等互持,怎么破?
A 等 B 锁,B 等 A 锁。
解释:InnoDB 自动检测,回滚一个(50s 超时)。
细节:高并发更新多列易死;解:统一加锁序 + 短事务。
好处:自愈,QPS 稳。
场景:转账 A 扣 B 加,死锁滚 A 重试。
19. undo/redo log:事务的双保险
undo 回滚,redo 恢复。
解释:undo 存旧版(原子+MVCC);redo WAL 先日志后盘(持久)。
细节:双写 buffer 防崩溃;binlog 复制用。
好处:掉电重启不丢,原子全。
场景:崩溃恢复 redo 重放。
20. 万能收尾:SQL 优化四关注
解释:① 覆盖索引?② 最左前缀?③ 函数/转换?④ explain ALL/temporary/filesort?
细节:覆盖 0 回表;前缀连续;函数失效;ALL 全扫改索引。
好处:线上 QPS 翻倍,维护易。
场景:慢 SQL 日志,先 explain 四查。