MySQL面试 八股文20道

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 四查。

相关推荐
Lgnazio42 分钟前
MYSQL数据库集群高可用和数据监控平台
数据库·mysql
白狐_79843 分钟前
基于 MySQL + MongoDB 的在线考试系统数据库设计与实现
数据库·mysql·mongodb
摘星编程1 小时前
openGauss DataVec向量数据库集成:面向AI应用的相似性搜索与知识图谱存储
数据库·人工智能·知识图谱
r***18641 小时前
FlinkCDC实战:将 MySQL 数据同步至 ES
android·mysql·elasticsearch
p***62991 小时前
mysql-connector-java 和 mysql-connector-j的区别
android·java·mysql
27669582921 小时前
最新 _rand 分析
前端·javascript·数据库·node·rand·231滑块·_rand分析
一 乐1 小时前
宠物医院预约|宠物医院|基于SprinBoot+vue的宠物医院预约管理系统源码+数据库+文档)
java·前端·数据库·vue.js·后端·springboot
蟹至之1 小时前
【MySQL】视图
数据库·mysql·视图
Fuly10241 小时前
langchain基础教程(6)---构建知识库--①向量数据库-chromadb
数据库·langchain